Exemplo n.º 1
0
static void
dissect_dsmcc_ddb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
            proto_tree *top_tree, guint offset)
{
    tvbuff_t   *sub_tvb;
    proto_item *pi;
    guint8		reserved;

    proto_tree_add_item(tree, hf_dsmcc_ddb_module_id, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;
    proto_tree_add_item(tree, hf_dsmcc_ddb_version, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset +=1;
    reserved = tvb_get_guint8(tvb, offset);
    pi = proto_tree_add_item(tree, hf_dsmcc_ddb_reserved, tvb,
        offset, 1, ENC_BIG_ENDIAN);
    if (0xff != reserved) {
        PROTO_ITEM_SET_GENERATED(pi);
        expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR,
                    "Invalid value - should be 0xff");
    }
    offset +=1;
    proto_tree_add_item(tree, hf_dsmcc_ddb_block_number, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    sub_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(data_handle, sub_tvb, pinfo, top_tree);
}
Exemplo n.º 2
0
guint
packet_mpeg_sect_crc(tvbuff_t *tvb, packet_info *pinfo,
             proto_tree *tree, guint start, guint end)
{
    guint32     crc, calculated_crc;
    const char *label;

    crc = tvb_get_ntohl(tvb, end);

    calculated_crc = crc;
    label = "Unverified";
    if (mpeg_sect_check_crc) {
        label = "Verified";
        calculated_crc = crc32_mpeg2_tvb_offset(tvb, start, end);
    }

    if (calculated_crc == crc) {
        proto_tree_add_uint_format( tree, hf_mpeg_sect_crc, tvb,
            end, 4, crc, "CRC: 0x%08x [%s]", crc, label);
    } else {
        proto_item *msg_error = NULL;

        msg_error = proto_tree_add_uint_format( tree, hf_mpeg_sect_crc, tvb,
                            end, 4, crc,
                            "CRC: 0x%08x [Failed Verification (Calculated: 0x%08x)]",
                            crc, calculated_crc );
        PROTO_ITEM_SET_GENERATED(msg_error);
        expert_add_info_format( pinfo, msg_error, PI_MALFORMED,
                    PI_ERROR, "Invalid CRC" );
    }

    return 4;
}
Exemplo n.º 3
0
static void
rtpproxy_add_notify_addr(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint end)
{
    gint offset = 0;
    gint tmp = 0;
    gboolean ipv6 = FALSE;
    proto_item *ti;

    /* Check for at least one colon */
    offset = tvb_find_guint8(tvb, begin, end, ':');
    if(offset != -1) {
        /* Find if it's the latest colon (not in case of a IPv6) */
        while((tmp = tvb_find_guint8(tvb, offset+1, end, ':')) != -1) {
            ipv6 = TRUE;
            offset = tmp;
        }
        /* We have ip:port */
        if(ipv6)
            proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv6, tvb, begin, offset - begin, ENC_ASCII | ENC_NA);
        else
            proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, offset - begin, ENC_ASCII | ENC_NA);
        proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, offset+1, end - (offset+1),
                            (guint16) g_ascii_strtoull((gchar*)tvb_get_string(wmem_packet_scope(), tvb, offset+1, end - (offset+1)), NULL, 10));
    }
    else {
        /* Only port is supplied */
        ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, 0, ENC_ASCII | ENC_NA);
        proto_item_append_text(ti, "<skipped>");
        PROTO_ITEM_SET_GENERATED(ti);
        proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, begin, end - begin,
                            (guint16) g_ascii_strtoull((gchar*)tvb_get_string(wmem_packet_scope(), tvb, begin, end - begin), NULL, 10));
    }
}
Exemplo n.º 4
0
/** General parsing function for arrays of enums.
 * All arrays have one 4 byte signed integer length information,
 * followed by n data elements.
 */
void parseArrayEnum(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, fctEnumParser pParserFunction)
{
    static const char szFieldName[] = "Array of Enum Type";
    proto_item *ti = proto_tree_add_text(tree, tvb, *pOffset, -1, "%s", szFieldName);
    proto_tree *subtree = proto_item_add_subtree(ti, ett_opcua_array);
    int i;
    gint32 iLen;

    /* read array length */
    iLen = tvb_get_letohl(tvb, *pOffset);
    proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN);

    if (iLen > MAX_ARRAY_LEN)
    {
        proto_item *pi;
        pi = proto_tree_add_text(tree, tvb, *pOffset, 4, "Array length %d too large to process", iLen);
        PROTO_ITEM_SET_GENERATED(pi);
        return;
    }

    *pOffset += 4;
    for (i=0; i<iLen; i++)
    {
        (*pParserFunction)(subtree, tvb, pOffset);
    }
    proto_item_set_end(ti, tvb, *pOffset);
}
Exemplo n.º 5
0
/** General parsing function for arrays of complex types.
 * All arrays have one 4 byte signed integer length information,
 * followed by n data elements.
 */
void parseArrayComplex(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, const char *szFieldName, fctComplexTypeParser pParserFunction)
{
    proto_item *ti = proto_tree_add_text(tree, tvb, *pOffset, -1, "Array of %s", szFieldName);
    proto_tree *subtree = proto_item_add_subtree(ti, ett_opcua_array);
    int i;
    gint32 iLen;

    /* read array length */
    iLen = tvb_get_letohl(tvb, *pOffset);
    proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN);

    if (iLen > MAX_ARRAY_LEN)
    {
        proto_item *pi;
        pi = proto_tree_add_text(tree, tvb, *pOffset, 4, "Array length %d too large to process", iLen);
        PROTO_ITEM_SET_GENERATED(pi);
        return;
    }

    *pOffset += 4;
    for (i=0; i<iLen; i++)
    {
        char szNum[20];
        g_snprintf(szNum, 20, "[%i]", i);
        (*pParserFunction)(subtree, tvb, pOffset, szNum);
    }
    proto_item_set_end(ti, tvb, *pOffset);
}
Exemplo n.º 6
0
/* Has storm request rate been exceeded with this request? */
static void check_for_storm_count(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  gboolean report_storm = FALSE;

  if (p_get_proto_data(pinfo->fd, proto_arp) != 0)
  {
    /* Read any previous stored packet setting */
    report_storm = (p_get_proto_data(pinfo->fd, proto_arp) == (void*)STORM);
  }
  else
  {
    /* Seeing packet for first time - check against preference settings */
    gint seconds_delta  = (gint) (pinfo->fd->abs_ts.secs - time_at_start_of_count.secs);
    gint nseconds_delta = pinfo->fd->abs_ts.nsecs - time_at_start_of_count.nsecs;
    gint gap = (seconds_delta*1000) + (nseconds_delta / 1000000);

    /* Reset if gap exceeds period or -ve gap (indicates we're rescanning from start) */
    if ((gap > (gint)global_arp_detect_request_storm_period) ||
        (gap < 0))
    {
      /* Time period elapsed without threshold being exceeded */
      arp_request_count = 1;
      time_at_start_of_count = pinfo->fd->abs_ts;
      p_add_proto_data(pinfo->fd, proto_arp, (void*)NO_STORM);
      return;
    }
    else
      if (arp_request_count > global_arp_detect_request_storm_packets)
      {
        /* Storm detected, record and reset start time. */
        report_storm = TRUE;
        p_add_proto_data(pinfo->fd, proto_arp, (void*)STORM);
        time_at_start_of_count = pinfo->fd->abs_ts;
      }
      else
      {
        /* Threshold not exceeded yet - no storm */
        p_add_proto_data(pinfo->fd, proto_arp, (void*)NO_STORM);
      }
  }

  if (report_storm)
  {
    /* Report storm and reset counter */
    proto_item *ti = proto_tree_add_none_format(tree, hf_arp_packet_storm, tvb, 0, 0,
                                                "Packet storm detected (%u packets in < %u ms)",
                                                global_arp_detect_request_storm_packets,
                                                global_arp_detect_request_storm_period);
    PROTO_ITEM_SET_GENERATED(ti);

    expert_add_info_format(pinfo, ti,
                           PI_SEQUENCE, PI_NOTE,
                           "ARP packet storm detected (%u packets in < %u ms)",
                           global_arp_detect_request_storm_packets,
                           global_arp_detect_request_storm_period);
    arp_request_count = 0;
  }
}
Exemplo n.º 7
0
/* Code to dissect a message block */
guint
dissect_moldudp_msgblk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        guint offset, guint32 sequence)
{
    proto_item *ti;
    proto_tree *blk_tree;
    guint16 msglen, real_msglen, whole_len;
    guint remaining;

    if (tvb_reported_length(tvb) - offset < MOLDUDP_MSGLEN_LEN)
        return 0;

    msglen = tvb_get_letohs(tvb, offset);
    remaining = tvb_reported_length(tvb) - offset - MOLDUDP_MSGLEN_LEN;

    if (msglen == 0)
        col_set_str(pinfo->cinfo, COL_INFO, "MoldUDP Messages (End Of Session)");

    if (tvb_reported_length(tvb) < (offset + MOLDUDP_MSGLEN_LEN))
        real_msglen = 0;
    else if (msglen <= remaining)
        real_msglen = msglen;
    else
        real_msglen = remaining;

    /* msglen and real_msglen only count the data section, and don't
     * include the two bytes for the length field itself. */
    whole_len = real_msglen + MOLDUDP_MSGLEN_LEN;

    ti = proto_tree_add_item(tree, hf_moldudp_msgblk,
            tvb, offset, whole_len, ENC_NA);

    blk_tree = proto_item_add_subtree(ti, ett_moldudp_msgblk);

    ti = proto_tree_add_uint(blk_tree, hf_moldudp_msgseq,
            tvb, offset, 0, sequence);

    PROTO_ITEM_SET_GENERATED(ti);

    ti = proto_tree_add_item(blk_tree, hf_moldudp_msglen,
            tvb, offset, MOLDUDP_MSGLEN_LEN, ENC_LITTLE_ENDIAN);

    if (msglen != real_msglen)
        expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
                "Invalid Message Length (claimed %u, found %u)",
                msglen, real_msglen);

    offset += MOLDUDP_MSGLEN_LEN;

    proto_tree_add_item(blk_tree, hf_moldudp_msgdata,
            tvb, offset, real_msglen, ENC_NA);

    return whole_len;
}
Exemplo n.º 8
0
static rtpproxy_info_t *
rtpproxy_add_tid(gboolean is_request, tvbuff_t *tvb, packet_info *pinfo, proto_tree *rtpproxy_tree, rtpproxy_conv_info_t *rtpproxy_conv, gchar* cookie)
{
    rtpproxy_info_t *rtpproxy_info;
    proto_item *pi;

    if (!PINFO_FD_VISITED(pinfo)) {
        if (is_request) {
            rtpproxy_info = wmem_new(wmem_file_scope(), rtpproxy_info_t);
            rtpproxy_info->req_frame = PINFO_FD_NUM(pinfo);
            rtpproxy_info->resp_frame = 0;
            rtpproxy_info->req_time = pinfo->fd->abs_ts;
            rtpproxy_info->callid = NULL;
            wmem_tree_insert_string(rtpproxy_conv->trans, cookie, rtpproxy_info, 0);
        } else {
            rtpproxy_info = (rtpproxy_info_t *)wmem_tree_lookup_string(rtpproxy_conv->trans, cookie, 0);
            if (rtpproxy_info) {
                rtpproxy_info->resp_frame = PINFO_FD_NUM(pinfo);
            }
        }
    } else {
        rtpproxy_info = (rtpproxy_info_t *)wmem_tree_lookup_string(rtpproxy_conv->trans, cookie, 0);
        if (rtpproxy_info && (is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame)) {
            nstime_t ns;

            pi = proto_tree_add_uint(rtpproxy_tree, is_request ? hf_rtpproxy_response_in : hf_rtpproxy_request_in, tvb, 0, 0, is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame);
            PROTO_ITEM_SET_GENERATED(pi);

            /* If reply then calculate response time */
            if (!is_request) {
                nstime_delta(&ns, &pinfo->fd->abs_ts, &rtpproxy_info->req_time);
                pi = proto_tree_add_time(rtpproxy_tree, hf_rtpproxy_response_time, tvb, 0, 0, &ns);
                PROTO_ITEM_SET_GENERATED(pi);
                if (nstime_cmp(&rtpproxy_timeout_ns, &ns) < 0)
                    expert_add_info_format(pinfo, rtpproxy_tree, &ei_rtpproxy_timeout, "Response timeout %.3f seconds", nstime_to_sec(&ns));
            }
        }
    }
    /* Could be NULL so we should check it before dereferencing */
    return rtpproxy_info;
}
Exemplo n.º 9
0
static int
dissect_device_list_response(packet_info *pinfo, proto_tree *tree,
                             tvbuff_t *tvb,
                             int offset)
{
    proto_item *ti_intf;
    proto_item *ti_dev;
    proto_tree *intf_tree = NULL;
    proto_tree *dev_tree = NULL;
    guint32 num_of_devs;
    guint32 i;
    guint8 num_of_intf;
    guint8 j;

    col_set_str(pinfo->cinfo, COL_INFO, "Device List Response");

    proto_tree_add_item_ret_uint(tree, hf_usbip_number_devices, tvb, offset, 4,
                                 ENC_BIG_ENDIAN, &num_of_devs);
    offset += 4;

    for (i = 0; i < num_of_devs; i++) {
        num_of_intf = tvb_get_guint8(tvb, offset + 0x137);
        ti_dev = proto_tree_add_uint(tree, hf_usbip_device, tvb, offset,
                                     0x138 + 4 * num_of_intf, i + 1);
        PROTO_ITEM_SET_GENERATED(ti_dev);

        dev_tree = proto_item_add_subtree(ti_dev, ett_usbip_dev);
        offset = dissect_device(dev_tree, tvb, offset);

        for (j = 0; j < num_of_intf; j++) {
            ti_intf = proto_tree_add_uint(dev_tree, hf_usbip_interface, tvb,
                                          offset, 3, j + 1);
            intf_tree = proto_item_add_subtree(ti_intf, ett_usbip_intf);

            proto_tree_add_item(intf_tree, hf_usbip_bInterfaceClass, tvb,
                                offset, 1, ENC_BIG_ENDIAN);
            offset += 1;

            proto_tree_add_item(intf_tree, hf_usbip_bInterfaceSubClass, tvb,
                                offset, 1, ENC_BIG_ENDIAN);
            offset += 1;

            proto_tree_add_item(intf_tree, hf_usbip_bInterfaceProtocol, tvb,
                                offset, 1, ENC_BIG_ENDIAN);
            offset += 1;

            proto_tree_add_item(intf_tree, hf_usbip_padding, tvb,
                                offset, 1, ENC_NA);
            offset += 1;
        }
    }
    return offset;
}
Exemplo n.º 10
0
void
expert_add_undecoded_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int length, const int severity)
{

	proto_item *expert_item; 

	expert_item = proto_tree_add_text(tree, tvb, offset, length, "Not dissected yet");

	expert_add_info_format(pinfo, expert_item, PI_UNDECODED, severity, "Not dissected yet(report to wireshark.org)"); \
	PROTO_ITEM_SET_GENERATED(expert_item); \

}
Exemplo n.º 11
0
static gint
dissect_hci_h4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    guint8             type;
    tvbuff_t          *next_tvb;
    proto_item        *main_item;
    proto_tree        *main_tree;
    proto_item        *sub_item;
    bluetooth_data_t  *bluetooth_data;

    bluetooth_data = (bluetooth_data_t *) data;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI H4");
    switch (pinfo->p2p_dir) {

    case P2P_DIR_SENT:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Sent ");
        break;

    case P2P_DIR_RECV:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Rcvd ");
        break;

    case P2P_DIR_UNKNOWN:
        break;

    default:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
                pinfo->p2p_dir);
        break;
    }

    type = tvb_get_guint8(tvb, 0);

    main_item = proto_tree_add_item(tree, proto_hci_h4, tvb, 0, 1, ENC_NA);
    main_tree = proto_item_add_subtree(main_item, ett_hci_h4);

    sub_item = proto_tree_add_uint(main_tree, hf_hci_h4_direction, tvb, 0, 0, pinfo->p2p_dir);
    PROTO_ITEM_SET_GENERATED(sub_item);

    proto_tree_add_item(main_tree, hf_hci_h4_type,
        tvb, 0, 1, ENC_LITTLE_ENDIAN);
    col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
            val_to_str(type, hci_h4_type_vals, "Unknown HCI packet type 0x%02x"));

    next_tvb = tvb_new_subset_remaining(tvb, 1);
    if (!dissector_try_uint_new(hci_h4_table, type, next_tvb, pinfo, tree, TRUE, bluetooth_data)) {
        call_dissector(data_handle, next_tvb, pinfo, tree);
    }

    return 1;
}
/* Code to dissect a message block */
guint
dissect_moldudp64_msgblk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        guint offset, guint64 sequence)
{
    proto_item *ti;
    proto_tree *blk_tree;
    guint16     msglen, real_msglen, whole_len;
    guint       remaining;

    if (tvb_length_remaining(tvb, offset) < MOLDUDP64_MSGLEN_LEN)
        return 0;

    msglen = tvb_get_ntohs(tvb, offset);
    remaining = tvb_reported_length(tvb) - offset - MOLDUDP64_MSGLEN_LEN;

    if (remaining < (offset + MOLDUDP64_MSGLEN_LEN))
        real_msglen = 0;
    else if (msglen <= remaining)
        real_msglen = msglen;
    else
        real_msglen = remaining;

    /* msglen and real_msglen only count the data section, and don't
     * include the two bytes for the length field itself. */
    whole_len = real_msglen + MOLDUDP64_MSGLEN_LEN;

    ti = proto_tree_add_item(tree, hf_moldudp64_msgblk,
            tvb, offset, whole_len, ENC_NA);

    blk_tree = proto_item_add_subtree(ti, ett_moldudp64_msgblk);

    ti = proto_tree_add_uint64(blk_tree, hf_moldudp64_msgseq,
            tvb, offset, 0, sequence);

    PROTO_ITEM_SET_GENERATED(ti);

    ti = proto_tree_add_item(blk_tree, hf_moldudp64_msglen,
            tvb, offset, MOLDUDP64_MSGLEN_LEN, ENC_BIG_ENDIAN);

    if (msglen != real_msglen)
        expert_add_info_format_text(pinfo, ti, &ei_moldudp64_msglen_invalid,
                "Invalid Message Length (claimed %u, found %u)",
                msglen, real_msglen);

    offset += MOLDUDP64_MSGLEN_LEN;

    proto_tree_add_item(blk_tree, hf_moldudp64_msgdata,
            tvb, offset, real_msglen, ENC_NA);

    return whole_len;
}
Exemplo n.º 13
0
static gint
rtpproxy_add_tag(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint realsize)
{
    proto_item *ti = NULL;
    proto_tree *another_tree = NULL;
    gint new_offset;
    guint end;

    new_offset = tvb_find_guint8(tvb, begin, -1, ' ');
    if(new_offset < 0)
        end = realsize; /* No more parameters */
    else
        end = new_offset;

    /* SER/OpenSER/OpenSIPS/Kamailio adds Media-ID right after the Tag
     * separated by a semicolon
     */
    new_offset = tvb_find_guint8(tvb, begin, end, ';');
    if(new_offset == -1) {
        ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, end - begin, ENC_ASCII | ENC_NA);
        another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag);
        ti = proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, 0, ENC_ASCII | ENC_NA);
        proto_item_append_text(ti, "<skipped>");
        PROTO_ITEM_SET_GENERATED(ti);
    }
    else {
        ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, new_offset - begin, ENC_ASCII | ENC_NA);
        if ((guint)new_offset == begin) {
            proto_item_append_text(ti, "<skipped>"); /* A very first Offer/Update command */
            PROTO_ITEM_SET_GENERATED(ti);
        }
        another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag);
        proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, end - (new_offset+1), ENC_ASCII | ENC_NA);
    }
    return (end == realsize ? -1 : (gint)end);
}
Exemplo n.º 14
0
static void
dissect_hci_h4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint8 type;
	tvbuff_t *next_tvb;
	proto_item *ti=NULL;
	proto_tree *hci_h4_tree=NULL;

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI H4");
	switch (pinfo->p2p_dir) {

	case P2P_DIR_SENT:
		col_add_fstr(pinfo->cinfo, COL_INFO, "Sent ");
		break;

	case P2P_DIR_RECV:
		col_add_fstr(pinfo->cinfo, COL_INFO, "Rcvd ");
		break;

	case P2P_DIR_UNKNOWN:
		break;

	default:
		col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
		    pinfo->p2p_dir);
		break;
	}

	type = tvb_get_guint8(tvb, 0);

	if(tree){
		ti = proto_tree_add_item(tree, proto_hci_h4, tvb, 0, 1, ENC_NA);
		hci_h4_tree = proto_item_add_subtree(ti, ett_hci_h4);
	}

	ti=proto_tree_add_uint(hci_h4_tree, hf_hci_h4_direction, tvb, 0, 0, pinfo->p2p_dir);
	PROTO_ITEM_SET_GENERATED(ti);

	proto_tree_add_item(hci_h4_tree, hf_hci_h4_type,
		tvb, 0, 1, ENC_LITTLE_ENDIAN);
	col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
			val_to_str(type, hci_h4_type_vals, "Unknown HCI packet type 0x%02x"));

	next_tvb = tvb_new_subset_remaining(tvb, 1);
	if(!dissector_try_uint(hci_h4_table, type, next_tvb, pinfo, tree)) {
		call_dissector(data_handle, next_tvb, pinfo, tree);
	}
}
Exemplo n.º 15
0
static int
dissect_kt_replication(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
{
    gint new_offset;
    guint32 next32, size;
    guint64 ts;
    nstime_t ns_ts;
    proto_item *pi;

    new_offset = offset;

    proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN);
    new_offset++;

    if (tvb_reported_length_remaining(tvb, new_offset) > 0) {
        next32 = tvb_get_ntohl(tvb, new_offset);
        if (next32 <= 1) { /* This means request. the 32 bits are flags */
            proto_tree_add_item(tree, hf_kt_flags, tvb, new_offset, 4, ENC_BIG_ENDIAN);
            new_offset += 4;

            proto_tree_add_item(tree, hf_kt_ts, tvb, new_offset, 8, ENC_BIG_ENDIAN);
            new_offset += 8;

            proto_tree_add_item(tree, hf_kt_sid, tvb, new_offset, 2, ENC_BIG_ENDIAN);
            new_offset += 2;
        } else { /* This is a response. The 32 bits are the first half of the ts */
            ts = tvb_get_ntoh64(tvb, new_offset);
            ns_ts.secs = (time_t)(ts/1000000000);
            ns_ts.nsecs = (int)(ts%1000000000);
            proto_tree_add_time(tree, hf_kt_ts, tvb, new_offset, 8, &ns_ts);
            new_offset += 8;

            size = tvb_get_ntohl(tvb, new_offset);
            proto_tree_add_uint(tree, hf_kt_size, tvb, new_offset, 4, size);
            new_offset += 4;

            proto_tree_add_item(tree, hf_kt_log, tvb, new_offset, size, ENC_NA);
            new_offset += size;
        }
    } else {
        /* This is an empty ack to the message with magic 0xB0. */
        pi = proto_tree_add_uint(tree, hf_kt_type, tvb, offset, 1, KT_OPER_RESPONSE);
        PROTO_ITEM_SET_GENERATED(pi);
        col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[response]");
    }

    return new_offset;
}
Exemplo n.º 16
0
void
dvb_add_chartbl(proto_tree *tree, int hf,
        tvbuff_t *tvb, gint offset, gint length, dvb_encoding_e encoding)
{
    if (length==0) {
        proto_item *pi;

        pi = proto_tree_add_bytes_format(tree, hf, tvb, 0, 0, NULL,
                "Default character table (Latin)");
        PROTO_ITEM_SET_GENERATED(pi);
    }
    else {
        proto_tree_add_bytes_format_value(tree, hf,
            tvb, offset, length, NULL, "%s (%s)",
            val_to_str_const(encoding, dvb_string_encoding_vals, "Unknown"),
            tvb_bytes_to_str_punct(wmem_packet_scope(), tvb, offset, length, ' '));
    }
}
Exemplo n.º 17
0
static int
dissect_corosync_totemnet_security_header(tvbuff_t *tvb,
                                          packet_info *pinfo, proto_tree *parent_tree,
                                          gboolean check_crypt_type,
                                          const gchar* key)
{
  proto_item *item;
  proto_tree *tree;

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "COROSYNC/TOTEMNET");
  col_clear(pinfo->cinfo, COL_INFO);

  if (parent_tree)
    {
      item = proto_tree_add_item(parent_tree, proto_corosync_totemnet, tvb, 0,
                                 -1, ENC_NA);
      tree = proto_item_add_subtree(item, ett_corosync_totemnet_security_header);

      proto_tree_add_item(tree,
                          hf_corosync_totemnet_security_header_hash_digest,
                          tvb, 0, SHA1_DIGEST_LEN, ENC_NA);
      proto_tree_add_item(tree,
                          hf_corosync_totemnet_security_header_salt,
                          tvb, SHA1_DIGEST_LEN, SALT_SIZE, ENC_NA);

      if (check_crypt_type)
        {
          int io_len = tvb_reported_length(tvb);
          proto_item * key_item;

          proto_tree_add_item(tree,
                              hf_corosync_totemnet_security_crypto_type,
                              tvb, io_len - 1, 1, ENC_BIG_ENDIAN);
          key_item = proto_tree_add_string(tree,
                                           hf_corosync_totemnet_security_crypto_key,
                                           tvb, 0, 0, key);
          PROTO_ITEM_SET_GENERATED(key_item);
        }
    }
  return SHA1_DIGEST_LEN + SALT_SIZE;
}
Exemplo n.º 18
0
static proto_tree*
expert_create_tree(proto_item *pi, int group, int severity, const char *msg)
{
	proto_tree *tree;
	proto_item *ti;

	tree = proto_item_add_subtree(pi, ett_expert);
	ti = proto_tree_add_protocol_format(tree, proto_expert, NULL, 0, 0, "Expert Info (%s/%s): %s",
					    val_to_str(severity, expert_severity_vals, "Unknown (%u)"),
					    val_to_str(group, expert_group_vals, "Unknown (%u)"),
					    msg);
	PROTO_ITEM_SET_GENERATED(ti);

	if (group == PI_MALFORMED) {
		/* Add hidden malformed protocol filter */
		proto_item *malformed_ti = proto_tree_add_item(tree, proto_malformed, NULL, 0, 0, ENC_NA);
		PROTO_ITEM_SET_HIDDEN(malformed_ti);
	}

	return proto_item_add_subtree(ti, ett_subexpert);
}
Exemplo n.º 19
0
/* Dissection routines */
static int
dissect_kt_replication_wait(tvbuff_t *tvb, proto_tree *tree)
{
    int offset;
    guint64 ts;
    nstime_t ns_ts;

    proto_item *pi;

    pi = proto_tree_add_uint(tree, hf_kt_type, tvb, 0, 1, KT_OPER_REQUEST);
    PROTO_ITEM_SET_GENERATED(pi);

    offset = 1;

    ts = tvb_get_ntoh64(tvb, offset);
    ns_ts.secs = (time_t)(ts/1000000000);
    ns_ts.nsecs = (int)(ts%1000000000);
    proto_tree_add_time(tree, hf_kt_ts, tvb, offset, 8, &ns_ts);
    offset += 8;

    return offset;
}
Exemplo n.º 20
0
static int
dissect_ret_unlink(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
                   int offset, usbip_conv_info_t *usbip_info,
                   guint32 seqnum)
{
    usbip_transaction_t *victim;

    col_set_str(pinfo->cinfo, COL_INFO, "URB Unlink Response");

    victim = (usbip_transaction_t *) wmem_tree_lookup32(usbip_info->pdus, seqnum);
    if (victim) {
        proto_item *ti;

        victim->ret_frame = pinfo->num;
        ti = proto_tree_add_uint(tree, hf_usbip_vic_frame, NULL, 0, 0,
                                 victim->cmd_frame);
        PROTO_ITEM_SET_GENERATED(ti);
    }
    proto_tree_add_item(tree, hf_usbip_status, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;
    return offset;
}
Exemplo n.º 21
0
/* ---------------------------------------------- */
static void
dissect_fix_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    /* Set up structures needed to add the protocol subtree and manage it */
    proto_item    *ti;
    proto_tree    *fix_tree;
    int            pdu_len;
    int            offset = 0;
    int            field_offset, ctrla_offset;
    int            tag_value;
    char          *value;
    char          *tag_str;
    fix_parameter *tag;

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

    /* get at least the fix version: 8=FIX.x.x */
    if (fix_marker(tvb, 0) != 0) {
        /* not a fix packet start but it's a fix packet */
        col_set_str(pinfo->cinfo, COL_INFO, "[FIX continuation]");
        ti = proto_tree_add_item(tree, proto_fix, tvb, 0, -1, ENC_NA);
        fix_tree = proto_item_add_subtree(ti, ett_fix);
        proto_tree_add_item(fix_tree, hf_fix_data, tvb, 0, -1, ENC_NA);
        return;
    }

    pdu_len = tvb_reported_length(tvb);
    ti = proto_tree_add_item(tree, proto_fix, tvb, 0, -1, ENC_NA);
    fix_tree = proto_item_add_subtree(ti, ett_fix);

    /* begin string */
    ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01);
    if (ctrla_offset == -1) {
        return;
    }
    offset = ctrla_offset + 1;

    /* msg length */
    ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01);
    if (ctrla_offset == -1) {
        return;
    }
    offset = ctrla_offset + 1;

    /* msg type */
    if (!(tag = fix_param(tvb, offset)) || tag->value_len < 1) {
        return;
    }

    if (check_col(pinfo->cinfo, COL_INFO)) {
        const char *msg_type;

        value = tvb_get_ephemeral_string(tvb, tag->value_offset, tag->value_len);
        msg_type = str_to_str(value, messages_val, "FIX Message (%s)");
        col_add_str(pinfo->cinfo, COL_INFO, msg_type);
    }

    /* In the interest of speed, if "tree" is NULL, don't do any work not
     * necessary to generate protocol tree items.
     */
    field_offset = 0;

    while(field_offset < pdu_len && (tag = fix_param(tvb, field_offset)) ) {
        int i, found;

        if (tag->tag_len < 1) {
            field_offset =  tag->ctrla_offset + 1;
            continue;
        }

        tag_str = tvb_get_ephemeral_string(tvb, field_offset, tag->tag_len);
        tag_value = atoi(tag_str);
        if (tag->value_len < 1) {
            proto_tree *field_tree;
            /* XXX - put an error indication here.  It's too late
               to return FALSE; we've already started dissecting,
               and if a heuristic dissector starts dissecting
               (either updating the columns or creating a protocol
               tree) and then gives up, it leaves crud behind that
               messes up other dissectors that might process the
               packet. */
            ti = proto_tree_add_text(fix_tree, tvb, field_offset, tag->field_len, "%i: <missing value>", tag_value);
            field_tree = proto_item_add_subtree(ti, ett_badfield);
            proto_tree_add_uint(field_tree, hf_fix_field_tag, tvb, field_offset, tag->tag_len, tag_value);
            field_offset =  tag->ctrla_offset + 1;
            continue;
        }

        /* fix_fields array is sorted by tag_value */
        found = 0;
        if ((i = tag_search(tag_value)) >= 0) {
            found = 1;
        }

        value = tvb_get_ephemeral_string(tvb, tag->value_offset, tag->value_len);
        if (found) {
            if (fix_fields[i].table) {
                if (tree) {
                    switch (fix_fields[i].type) {
                    case 1: /* strings */
                        proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value,
                            "%s (%s)", value, str_to_str(value, fix_fields[i].table, "unknown %s"));
                        break;
                    case 2: /* char */
                        proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value,
                            "%s (%s)", value, val_to_str(*value, fix_fields[i].table, "unknown %d"));
                        break;
                    default:
                        proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value,
                            "%s (%s)", value, val_to_str(atoi(value), fix_fields[i].table, "unknown %d"));
                        break;
                    }
                }
            }
            else {
              proto_item *item;

              /* checksum */
              switch(tag_value) {
              case 10:
                {
                    proto_tree *checksum_tree;
                    guint8 sum = 0;
                    const guint8 *data = tvb_get_ptr(tvb, 0, field_offset);
                    gboolean sum_ok;
                    int j;

                    for (j = 0; j < field_offset; j++, data++) {
                         sum += *data;
                    }
                    sum_ok = (atoi(value) == sum);
                    if (sum_ok) {
                        item = proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len,
                                value, "%s [correct]", value);
                    }
                    else {
                        item = proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len,
                                value, "%s [incorrect should be %d]", value, sum);
                    }
                    checksum_tree = proto_item_add_subtree(item, ett_checksum);
                    item = proto_tree_add_boolean(checksum_tree, hf_fix_checksum_good, tvb, field_offset, tag->field_len, sum_ok);
                    PROTO_ITEM_SET_GENERATED(item);
                    item = proto_tree_add_boolean(checksum_tree, hf_fix_checksum_bad, tvb, field_offset, tag->field_len, !sum_ok);
                    PROTO_ITEM_SET_GENERATED(item);
                    if (!sum_ok)
                        expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
                }
                break;
              default:
                proto_tree_add_string(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value);
                break;
              }
            }
        }
        else if (tree) {
          proto_tree *field_tree;

          /* XXX - it could be -1 if the tag isn't a number */
          ti = proto_tree_add_text(fix_tree, tvb, field_offset, tag->field_len, "%i: %s", tag_value, value);
          field_tree = proto_item_add_subtree(ti, ett_unknow);
          proto_tree_add_uint(field_tree, hf_fix_field_tag, tvb, field_offset, tag->tag_len, tag_value);
          proto_tree_add_item(field_tree, hf_fix_field_value, tvb, tag->value_offset, tag->value_len, ENC_ASCII|ENC_NA);
        }

        field_offset =  tag->ctrla_offset + 1;

        tag_str = NULL;
    }
    return;
}
Exemplo n.º 22
0
static ros_call_response_t *
ros_match_call_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint invokeId, gboolean isInvoke)
{
  ros_call_response_t rcr, *rcrp=NULL;
  ros_conv_info_t *ros_info = ros_info_items;

  /* first see if we have already matched this */

  rcr.invokeId=invokeId;
  rcr.is_request = isInvoke;

  if(isInvoke) {
    rcr.req_frame=pinfo->fd->num;
    rcr.rep_frame=0;
  } else {
    rcr.req_frame=0;
    rcr.rep_frame=pinfo->fd->num;
  }

  rcrp=(ros_call_response_t *)g_hash_table_lookup(ros_info->matched, &rcr);

  if(rcrp) {
    /* we have found a match */
    rcrp->is_request=rcr.is_request;

  } else {

    /* we haven't found a match - try and match it up */

    if(isInvoke) {
      /* this a a request - add it to the unmatched list */

      /* check that we dont already have one of those in the
	 unmatched list and if so remove it */

      rcr.invokeId=invokeId;

      rcrp=(ros_call_response_t *)g_hash_table_lookup(ros_info->unmatched, &rcr);

      if(rcrp){
	g_hash_table_remove(ros_info->unmatched, rcrp);
      }

      /* if we cant reuse the old one, grab a new chunk */
      if(!rcrp){
	rcrp=wmem_new(wmem_file_scope(), ros_call_response_t);
      }
      rcrp->invokeId=invokeId;
      rcrp->req_frame=pinfo->fd->num;
      rcrp->req_time=pinfo->fd->abs_ts;
      rcrp->rep_frame=0;
      rcrp->is_request=TRUE;
      g_hash_table_insert(ros_info->unmatched, rcrp, rcrp);
      return NULL;

    } else {

      /* this is a result - it should be in our unmatched list */

      rcr.invokeId=invokeId;
      rcrp=(ros_call_response_t *)g_hash_table_lookup(ros_info->unmatched, &rcr);

      if(rcrp){

	if(!rcrp->rep_frame){
	  g_hash_table_remove(ros_info->unmatched, rcrp);
	  rcrp->rep_frame=pinfo->fd->num;
	  rcrp->is_request=FALSE;
	  g_hash_table_insert(ros_info->matched, rcrp, rcrp);
	}
      }
    }
  }

  if(rcrp){ /* we have found a match */
    proto_item *item = NULL;

    if(rcrp->is_request){
      item=proto_tree_add_uint(tree, hf_ros_response_in, tvb, 0, 0, rcrp->rep_frame);
      PROTO_ITEM_SET_GENERATED (item);
    } else {
      nstime_t ns;
      item=proto_tree_add_uint(tree, hf_ros_response_to, tvb, 0, 0, rcrp->req_frame);
      PROTO_ITEM_SET_GENERATED (item);
      nstime_delta(&ns, &pinfo->fd->abs_ts, &rcrp->req_time);
      item=proto_tree_add_time(tree, hf_ros_time, tvb, 0, 0, &ns);
      PROTO_ITEM_SET_GENERATED (item);
    }
  }

  return rcrp;
}
Exemplo n.º 23
0
static void
dissect_v5dl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*v5dl_tree, *addr_tree;
	proto_item	*v5dl_ti, *addr_ti;
	int		direction;
	guint		v5dl_header_len;
	guint16		control;
#if 0
	proto_tree	*checksum_tree;
	proto_item	*checksum_ti;
	guint16		checksum, checksum_calculated;
	guint		checksum_offset;
#endif
	guint16		addr, cr, eah, eal, v5addr;
	gboolean	is_response = 0;
#if 0
	guint		length, reported_length;
#endif
	tvbuff_t	*next_tvb;
	const char	*srcname = "?";
	const char	*dstname = "?";

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

	addr = tvb_get_ntohs(tvb, 0);
	cr = addr & V5DL_CR;
	eal = (addr & V5DL_EAL) >> V5DL_EAL_SHIFT;
	eah = (addr & V5DL_EAH) >> V5DL_EAH_SHIFT;
	v5addr = (eah << 7) + eal;
	v5dl_header_len = 2;	/* addr */

	direction = pinfo->p2p_dir;
	if (pinfo->p2p_dir == P2P_DIR_RECV) {
	    is_response = cr ? FALSE : TRUE;
	    srcname = "Network";
	    dstname = "User";
	}
	else if (pinfo->p2p_dir == P2P_DIR_SENT) {
	    is_response = cr ? TRUE : FALSE;
	    srcname = "User";
	    dstname = "Network";
	}

	col_set_str(pinfo->cinfo, COL_RES_DL_SRC, srcname);
	col_set_str(pinfo->cinfo, COL_RES_DL_DST, dstname);

	if (tree) {
		proto_item *direction_ti;

		v5dl_ti = proto_tree_add_item(tree, proto_v5dl, tvb, 0, -1,
		    ENC_NA);
		v5dl_tree = proto_item_add_subtree(v5dl_ti, ett_v5dl);

		/*
		 * Don't show the direction if we don't know it.
		 */
		if (direction != P2P_DIR_UNKNOWN) {
			direction_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_direction,
			                                   tvb, 0, 0, pinfo->p2p_dir);
			PROTO_ITEM_SET_GENERATED(direction_ti);
		}

		addr_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_ef, tvb,
		    0, 2, v5addr);
		addr_tree = proto_item_add_subtree(addr_ti, ett_v5dl_address);
		proto_tree_add_uint(addr_tree, hf_v5dl_eah, tvb, 0, 1, addr);
		proto_tree_add_uint(addr_tree, hf_v5dl_cr,  tvb, 0, 1, addr);
		proto_tree_add_uint(addr_tree, hf_v5dl_ea1, tvb, 0, 1, addr);
		proto_tree_add_uint(addr_tree, hf_v5dl_eal, tvb, 1, 1, addr);
		proto_tree_add_uint(addr_tree, hf_v5dl_ea2, tvb, 1, 1, addr);
	}
	else {
		v5dl_ti = NULL;
		v5dl_tree = NULL;
	}

	control = dissect_xdlc_control(tvb, 2, pinfo, v5dl_tree, hf_v5dl_control,
	    ett_v5dl_control, &v5dl_cf_items, &v5dl_cf_items_ext, NULL, NULL,
	    is_response, TRUE, FALSE);
	v5dl_header_len += XDLC_CONTROL_LEN(control, TRUE);

	if (tree)
		proto_item_set_len(v5dl_ti, v5dl_header_len);

	/*
	 * XXX - the sample capture supplied with bug 7027 does not
	 * appear to include checksums in the packets.
	 */
#if 0
	/*
	 * Check the checksum, if available.
	 * The checksum is a CCITT CRC-16 at the end of the packet, so
	 * if we don't have the entire packet in the capture - i.e., if
	 * tvb_captured_length(tvb) != tvb_reported_length(tvb) we can't check it.
	 */
	length = tvb_captured_length(tvb);
	reported_length = tvb_reported_length(tvb);

	/*
	 * If the reported length isn't big enough for the V5DL header
	 * and 2 bytes of checksum, the packet is malformed, as the
	 * checksum overlaps the header.
	 */
	if (reported_length < v5dl_header_len + 2)
		THROW(ReportedBoundsError);

	if (length == reported_length) {
		/*
		 * There's no snapshot length cutting off any of the
		 * packet.
		 */
		checksum_offset = reported_length - 2;
		checksum = tvb_get_ntohs(tvb, checksum_offset);
		checksum_calculated = crc16_ccitt_tvb(tvb, checksum_offset);
		checksum_calculated = g_htons(checksum_calculated);  /* Note: g_htons() macro may eval arg multiple times */

		if (checksum == checksum_calculated) {
			checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset,
								 2, 0,
								 "0x%04x [correct]",
								 checksum);
			checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum);
			proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, TRUE);
			proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, FALSE);
		} else {
			checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset,
								 2, 0,
								 "0x%04x [incorrect, should be 0x%04x]",
								 checksum, checksum_calculated);
			checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum);
			proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, FALSE);
			proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, TRUE);
		}

		/*
		 * Remove the V5DL header *and* the checksum.
		 */
		next_tvb = tvb_new_subset(tvb, v5dl_header_len,
		    tvb_captured_length_remaining(tvb, v5dl_header_len) - 2,
		    tvb_reported_length_remaining(tvb, v5dl_header_len) - 2);
	} else {
		/*
		 * Some or all of the packet is cut off by a snapshot
		 * length.
		 */
		if (length == reported_length - 1) {
			/*
			 * One byte is cut off, so there's only one
			 * byte of checksum in the captured data.
			 * Remove that byte from the captured length
			 * and both bytes from the reported length.
			 */
			next_tvb = tvb_new_subset(tvb, v5dl_header_len,
			    tvb_captured_length_remaining(tvb, v5dl_header_len) - 1,
			    tvb_reported_length_remaining(tvb, v5dl_header_len) - 2);
		} else {
			/*
			 * Two or more bytes are cut off, so there are
			 * no bytes of checksum in the captured data.
			 * Just remove the checksum from the reported
			 * length.
			 */
			next_tvb = tvb_new_subset(tvb, v5dl_header_len,
			    tvb_captured_length_remaining(tvb, v5dl_header_len),
			    tvb_reported_length_remaining(tvb, v5dl_header_len) - 2);
		}
	}
#else
	next_tvb = tvb_new_subset_remaining(tvb, v5dl_header_len);
#endif

	if (XDLC_IS_INFORMATION(control)) {
		/* call V5.2 dissector */
	        call_dissector(v52_handle, next_tvb, pinfo, tree);
	}
}
Exemplo n.º 24
0
static void
dissect_zrtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_tree    *zrtp_tree;
  proto_tree    *zrtp_msg_tree;
  proto_tree    *zrtp_msg_data_tree;
  proto_tree    *checksum_tree;
  proto_item    *ti;
  int            linelen;
  int            checksum_offset;
  unsigned char  message_type[9];
  unsigned int   prime_offset = 0;
  unsigned int   msg_offset   = 12;
  guint32        sent_crc, calc_crc;

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

  col_set_str(pinfo->cinfo, COL_INFO, "Unknown ZRTP Packet");

  ti = proto_tree_add_protocol_format(tree, proto_zrtp, tvb, 0, -1, "ZRTP protocol");
  zrtp_tree = proto_item_add_subtree(ti, ett_zrtp);

  proto_tree_add_item(zrtp_tree, hf_zrtp_rtpversion, tvb, prime_offset+0, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(zrtp_tree, hf_zrtp_rtppadding, tvb, prime_offset+0, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(zrtp_tree, hf_zrtp_rtpextension, tvb, prime_offset+0, 1, ENC_BIG_ENDIAN);

  proto_tree_add_item(zrtp_tree, hf_zrtp_sequence, tvb, prime_offset+2, 2, ENC_BIG_ENDIAN);

  proto_tree_add_item(zrtp_tree, hf_zrtp_cookie, tvb, prime_offset+4, 4, ENC_ASCII|ENC_NA);

  proto_tree_add_item(zrtp_tree, hf_zrtp_source_id, tvb, prime_offset+8, 4, ENC_BIG_ENDIAN);

  linelen = tvb_reported_length_remaining(tvb, msg_offset);
  checksum_offset = linelen-4;

  ti = proto_tree_add_protocol_format(zrtp_tree, proto_zrtp, tvb, msg_offset, linelen-4, "Message");
  zrtp_msg_tree = proto_item_add_subtree(ti, ett_zrtp_msg);

  proto_tree_add_item(zrtp_msg_tree, hf_zrtp_signature, tvb, msg_offset+0, 2, ENC_BIG_ENDIAN);

  proto_tree_add_item(zrtp_msg_tree, hf_zrtp_msg_length, tvb, msg_offset+2, 2, ENC_BIG_ENDIAN);

  tvb_memcpy(tvb, (void *)message_type, msg_offset+4, 8);
  message_type[8] = '\0';
  proto_tree_add_item(zrtp_msg_tree, hf_zrtp_msg_type, tvb, msg_offset+4, 8, ENC_ASCII|ENC_NA);

  linelen = tvb_reported_length_remaining(tvb, msg_offset+12);

  if (!strncmp(message_type, "Hello   ", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_Hello(tvb, pinfo, zrtp_msg_data_tree);
  } else if (!strncmp(message_type, "HelloACK", 8)) {
    dissect_HelloACK(pinfo);
  } else if (!strncmp(message_type, "Commit  ", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_Commit(tvb, pinfo, zrtp_msg_data_tree);
  } else if (!strncmp(message_type, "DHPart1 ", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_DHPart(tvb, pinfo, zrtp_msg_data_tree, 1);
  } else if (!strncmp(message_type, "DHPart2 ", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_DHPart(tvb, pinfo, zrtp_msg_data_tree, 2);
  } else if (!strncmp(message_type, "Confirm1", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_Confirm(tvb, pinfo, zrtp_msg_data_tree, 1);
  } else if (!strncmp(message_type, "Confirm2", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_Confirm(tvb, pinfo, zrtp_msg_data_tree, 2);
  } else if (!strncmp(message_type, "Conf2ACK", 8)) {
    dissect_Conf2ACK(pinfo);
  } else if (!strncmp(message_type, "Error   ", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_Error(tvb, pinfo, zrtp_msg_data_tree);
  } else if (!strncmp(message_type, "ErrorACK", 8)) {
    dissect_ErrorACK(pinfo);
  } else if (!strncmp(message_type, "GoClear ", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_GoClear(tvb, pinfo, zrtp_msg_data_tree);
  } else if (!strncmp(message_type, "ClearACK", 8)) {
    dissect_ClearACK(pinfo);
  } else if (!strncmp(message_type, "SASrelay", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_SASrelay(tvb, pinfo, zrtp_msg_data_tree);
  } else if (!strncmp(message_type, "RelayACK", 8)) {
    dissect_RelayACK(pinfo);
  } else if (!strncmp(message_type, "Ping    ", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_Ping(tvb, pinfo, zrtp_msg_data_tree);
  } else if (!strncmp(message_type, "PingACK ", 8)) {
    ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
    zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
    dissect_PingACK(tvb, pinfo, zrtp_msg_data_tree);
  }

  sent_crc = tvb_get_ntohl(tvb, msg_offset+checksum_offset);
  calc_crc = ~crc32c_calculate(tvb_get_ptr(tvb, 0, msg_offset+checksum_offset), msg_offset+checksum_offset, CRC32C_PRELOAD);

  if (sent_crc == calc_crc) {
    ti = proto_tree_add_uint_format_value(zrtp_tree, hf_zrtp_checksum, tvb, msg_offset+checksum_offset, 4, sent_crc,
                                          "0x%04x [correct]", sent_crc);
    checksum_tree = proto_item_add_subtree(ti, ett_zrtp_checksum);
    ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_good,  tvb, msg_offset+checksum_offset, 4, TRUE);
    PROTO_ITEM_SET_GENERATED(ti);
    ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_bad,   tvb, msg_offset+checksum_offset, 4, FALSE);
    PROTO_ITEM_SET_GENERATED(ti);
  } else {
    ti = proto_tree_add_uint_format_value(zrtp_tree, hf_zrtp_checksum, tvb, msg_offset+checksum_offset, 4, sent_crc,
                                          "0x%04x [incorrect, should be 0x%04x]", sent_crc, calc_crc);
    checksum_tree = proto_item_add_subtree(ti, ett_zrtp_checksum);
    ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_good,  tvb, msg_offset+checksum_offset, 4, FALSE);
    PROTO_ITEM_SET_GENERATED(ti);
    ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_bad,   tvb, msg_offset+checksum_offset, 4, TRUE);
    PROTO_ITEM_SET_GENERATED(ti);
  }

}
Exemplo n.º 25
0
static void
dissect_etv_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto,
	int hf_filter_info, int hf_reserved )
{
	tvbuff_t   *sub_tvb;
	guint       offset = 0;
	proto_item *ti;
	proto_item *pi;
	proto_tree *etv_tree;
	proto_item *items[PACKET_MPEG_SECT_PI__SIZE];
	gboolean    ssi;
	guint       reserved;
	guint8      reserved2;
	guint16     filter_info;
	guint       sect_len;

	ti = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA);
	etv_tree = proto_item_add_subtree(ti, ett_etv);

	offset += packet_mpeg_sect_header_extra(tvb, offset, etv_tree, &sect_len,
						&reserved, &ssi, items);

	if (FALSE != ssi) {
		proto_item *msg_error;
		msg_error = items[PACKET_MPEG_SECT_PI__SSI];

		PROTO_ITEM_SET_GENERATED(msg_error);
		expert_add_info_format(pinfo, msg_error, PI_MALFORMED, PI_ERROR,
					"Invalid section_syntax_indicator (should be 0)");
	}

	if (4 != reserved) {
		proto_item *msg_error;
		msg_error = items[PACKET_MPEG_SECT_PI__RESERVED];

		PROTO_ITEM_SET_GENERATED(msg_error);
		expert_add_info_format(pinfo, msg_error, PI_MALFORMED, PI_ERROR,
					"Invalid reserved1 bits (should all be 100)");
	}

	col_append_fstr(pinfo->cinfo, COL_INFO, ", Length: %u", sect_len);
	proto_item_append_text(ti, " Length=%u", sect_len);
	if (1021 < sect_len) {
		proto_item *msg_error;
		msg_error = items[PACKET_MPEG_SECT_PI__LENGTH];

		PROTO_ITEM_SET_GENERATED(msg_error);
		expert_add_info_format(pinfo, msg_error, PI_MALFORMED, PI_ERROR,
					"Invalid section_length (must not exceed 1021)");
	}

	filter_info = tvb_get_ntohs(tvb, offset);
	col_append_fstr(pinfo->cinfo, COL_INFO, ", Filter: 0x%x", filter_info);
	proto_item_append_text(ti, " Filter=0x%x", filter_info);
	pi = proto_tree_add_item(etv_tree, hf_filter_info, tvb, offset, 2, ENC_BIG_ENDIAN);
	if ((proto_etv_dii == proto) && (0xFBFB != filter_info)) {
		PROTO_ITEM_SET_GENERATED(pi);
		expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR,
					"Invalid filter_info value (must be 0xFBFB)");
	} else if ((proto_etv_ddb == proto) &&
			((filter_info < 1) || (0xfbef < filter_info)))
	{
		PROTO_ITEM_SET_GENERATED(pi);
		expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR,
					"Invalid filter_info value (must be [0x0001-0xFBEF] inclusive)");
	}
	offset += 2;

	reserved2 = tvb_get_guint8(tvb, offset);
	pi = proto_tree_add_item(etv_tree, hf_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
	if (0 != reserved2) {
		PROTO_ITEM_SET_GENERATED(pi);
		expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR,
					"Invalid reserved2 bits (should all be 0)");
	}
	offset += 1;

	sub_tvb = tvb_new_subset(tvb, offset, sect_len-7, sect_len-7);
	call_dissector(dsmcc_handle, sub_tvb, pinfo, tree);

	sect_len += 3 - 4; /* add header, remove crc */

	packet_mpeg_sect_crc(tvb, pinfo, etv_tree, 0, sect_len);
}
Exemplo n.º 26
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(tftp_tree, hf_tftp_source_file,
                        tvb, offset, i1, ENC_ASCII|ENC_NA);

    tftp_info->source_file = tvb_get_string_enc(wmem_file_scope(), tvb, offset, i1, ENC_ASCII);
    /* 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(tftp_tree, hf_tftp_destination_file,
                        tvb, offset, i1, ENC_ASCII|ENC_NA);

    tftp_info->destination_file =
      tvb_get_string_enc(wmem_file_scope(), tvb, offset, i1, ENC_ASCII);
    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_dissector(data_handle, 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;

  }
}
Exemplo n.º 27
0
static void
dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint16     ar_hrd;
  guint16     ar_pro;
  guint8      ar_hln;
  guint8      ar_pln;
  guint16     ar_op;
  int         tot_len;
  proto_tree  *arp_tree = NULL;
  proto_item  *ti, *item;
  const gchar *op_str;
  int         sha_offset, spa_offset, tha_offset, tpa_offset;
  const guint8      *spa_val, *tpa_val;
  gboolean    is_gratuitous;
  gboolean    duplicate_detected = FALSE;
  guint32     duplicate_ip = 0;

  /* Call it ARP, for now, so that if we throw an exception before
     we decide whether it's ARP or RARP or IARP or ATMARP, it shows
     up in the packet list as ARP.

     Clear the Info column so that, if we throw an exception, it
     shows up as a short or malformed ARP frame. */
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
  col_clear(pinfo->cinfo, COL_INFO);

  /* Hardware Address Type */
  ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
  if (ar_hrd == ARPHRD_ATM2225) {
    call_dissector(atmarp_handle, tvb, pinfo, tree);
    return;
  }
  /* Protocol Address Type */
  ar_pro = tvb_get_ntohs(tvb, AR_PRO);
  /* Hardware Address Size */
  ar_hln = tvb_get_guint8(tvb, AR_HLN);
  /* Protocol Address Size */
  ar_pln = tvb_get_guint8(tvb, AR_PLN);
  /* Operation */
  ar_op  = tvb_get_ntohs(tvb, AR_OP);

  tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;

  /* Adjust the length of this tvbuff to include only the ARP datagram.
     Our caller may use that to determine how much of its packet
     was padding. */
  tvb_set_reported_length(tvb, tot_len);

  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
    switch (ar_op) {

      case ARPOP_REQUEST:
        if (global_arp_detect_request_storm)
        {
          request_seen(pinfo);
        }
	/* FALLTHRU */
      case ARPOP_REPLY:
      default:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
        break;

      case ARPOP_RREQUEST:
      case ARPOP_RREPLY:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
        break;

      case ARPOP_IREQUEST:
      case ARPOP_IREPLY:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
        break;
    }
  }

  /* Get the offsets of the addresses. */
  /* Source Hardware Address */
  sha_offset = MIN_ARP_HEADER_SIZE;
  /* Source Protocol Address */
  spa_offset = sha_offset + ar_hln;
  /* Target Hardware Address */
  tha_offset = spa_offset + ar_pln;
  /* Target Protocol Address */
  tpa_offset = tha_offset + ar_hln;

  if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
      ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
      ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {

    /* inform resolv.c module of the new discovered addresses */

    guint32 ip;
    const guint8 *mac;

    /* Add sender address if sender MAC address is neither a broadcast/
       multicast address nor an all-zero address and if sender IP address
       isn't all zeroes. */
    ip = tvb_get_ipv4(tvb, spa_offset);
    mac = tvb_get_ptr(tvb, sha_offset, 6);
    if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
    {
      add_ether_byip(ip, mac);
      if (global_arp_detect_duplicate_ip_addresses)
      {
        duplicate_detected =
          check_for_duplicate_addresses(pinfo, tree, tvb, mac, ip,
                                        &duplicate_ip);
      }
    }

    /* Add target address if target MAC address is neither a broadcast/
       multicast address nor an all-zero address and if target IP address
       isn't all zeroes. */

    /* Do not add target address if the packet is a Request. According to the RFC,
       target addresses in requests have no meaning */

    ip = tvb_get_ipv4(tvb, tpa_offset);
    mac = tvb_get_ptr(tvb, tha_offset, 6);
    if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0
        && ar_op != ARPOP_REQUEST)
    {
      add_ether_byip(ip, mac);
      if (global_arp_detect_duplicate_ip_addresses)
      {
        duplicate_detected =
          check_for_duplicate_addresses(pinfo, tree, tvb, mac, ip,
                                        &duplicate_ip);
      }
    }
  }

  if (!tree && !check_col(pinfo->cinfo, COL_INFO)) {
    /* We're not building a protocol tree and we're not setting the Info
       column, so we don't have any more work to do. */
    return;
  }

  spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
  tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);

  /* ARP requests/replies with the same sender and target protocol
     address are flagged as "gratuitous ARPs", i.e. ARPs sent out as,
     in effect, an announcement that the machine has MAC address
     XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY. Requests are to
     provoke complaints if some other machine has the same IPv4 address,
     replies are used to announce relocation of network address, like
     in failover solutions. */
  if (((ar_op == ARPOP_REQUEST) || (ar_op == ARPOP_REPLY)) && (memcmp(spa_val, tpa_val, ar_pln) == 0))
    is_gratuitous = TRUE;
  else
    is_gratuitous = FALSE;

  if (check_col(pinfo->cinfo, COL_INFO)) {
    switch (ar_op) {
      case ARPOP_REQUEST:
	if (is_gratuitous)
          col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Request)",
                       arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
	else
          col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
                       arpproaddr_to_str(tpa_val, ar_pln, ar_pro),
                       arpproaddr_to_str(spa_val, ar_pln, ar_pro));
        break;
      case ARPOP_REPLY:
        if (is_gratuitous)
          col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Reply)",
                       arpproaddr_to_str(spa_val, ar_pln, ar_pro));
        else
          col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
                       arpproaddr_to_str(spa_val, ar_pln, ar_pro),
                       tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd));
        break;
      case ARPOP_RREQUEST:
      case ARPOP_IREQUEST:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s?  Tell %s",
                     tvb_arphrdaddr_to_str(tvb, tha_offset, ar_hln, ar_hrd),
                     tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd));
        break;
      case ARPOP_RREPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
                     tvb_arphrdaddr_to_str(tvb, tha_offset, ar_hln, ar_hrd),
                     arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
        break;
      case ARPOP_IREPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
                     tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd),
                     arpproaddr_to_str(spa_val, ar_pln, ar_pro));
        break;
      default:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
        break;
    }
  }

  if (tree) {
    if ((op_str = match_strval(ar_op, op_vals)))  {
      if (is_gratuitous && (ar_op == ARPOP_REQUEST))
        op_str = "request/gratuitous ARP";
      if (is_gratuitous && (ar_op == ARPOP_REPLY))
        op_str = "reply/gratuitous ARP";
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "Address Resolution Protocol (%s)", op_str);
    } else
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "Address Resolution Protocol (opcode 0x%04x)", ar_op);
    arp_tree = proto_item_add_subtree(ti, ett_arp);
    proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
    proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
    proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
    proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
    proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);
    item = proto_tree_add_boolean(arp_tree, hf_arp_isgratuitous, tvb, 0, 0, is_gratuitous);
    PROTO_ITEM_SET_GENERATED(item);
    if (ar_hln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_HW_IS_ETHER(ar_hrd, ar_hln) ?
                          hf_arp_src_hw_mac :
                          hf_arp_src_hw,
                          tvb, sha_offset, ar_hln, FALSE);
    }
    if (ar_pln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_pln) ?
                          hf_arp_src_proto_ipv4 :
                          hf_arp_src_proto,
                          tvb, spa_offset, ar_pln, FALSE);
    }
    if (ar_hln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_HW_IS_ETHER(ar_hrd, ar_hln) ?
                          hf_arp_dst_hw_mac :
                          hf_arp_dst_hw,
                          tvb, tha_offset, ar_hln, FALSE);
    }
    if (ar_pln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_pln) ?
                          hf_arp_dst_proto_ipv4 :
                          hf_arp_dst_proto,
                          tvb, tpa_offset, ar_pln, FALSE);
    }
  }

  if (global_arp_detect_request_storm)
  {
    check_for_storm_count(tvb, pinfo, arp_tree);
  }

  if (duplicate_detected)
  {
    /* Also indicate in info column */
    if (check_col(pinfo->cinfo, COL_INFO))
    {
      col_append_fstr(pinfo->cinfo, COL_INFO, " (duplicate use of %s detected!)",
                      arpproaddr_to_str((guint8*)&duplicate_ip, 4, ETHERTYPE_IP));
    }
  }
}
Exemplo n.º 28
0
/* Check to see if this mac & ip pair represent 2 devices trying to share
   the same IP address - report if found (+ return TRUE and set out param) */
static gboolean check_for_duplicate_addresses(packet_info *pinfo, proto_tree *tree,
                                              tvbuff_t *tvb,
                                              const guint8 *mac, guint32 ip,
                                              guint32 *duplicate_ip)
{
  struct   address_hash_value *value;
  gboolean return_value = FALSE;

  /* Look up any existing entries */
  value = g_hash_table_lookup(address_hash_table, GUINT_TO_POINTER(ip));

  /* If MAC matches table, just update details */
  if (value != NULL)
  {
    if (pinfo->fd->num > value->frame_num)
    {
      if ((memcmp(value->mac, mac, 6) == 0))
      {
        /* Same MAC as before - update existing entry */
        value->frame_num = pinfo->fd->num;
        value->time_of_entry = pinfo->fd->abs_ts.secs;
      }
      else
      {
        /* Doesn't match earlier MAC - report! */
        proto_tree *duplicate_tree;

        /* Create subtree */
        proto_item *ti = proto_tree_add_none_format(tree, hf_arp_duplicate_ip_address,
                                                    tvb, 0, 0,
                                                    "Duplicate IP address detected for %s (%s) - also in use by %s (frame %u)",
                                                    arpproaddr_to_str((guint8*)&ip, 4, ETHERTYPE_IP),
                                                    ether_to_str(mac),
                                                    ether_to_str(value->mac),
                                                    value->frame_num);
        PROTO_ITEM_SET_GENERATED(ti);
        duplicate_tree = proto_item_add_subtree(ti, ett_arp_duplicate_address);

        /* Add item for navigating to earlier frame */
        ti = proto_tree_add_uint(duplicate_tree, hf_arp_duplicate_ip_address_earlier_frame,
                                 tvb, 0, 0, value->frame_num);
        PROTO_ITEM_SET_GENERATED(ti);
        expert_add_info_format(pinfo, ti,
                               PI_SEQUENCE, PI_WARN,
                               "Duplicate IP address configured (%s)",
                               arpproaddr_to_str((guint8*)&ip, 4, ETHERTYPE_IP));

        /* Time since that frame was seen */
        ti = proto_tree_add_uint(duplicate_tree,
                                 hf_arp_duplicate_ip_address_seconds_since_earlier_frame,
                                 tvb, 0, 0,
                                 (guint32)(pinfo->fd->abs_ts.secs - value->time_of_entry));
        PROTO_ITEM_SET_GENERATED(ti);

        *duplicate_ip = ip;
        return_value = TRUE;
      }
    }
  }
  else
  {
    /* No existing entry. Prepare one */
    value = se_alloc(sizeof(struct address_hash_value));
    memcpy(value->mac, mac, 6);
    value->frame_num = pinfo->fd->num;
    value->time_of_entry = pinfo->fd->abs_ts.secs;

    /* Add it */
    g_hash_table_insert(address_hash_table, GUINT_TO_POINTER(ip), value);
  }

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

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

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

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

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

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

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

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

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

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

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

    if (has_fcs) {
      guint32 sent_fcs = tvb_get_ntohl(trailer_tvb, padding_length+trailer_length);
      if(eth_check_fcs){
        guint32 fcs = crc32_802_tvb(tvb, tvb_length(tvb) - 4);
        if (fcs == sent_fcs) {
          item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb,
                                            padding_length+trailer_length, 4, sent_fcs,
                                            "Frame check sequence: 0x%08x [correct]", sent_fcs);
          checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                        padding_length+trailer_length, 4, TRUE);
          PROTO_ITEM_SET_GENERATED(item);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                        padding_length+trailer_length, 4, FALSE);
          PROTO_ITEM_SET_GENERATED(item);
        } else {
          item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb,
                                            padding_length+trailer_length, 4, sent_fcs,
                                            "Frame check sequence: 0x%08x [incorrect, should be 0x%08x]",
                                            sent_fcs, fcs);
          checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                        padding_length+trailer_length, 4, FALSE);
          PROTO_ITEM_SET_GENERATED(item);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                        padding_length+trailer_length, 4, TRUE);
          PROTO_ITEM_SET_GENERATED(item);
          expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
          col_append_str(pinfo->cinfo, COL_INFO, " [ETHERNET FRAME CHECK SEQUENCE INCORRECT]");
        }
      }else{
        item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb,
                                          padding_length+trailer_length, 4, sent_fcs,
                                          "Frame check sequence: 0x%08x [validiation disabled]", sent_fcs);
        checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
        item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                      padding_length+trailer_length, 4, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
        item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                      padding_length+trailer_length, 4, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
      }
      trailer_length += 4;
    }
    proto_tree_set_appendix(fh_tree, tvb, tvb_length(tvb) - padding_length - trailer_length, padding_length + trailer_length);
  }
}