예제 #1
0
static int dissect_pbb_header(tvbuff_t *tvb, proto_tree *tree) {
  proto_tree *header_tree = NULL;
  proto_tree *headerFlags_tree = NULL;

  proto_item *header_item = NULL;
  proto_item *headerFlags_item = NULL;

  guint8 packet_flags;
  guint headerLength = 1;
  guint tlvIndex = 0;

  /* calculate header length */
  packet_flags = tvb_get_guint8(tvb, 0);
  if ((packet_flags & PACKET_HEADER_HASSEQNR) != 0) {
    headerLength += 2;
  }
  if ((packet_flags & PACKET_HEADER_HASTLV) != 0) {
    tlvIndex = headerLength;
    headerLength += 2;
  }

  if (tvb_reported_length(tvb) < headerLength) {
    proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, 0, -1,
        tvb_get_ptr(tvb, 0, -1), "Not enough octets for packetbb header");
    return tvb_reported_length(tvb);
  }
  if ((packet_flags & PACKET_HEADER_HASTLV) != 0) {
    headerLength += tvb_get_ntohs(tvb, tlvIndex);
  }
  if (tvb_reported_length(tvb) < headerLength) {
    proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, 0, -1,
        tvb_get_ptr(tvb, 0, -1), "Not enough octets for packetbb tlvblock");
    return tvb_reported_length(tvb);
  }

  header_item = proto_tree_add_item(tree, hf_packetbb_header, tvb, 0, headerLength, FALSE);
  header_tree = proto_item_add_subtree(header_item, ett_packetbb_header);

  /* version */
  proto_tree_add_uint(header_tree, hf_packetbb_version, tvb, 0, 1, packet_flags >> 4);

  /* flags */
  headerFlags_item = proto_tree_add_uint(header_tree, hf_packetbb_header_flags,
      tvb, 0, 1, packet_flags & 0x0f);

  headerFlags_tree = proto_item_add_subtree(headerFlags_item, ett_packetbb_header_flags);
  proto_tree_add_boolean(headerFlags_tree, hf_packetbb_header_flags_phasseqnum, tvb, 0, 1, packet_flags);
  proto_tree_add_boolean(headerFlags_tree, hf_packetbb_header_flags_phastlv, tvb, 0, 1, packet_flags);

  /* sequence number */
  if ((packet_flags & PACKET_HEADER_HASSEQNR) != 0) {
    proto_tree_add_item(header_tree, hf_packetbb_seqnr, tvb, 1, 2, FALSE);
  }

  if ((packet_flags & PACKET_HEADER_HASTLV) != 0) {
    return dissect_pbb_tlvblock(tvb, tree, tlvIndex, tvb_reported_length(tvb), 0);
  }
  return headerLength;
}
예제 #2
0
/**
 * dissect_messageid is a utility function which
 * calculates the ID of the message.
 *
 * @see dissect_packetid()
 * @see dissect_reliable_message_index_base()
 * @see dissect_content_length()
 * @see dissect_reliable_message_number()
 * @see dissect_payload()
 * @param buffer the buffer to the data
 * @param offset the offset where to start reading the data
 * @param tree the parent tree where the dissected data is going to be inserted
 * @return int returns the messageid
 *
 */
static int
dissect_messageid(tvbuff_t *buffer, int *offset, proto_tree *tree, packet_info *pinfo, emem_strbuf_t* info_field)
{
    gint   messageid_length;
    guint8 messageid;

    messageid = tvb_get_bits8(buffer, (*offset) * 8, 8);

    switch(messageid)
    {
        case DISCONNECT:
        case DISCONNECTACK:
        case CONNECTSYN:
        case CONNECTSYNACK:
        case CONNECTACK:
            messageid_length = 4;
        break;
        default:
            messageid_length = 1;
        break;
    }

    proto_tree_add_bytes_format(tree, hf_knet_messageid, buffer, *offset, messageid_length, NULL,
    "Message ID: %s (%d)", val_to_str_const(messageid, packettypenames, "AppData or Malformed Message ID"), messageid);

    col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(messageid, packettypenames, "AppData "));

    *offset += messageid_length;

    ep_strbuf_append_printf(info_field, "Msg ID (%d) ", messageid);

    return messageid;
}
static void
dissect_hello_restart_clv(tvbuff_t *tvb,
                          proto_tree *tree, int offset, int id_length, int length)
{
    int restart_options=0;
    proto_tree *flags_tree;
    proto_item *restart_flags_item;
    proto_item *hold_time_item;
    const char *sep;
    const guint8 *neighbor_id;

    if (length >= 1) {
        restart_options = tvb_get_guint8(tvb, offset);
        restart_flags_item = proto_tree_add_uint ( tree, hf_isis_hello_clv_restart_flags,
                             tvb, offset, 1, restart_options);
        flags_tree = proto_item_add_subtree(restart_flags_item, ett_isis_hello_clv_restart_flags);
        proto_tree_add_boolean (flags_tree, hf_isis_hello_clv_restart_flags_sa,
                                tvb, offset, 1, restart_options );
        proto_tree_add_boolean (flags_tree, hf_isis_hello_clv_restart_flags_ra,
                                tvb, offset, 1, restart_options );
        proto_tree_add_boolean (flags_tree, hf_isis_hello_clv_restart_flags_rr,
                                tvb, offset, 1, restart_options );

        /* Append an indication of which flags are set in the restart
         * options
         */
        sep = initial_sep;
        APPEND_BOOLEAN_FLAG(ISIS_MASK_RESTART_SA(restart_options), restart_flags_item, "%sSA");
        APPEND_BOOLEAN_FLAG(ISIS_MASK_RESTART_RA(restart_options), restart_flags_item, "%sRA");
        APPEND_BOOLEAN_FLAG(ISIS_MASK_RESTART_RR(restart_options), restart_flags_item, "%sRR");
        if (sep != initial_sep)
        {
            proto_item_append_text (restart_flags_item, ")");
        }

    }

    /* The Remaining Time field should only be present if the RA flag is
     * set
     */
    if (length >= 3 && ISIS_MASK_RESTART_RA(restart_options)) {
        hold_time_item = proto_tree_add_uint ( tree, hf_isis_hello_clv_restart_remain_time,
                                               tvb, offset+1, 2, tvb_get_ntohs(tvb, offset+1) );
        proto_item_append_text( hold_time_item, "s" );
    }

    /* The Restarting Neighbor ID should only be present if the RA flag is
     * set.
     */
    if (length >= 3 + id_length && ISIS_MASK_RESTART_RA(restart_options)) {
        neighbor_id = tvb_get_ptr(tvb, offset+3, id_length);
        proto_tree_add_bytes_format( tree,
                                     hf_isis_hello_clv_restart_neighbor, tvb, offset+3,
                                     id_length, neighbor_id, "Restarting Neighbor ID: %s",
                                     print_system_id( neighbor_id, id_length ) );
    }
}
예제 #4
0
/** Dissect the Tag Packet Layer.
 *  Split the AF packet into its tag items. Each tag item has a 4 character
 *  tag, a length in bits and a value. The *ptr tag is dissected in the routine.
 *  All other tags are listed and may be handled by other dissectors.
 *  Child dissectors are tied to the parent tree, not to this tree, so that
 *  they appear at the same level as DCP.
 *  \param[in,out] tvb The buffer containing the packet
 *  \param[in,out] pinfo The packet info structure
 *  \param[in,out] tree The structure containing the details which will be displayed, filtered, etc.
 */
static void
dissect_tpl(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{
  proto_tree *tpl_tree = NULL;
  guint offset=0;
  char *prot=NULL;
  guint16 maj, min;

  pinfo->current_proto = "DCP-TPL";
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCP-TPL");

  if(tree) {
    proto_item *ti = NULL;
    ti = proto_tree_add_item (tree, proto_tpl, tvb, 0, -1, FALSE);
    tpl_tree = proto_item_add_subtree (ti, ett_tpl);
  }
  while(offset<tvb_length(tvb)) {
    guint32 bits;
    guint32 bytes;
    char *tag = (char*)tvb_get_ephemeral_string (tvb, offset, 4); offset += 4;
    bits = tvb_get_ntohl(tvb, offset); offset += 4;
    bytes = bits / 8;
    if(bits % 8)
      bytes++;
    if(tree) {
      proto_item *i = NULL;
      const guint8 *p = tvb_get_ptr(tvb, offset, bytes);
      if(strcmp(tag, "*ptr")==0) {
        prot = (char*)tvb_get_ephemeral_string (tvb, offset, 4);
        maj = tvb_get_ntohs(tvb, offset+4);
        min = tvb_get_ntohs(tvb, offset+6);
        i = proto_tree_add_bytes_format(tpl_tree, hf_tpl_tlv, tvb,
              offset-8, bytes+8, p, "%s %s rev %d.%d", tag, prot, maj, min);
      } else {
        i = proto_tree_add_bytes_format(tpl_tree, hf_tpl_tlv, tvb,
              offset-8, bytes+8, p, "%s (%u bits)", tag, bits);
      }
    }
    offset += bytes;
  }
  if(prot) {  /* prot is non-NULL only if we have our tree. */
    dissector_try_string(tpl_dissector_table, prot, tvb, pinfo, tree->parent);
  }
}
예제 #5
0
static gint
dissect_om2k_attr_unkn(tvbuff_t *tvb, gint offset, gint len, gint iei, proto_tree *tree)
{
	proto_tree_add_bytes_format(tree, hf_om2k_unknown_val, tvb,
				    offset, len, NULL,
				    "%s: %s",
				    val_to_str_ext(iei, &om2k_attr_vals_ext, "0x%02x"),
				    tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, len));
	return len;
}
예제 #6
0
static void
decode_iei_ns_pdu(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
  tvbuff_t * next_tvb;

  proto_tree_add_bytes_format(bi->nsip_tree, hf_nsip_ns_pdu, bi->tvb, ie_start_offset,
                      ie->total_length, NULL,
                      "NS PDU (%u bytes)", ie->value_length);
  next_tvb = tvb_new_subset(bi->tvb, bi->offset, ie->value_length, -1);
  if (nsip_handle) {
    gboolean was_recursive;
    was_recursive = nsip_is_recursive;
    nsip_is_recursive = TRUE;
    call_dissector(nsip_handle, next_tvb, bi->pinfo, bi->nsip_tree);
    nsip_is_recursive = was_recursive;
  }
  bi->offset += ie->value_length;
}
예제 #7
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, ' '));
    }
}
예제 #8
0
/**
 * dissect_payload is a utility function which
 * calculates the actual payload of the message.
 *
 * @see dissect_packetid()
 * @see dissect_reliable_message_index_base()
 * @see dissect_content_length()
 * @see dissect_reliable_message_number()
 * @see dissect_messageid()
 * @param buffer the buffer to the data
 * @param offset the offset where to start reading the data
 * @param messageid the messageid of the received message
 * @param tree the parent tree where the dissected data is going to be inserted
 * @param content_length the content length of the payload
 * @return int returns 0 at the moment
 *
 */
static int
dissect_payload(tvbuff_t *buffer, int offset, int messageid, proto_tree *tree, int content_length)
{
    proto_item *payload_ti;
    proto_tree *payload_tree;

    payload_ti   = proto_tree_add_item(tree, hf_knet_payload_tree, buffer, offset, content_length - 1, ENC_NA);
    payload_tree = proto_item_add_subtree(payload_ti, ett_knet_payload);

    switch(messageid)
    {
        case PINGREQUEST:
        case PINGREPLY:
            proto_tree_add_item(payload_tree, hf_knet_pingid, buffer, offset, 1, ENC_LITTLE_ENDIAN);
        break;
        case FLOWCONTROLREQUEST:
            proto_tree_add_item(payload_tree, hf_knet_flowctrlreq, buffer, offset, 3, ENC_LITTLE_ENDIAN);
        break;
        case PACKETACK:
            proto_tree_add_item(payload_tree, hf_knet_packetack, buffer, offset, 3, ENC_LITTLE_ENDIAN);
            offset += 3;
            proto_tree_add_item(payload_tree, hf_knet_seqnumber, buffer, offset, 4, ENC_LITTLE_ENDIAN);
        break;
        case DISCONNECT:    /*No payload*/
        case DISCONNECTACK: /*No payload*/
            proto_tree_add_bytes_format(payload_tree, hf_knet_payload, buffer, offset, 0, NULL, "No Payload");
        break;
        case CONNECTSYN:    /*TODO: Not yet implemented, implement when available*/
        case CONNECTSYNACK: /*TODO: Not yet implemented, implement when available*/
        case CONNECTACK:    /*TODO: Not yet implemented, implement when available*/
            proto_tree_add_item(payload_tree, hf_knet_payload, buffer, offset, content_length-1, ENC_NA);
        break;
        default: /* Application Specific Message */
            proto_tree_add_item(payload_tree, hf_knet_payload, buffer, offset, content_length-1, ENC_NA);
        break;
    }

    return 0;
}
예제 #9
0
/* Parse Short Message, only if UDH present
 * (otherwise this function is not called).
 * Call WSP dissector if port matches WSP traffic.
 */
static void
parse_gsm_sms_ud_message(proto_tree *sm_tree, tvbuff_t *tvb, packet_info *pinfo,
        proto_tree *top_tree)
{
    tvbuff_t      *sm_tvb                    = NULL;
    proto_item    *ti;
    proto_tree    *subtree, *tree;
    guint8         udh_len, udh, len;
    guint          sm_len                    = tvb_reported_length(tvb);
    guint          sm_data_len;
    guint32        i                         = 0;
    /* Multiple Messages UDH */
    gboolean       is_fragmented             = FALSE;
    fragment_head *fd_sm                     = NULL;
    guint16        sm_id                     = 0;
    guint16        frags                     = 0;
    guint16        frag                      = 0;
    gboolean       save_fragmented           = FALSE;
    gboolean       try_gsm_sms_ud_reassemble = FALSE;
    /* SMS Message reassembly */
    gboolean       reassembled               = FALSE;
    guint32        reassembled_in            = 0;
    /* Port Number UDH */
    guint16        p_src                     = 0;
    guint16        p_dst                     = 0;
    gboolean       ports_available           = FALSE;

    udh_len = tvb_get_guint8(tvb, i++);
    ti   = proto_tree_add_uint(sm_tree, hf_gsm_sms_udh_length, tvb, 0, 1, udh_len);
    tree = proto_item_add_subtree(ti, ett_udh);
    while (i < udh_len) {
        udh = tvb_get_guint8(tvb, i++);
        len = tvb_get_guint8(tvb, i++);
        subtree = proto_tree_add_uint(tree, hf_gsm_sms_udh_iei,
                tvb, i-2, 2+len, udh);
        switch (udh) {
            case 0x00: /* Multiple messages - 8-bit message ID */
                if (len == 3) {
                    sm_id = tvb_get_guint8(tvb, i++);
                    frags = tvb_get_guint8(tvb, i++);
                    frag  = tvb_get_guint8(tvb, i++);
                    if (frags > 1)
                        is_fragmented = TRUE;
                    proto_item_append_text(subtree,
                            ": message %u, part %u of %u", sm_id, frag, frags);
                    subtree = proto_item_add_subtree(subtree,
                            ett_udh_ie);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_id,
                            tvb, i-3, 1, sm_id);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_parts,
                            tvb, i-2, 1, frags);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_part,
                            tvb, i-1, 1, frag);
                } else {
                    proto_item_append_text(subtree, " - Invalid format!");
                    i += len;
                }
                break;

            case 0x08: /* Multiple messages - 16-bit message ID */
                if (len == 4) {
                    sm_id = tvb_get_ntohs(tvb, i); i += 2;
                    frags = tvb_get_guint8(tvb, i++);
                    frag  = tvb_get_guint8(tvb, i++);
                    if (frags > 1)
                        is_fragmented = TRUE;
                    proto_item_append_text(subtree,
                            ": message %u, part %u of %u", sm_id, frag, frags);
                    subtree = proto_item_add_subtree(subtree,
                            ett_udh_ie);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_id,
                            tvb, i-4, 2, sm_id);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_parts,
                            tvb, i-2, 1, frags);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_part,
                            tvb, i-1, 1, frag);
                } else {
                    proto_item_append_text(subtree, " - Invalid format!");
                    i += len;
                }
                break;

            case 0x04: /* Port Number UDH - 8-bit address */
                if (len == 2) { /* Port fields */
                    p_dst = tvb_get_guint8(tvb, i++);
                    p_src = tvb_get_guint8(tvb, i++);
                    proto_item_append_text(subtree,
                            ": source port %u, destination port %u",
                            p_src, p_dst);
                    subtree = proto_item_add_subtree(subtree, ett_udh_ie);
                    proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_dst,
                            tvb, i-2, 1, p_dst);
                    proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_src,
                            tvb, i-1, 1, p_src);
                    ports_available = TRUE;
                } else {
                    proto_item_append_text(subtree, " - Invalid format!");
                    i += len;
                }
                break;

            case 0x05: /* Port Number UDH - 16-bit address */
                if (len == 4) { /* Port fields */
                    p_dst = tvb_get_ntohs(tvb, i); i += 2;
                    p_src = tvb_get_ntohs(tvb, i); i += 2;
                    proto_item_append_text(subtree,
                            ": source port %u, destination port %u",
                            p_src, p_dst);
                    subtree = proto_item_add_subtree(subtree, ett_udh_ie);
                    proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_dst,
                            tvb, i-4, 2, p_dst);
                    proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_src,
                            tvb, i-2, 2, p_src);
                    ports_available = TRUE;
                } else {
                    proto_item_append_text(subtree, " - Invalid format!");
                    i += len;
                }
                break;

            default:
                i += len;
                break;
        }
    }
    if (tvb_reported_length_remaining(tvb, i) <= 0)
        return; /* No more data */

    /*
     * XXX - where does the "1" come from?  If it weren't there,
     * "sm_data_len" would, I think, be the same as
     * "tvb_reported_length_remaining(tvb, i)".
     *
     * I think that the above check ensures that "sm_len" won't
     * be less than or equal to "udh_len", so it ensures that
     * "sm_len" won't be less than "1 + udh_len", so we don't
     * have to worry about "sm_data_len" being negative.
     */
    sm_data_len = sm_len - (1 + udh_len);
    if (sm_data_len == 0)
        return; /* no more data */

    /*
     * Try reassembling the packets.
     * XXX - fragment numbers are 1-origin, but the fragment number
     * field could be 0.
     * Should we flag a fragmented message with a fragment number field
     * of 0?
     * What if the fragment count is 0?  Should we flag that as well?
     */
    if (is_fragmented && frag != 0 && frags != 0 &&
        tvb_bytes_exist(tvb, i, sm_data_len)) {
        try_gsm_sms_ud_reassemble = TRUE;
        save_fragmented = pinfo->fragmented;
        pinfo->fragmented = TRUE;
        fd_sm = fragment_add_seq_check(&sm_reassembly_table,
                tvb, i,
                pinfo,
                sm_id,                /* guint32 ID for fragments belonging together */
                NULL,
                frag-1,               /* guint32 fragment sequence number */
                sm_data_len,          /* guint32 fragment length */
                (frag != frags));     /* More fragments? */
        if (fd_sm) {
            reassembled    = TRUE;
            reassembled_in = fd_sm->reassembled_in;
        }
        sm_tvb = process_reassembled_data(tvb, i, pinfo,
            "Reassembled Short Message", fd_sm, &sm_frag_items,
            NULL, sm_tree);
        if (reassembled) { /* Reassembled */
            col_append_str(pinfo->cinfo, COL_INFO,
                        " (Short Message Reassembled)");
        } else {
            /* Not last packet of reassembled Short Message */
            col_append_fstr(pinfo->cinfo, COL_INFO,
                    " (Short Message fragment %u of %u)", frag, frags);
        }
    } /* Else: not fragmented */

    if (! sm_tvb) /* One single Short Message, or not reassembled */
        sm_tvb = tvb_new_subset_remaining(tvb, i);
    /* Try calling a subdissector */
    if (sm_tvb) {
        if ((reassembled && pinfo->fd->num == reassembled_in)
            || frag==0 || (frag==1 && try_dissect_1st_frag)) {
            /* Try calling a subdissector only if:
             *  - the Short Message is reassembled in this very packet,
             *  - the Short Message consists of only one "fragment",
             *  - the preference "Always Try Dissection for 1st SM fragment"
             *    is switched on, and this is the SM's 1st fragment. */
            if (ports_available) {
                gboolean disallow_write = FALSE; /* TRUE if we changed writability
                                    of the columns of the summary */
                if (prevent_subdissectors_changing_columns && col_get_writable(pinfo->cinfo)) {
                    disallow_write = TRUE;
                    col_set_writable(pinfo->cinfo, FALSE);
                }

                if (port_number_udh_means_wsp) {
                    call_dissector(wsp_handle, sm_tvb, pinfo, top_tree);
                } else {
                    if (! dissector_try_uint(gsm_sms_dissector_table, p_src,
                                sm_tvb, pinfo, top_tree)) {
                        if (! dissector_try_uint(gsm_sms_dissector_table, p_dst,
                                    sm_tvb, pinfo, top_tree)) {
                            if (sm_tree) { /* Only display if needed */
                                proto_tree_add_item(sm_tree, hf_gsm_sms_ud_short_msg, sm_tvb, 0, -1, ENC_NA);
                            }
                        }
                    }
                }

                if (disallow_write)
                    col_set_writable(pinfo->cinfo, TRUE);
            } else { /* No ports IE */
                proto_tree_add_item(sm_tree, hf_gsm_sms_ud_short_msg, sm_tvb, 0, -1, ENC_NA);
            }
        } else {
            /* The packet is not reassembled,
             * or it is reassembled in another packet */
            proto_tree_add_bytes_format(sm_tree, hf_gsm_sms_ud_short_msg, sm_tvb, 0, -1,
                    NULL, "Unreassembled Short Message fragment %u of %u",
                    frag, frags);
        }
    }

    if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
        pinfo->fragmented = save_fragmented;
    return;
}
예제 #10
0
/*
 * dissector function of search data (request and response)
 *
 * input: tree, buffer (block data) flags (req or rsp)
 * return: nothing
 */
static void
dissect_bcp_search_data(proto_tree *bcp_tree, tvbuff_t *tvb, gint flags)
{
    proto_tree *bcp_subtree = NULL;
    guint type = 0;
    guint offset = 0;
    guint offset_base = offset;
    guint len = tvb_reported_length(tvb);

    if (flags & BCP_PROT_FLG_REQ)
    {
        type = tvb_get_ntohl(tvb, offset);
        switch (type)
        {
            case BCP_SEARCH_IPADDR:
                bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
                                  "BCP Search Request: IpAddrFirst=%s, IpAddrLast=%s",
                                  tvb_ip_to_str(tvb, offset + 8),
                                  tvb_ip_to_str(tvb, offset + 12)
                                  );
                break;

            case BCP_SEARCH_NAME:
                bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
                                  "BCP Search Request: Name=%s",
                                  tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 8, BCP_NAME_LEN, ENC_ASCII)
                                  );
                break;

            default:
                bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
                                  "BCP Search Request: Unknown AddrType");
                break;
        }

        proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_addrtype, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;
        proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_reserved, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        switch (type)
        {
            case BCP_SEARCH_IPADDR:
                proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_ipaddrfirst, tvb, offset, 4, ENC_BIG_ENDIAN);
                proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_ipaddrlast, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
                break;

            case BCP_SEARCH_NAME:
                proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_name, tvb, offset, BCP_NAME_LEN, ENC_ASCII|ENC_NA);
                break;

            default:
                proto_tree_add_bytes_format(bcp_subtree, hf_bcp_searchreq_addrdata, tvb, offset, BCP_NAME_LEN,
                                            NULL, "Unknown Address Data (%u bytes)", BCP_NAME_LEN);
                break;
        }
        offset += BCP_NAME_LEN;
    }

    if (flags & BCP_PROT_FLG_RSP)
    {
        bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
                          "BCP Search Response: Name=%s, IpAddr=%s Error=%d",
                          tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 16, BCP_NAME_LEN, ENC_ASCII),
                          tvb_ip_to_str(tvb, offset + 12),
                          tvb_get_letohl(tvb, offset)
                          );

        proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_error, tvb, offset, 4, ENC_NA);
        offset += 4;
        proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_starttime, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;
        proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_lenin, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;
        proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_lenout, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;
        proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ipaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;
        proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_name, tvb, offset, BCP_NAME_LEN, ENC_ASCII|ENC_NA);
        offset += BCP_NAME_LEN;
        proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ethaddr, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
        offset += BCP_ETHADDR_LEN;
        if((len-(offset-offset_base)))
        {
            proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ethaddr2, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
            offset += BCP_ETHADDR_LEN;
        }
    }
}
예제 #11
0
static void
dissect_ntp_std(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
{
	proto_tree      *flags_tree;
	proto_item	*tf;
	guint8		stratum;
	guint8		ppoll;
	gint8		precision;
	double		rootdelay;
	double		rootdispersion;
	const guint8	*refid;
	guint32		refid_addr;
	const guint8	*reftime;
	const guint8	*org;
	const guint8	*rec;
	const guint8	*xmt;
	const gchar	*buffc;
	gchar		*buff;
	int		i;
	int		macofs;
	gint            maclen;

	tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);

	/* Adding flag subtree and items */
	flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
	proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
	proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
	proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);

	/* Stratum, 1byte field represents distance from primary source
	 */
	stratum = tvb_get_guint8(tvb, 1);
	if (stratum == 0) {
		buffc="Peer Clock Stratum: unspecified or unavailable (%u)";
	} else if (stratum == 1) {
		buffc="Peer Clock Stratum: primary reference (%u)";
	} else if ((stratum >= 2) && (stratum <= 15)) {
		buffc="Peer Clock Stratum: secondary reference (%u)";
	} else {
		buffc="Peer Clock Stratum: reserved: %u";
	}
	proto_tree_add_uint_format(ntp_tree, hf_ntp_stratum, tvb, 1, 1,
				   stratum, buffc, stratum);
	/* Poll interval, 1byte field indicating the maximum interval
	 * between successive messages, in seconds to the nearest
	 * power of two.
	 */
	ppoll = tvb_get_guint8(tvb, 2);
	if ((ppoll >= 4) && (ppoll <= 17)) {
		proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
				   ppoll, 
				   "Peer Polling Interval: %u (%u sec)",
				   ppoll,
				   1 << ppoll);
	} else {
		proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
				   ppoll,
				   "Peer Polling Interval: invalid (%u)",
				   ppoll);
	}
	
	/* Precision, 1byte field indicating the precision of the
	 * local clock, in seconds to the nearest power of two.
	 */
	precision = tvb_get_guint8(tvb, 3);
	proto_tree_add_int_format(ntp_tree, hf_ntp_precision, tvb, 3, 1,
				   precision,
				   "Peer Clock Precision: %8.6f sec",
				   pow(2, precision));

	/* Root Delay is a 32-bit signed fixed-point number indicating
	 * the total roundtrip delay to the primary reference source,
	 * in seconds with fraction point between bits 15 and 16.
	 */
	rootdelay = ((gint16)tvb_get_ntohs(tvb, 4)) +
			(tvb_get_ntohs(tvb, 6) / 65536.0);
	proto_tree_add_double_format(ntp_tree, hf_ntp_rootdelay, tvb, 4, 4,
				   rootdelay,
				   "Root Delay: %9.4f sec",
				   rootdelay);

	/* Root Dispersion, 32-bit unsigned fixed-point number indicating
	 * the nominal error relative to the primary reference source, in
	 * seconds with fraction point between bits 15 and 16.
	 */
	rootdispersion = ((gint16)tvb_get_ntohs(tvb, 8)) +
				(tvb_get_ntohs(tvb, 10) / 65536.0);
	proto_tree_add_double_format(ntp_tree, hf_ntp_rootdispersion, tvb, 8, 4,
				   rootdispersion,
				   "Root Dispersion: %9.4f sec",
				   rootdispersion);

	/* Now, there is a problem with secondary servers.  Standards
	 * asks from stratum-2 - stratum-15 servers to set this to the
	 * low order 32 bits of the latest transmit timestamp of the
	 * reference source.
	 * But, all V3 and V4 servers set this to IP adress of their
	 * higher level server. My decision was to resolve this address.
	 */
	refid = tvb_get_ptr(tvb, 12, 4);
	buff = ep_alloc(NTP_TS_SIZE);
	if (stratum <= 1) {
		g_snprintf (buff, NTP_TS_SIZE, "Unidentified reference source '%.4s'",
			refid);
		for (i = 0; primary_sources[i].id; i++) {
			if (memcmp (refid, primary_sources[i].id, 4) == 0) {
				g_snprintf(buff, NTP_TS_SIZE, "%s",
					primary_sources[i].data);
				break;
			}
		}
	} else {
		int buffpos;
		refid_addr = tvb_get_ipv4(tvb, 12);
		buffpos = g_snprintf(buff, NTP_TS_SIZE, "%s", get_hostname (refid_addr));
		if (buffpos >= NTP_TS_SIZE) {
			buff[NTP_TS_SIZE-4]='.';
			buff[NTP_TS_SIZE-3]='.';
			buff[NTP_TS_SIZE-2]='.';
			buff[NTP_TS_SIZE-1]=0;
		}
	}
	proto_tree_add_bytes_format(ntp_tree, hf_ntp_refid, tvb, 12, 4,
				   refid,
				   "Reference Clock ID: %s", buff);

	/* Reference Timestamp: This is the time at which the local clock was
	 * last set or corrected.
	 */
	reftime = tvb_get_ptr(tvb, 16, 8);
	proto_tree_add_bytes_format(ntp_tree, hf_ntp_reftime, tvb, 16, 8,
				   reftime,
			           "Reference Clock Update Time: %s",
				   ntp_fmt_ts(reftime));

	/* Originate Timestamp: This is the time at which the request departed
	 * the client for the server.
	 */
	org = tvb_get_ptr(tvb, 24, 8);
	proto_tree_add_bytes_format(ntp_tree, hf_ntp_org, tvb, 24, 8,
				   org,
			           "Originate Time Stamp: %s",
				   ntp_fmt_ts(org));

	/* Receive Timestamp: This is the time at which the request arrived at
	 * the server.
	 */
	rec = tvb_get_ptr(tvb, 32, 8);
	proto_tree_add_bytes_format(ntp_tree, hf_ntp_rec, tvb, 32, 8,
				   rec,
			           "Receive Time Stamp: %s",
				   ntp_fmt_ts(rec));

	/* Transmit Timestamp: This is the time at which the reply departed the
	 * server for the client.
	 */
	xmt = tvb_get_ptr(tvb, 40, 8);
	proto_tree_add_bytes_format(ntp_tree, hf_ntp_xmt, tvb, 40, 8,
				   xmt,
			           "Transmit Time Stamp: %s",
				   ntp_fmt_ts(xmt));

	/* MAX_MAC_LEN is the largest message authentication code
	 * (MAC) length.  If we have more data left in the packet
	 * after the header than that, the extra data is NTP4
	 * extensions; parse them as such.
	 */
	macofs = 48;
	while (tvb_reported_length_remaining(tvb, macofs) > (gint)MAX_MAC_LEN)
		macofs = dissect_ntp_ext(tvb, ntp_tree, macofs);

	/* When the NTP authentication scheme is implemented, the
	 * Key Identifier and Message Digest fields contain the
	 * message authentication code (MAC) information defined in
	 * Appendix C of RFC-1305. Will print this as hex code for now.
	 */
	if (tvb_reported_length_remaining(tvb, macofs) >= 4)
		proto_tree_add_item(ntp_tree, hf_ntp_keyid, tvb, macofs, 4,
				    FALSE);
	macofs += 4;
	maclen = tvb_reported_length_remaining(tvb, macofs);
	if (maclen > 0)
		proto_tree_add_item(ntp_tree, hf_ntp_mac, tvb, macofs,
				    maclen, FALSE);
}
예제 #12
0
파일: packet-rrac.c 프로젝트: asmblur/SynCE
/* Code to actually dissect the packets */
static void
dissect_RRAC_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  int available_packet_data = 0;

/* Set up structures needed to add the protocol subtree and manage it */
	proto_item *ti;
	proto_tree *RRAC_tree;

/* Make entries in Protocol column and Info column on summary display */
	if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
		col_set_str(pinfo->cinfo, COL_PROTOCOL, "RRAC");
    
/* This field shows up as the "Info" column in the display; you should make
   it, if possible, summarize what's in the packet, so that a user looking
   at the list of packets can tell what type of packet it is. See section 1.5
   for more information.

   If you are setting it to a constant string, use "col_set_str()", as
   it's more efficient than the other "col_set_XXX()" calls.

   If you're setting it to a string you've constructed, or will be
   appending to the column later, use "col_add_str()".

   "col_add_fstr()" can be used instead of "col_add_str()"; it takes
   "printf()"-like arguments.  Don't use "col_add_fstr()" with a format
   string of "%s" - just use "col_add_str()" or "col_set_str()", as it's
   more efficient than "col_add_fstr()".

   If you will be fetching any data from the packet before filling in
   the Info column, clear that column first, in case the calls to fetch
   data from the packet throw an exception because they're fetching data
   past the end of the packet, so that the Info column doesn't have data
   left over from the previous dissector; do

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

   */

  if (check_col(pinfo->cinfo, COL_INFO))  {
    if (pinfo->srcport == RRAC_TCP_PORT) {
      col_set_str(pinfo->cinfo, COL_INFO, "Request");
    }
    else {
      col_set_str(pinfo->cinfo, COL_INFO, "Reply");
    }
  }

/* In the interest of speed, if "tree" is NULL, avoid building a
   protocol tree and adding stuff to it if possible.  Note,
   however, that you must call subdissectors regardless of whether
   "tree" is NULL or not. */
  if (tree) {
    int offset = 0;

    while (tvb_length_remaining(tvb, offset) > 0) {
      const guint8 *data;

#if 0
      /* Need at least 4 for size */
      if (tvb_length_remaining(tvb, offset) < 4) {
        pinfo->desegment_offset = offset;
        pinfo->desegment_len = 4;
        return;
      }
#endif

      /* NOTE: The offset and length values in the call to
         "proto_tree_add_item()" define what data available_packet_data to highlight in the hex
         display window when the line in the protocol tree display
         corresponding to that item is selected.

         Supplying a length of -1 is the way to highlight all data from the
         offset to the end of the packet. */

#if 0
      if (test_value == 0)
      {
        int start_offset = offset;
        guint32 object_id;

        /* Assume data protocol */
        if (tvb_length_remaining(tvb, offset) < 12) {
          pinfo->desegment_offset = offset;
          pinfo->desegment_len = 12;
          return;
        }

        object_id = tvb_get_letohs(tvb, offset);

        proto_tree_add_item(RRAC_tree, hf_RRAC_object_id, tvb, offset, 4, TRUE);
        offset += 4;
        proto_tree_add_item(RRAC_tree, hf_RRAC_type_id, tvb, offset, 4, TRUE);
        offset += 4;
        proto_tree_add_item(RRAC_tree, hf_RRAC_data_flags, tvb, offset, 4, TRUE);
        offset += 4;

        if (object_id != 0xffffffff)
        {
          proto_tree_add_item(RRAC_tree, hf_RRAC_chunk_size, tvb, offset, 2, TRUE);
          offset += 2;
          proto_tree_add_item(RRAC_tree, hf_RRAC_chunk_flags, tvb, offset, 2, TRUE);
          offset += 2;

          available_packet_data = tvb_length_remaining(tvb, offset);
          if (available_packet_data > 0)
          {
            data = tvb_get_ptr(tvb, offset, available_packet_data);
            proto_tree_add_available_packet_data_format(RRAC_tree, hf_RRAC_data, tvb,
                offset,
                available_packet_data,
                data,
                "Data (%i available_packet_data)", available_packet_data);
            offset += available_packet_data;
          }
        }
      }
#endif

      if (is_rrac_command_stream(tvb, offset))
      {
        guint16 command = tvb_get_letohs(tvb, offset);
        guint16 total_packet_data = tvb_get_letohs(tvb, offset + 2);

        available_packet_data = tvb_length_remaining(tvb, offset + 4);

#if 0
        fprintf(stderr, 
            "c=%04x t=%04x a=%04x  do=%04x dl=%04x cd=%i\n", 
            command, total_packet_data, available_packet_data,
            pinfo->desegment_offset, pinfo->desegment_len, pinfo->can_desegment);
#endif

        /* create display subtree for the protocol */
        ti = proto_tree_add_item(tree, proto_RRAC, tvb, offset, total_packet_data + 4, FALSE);
        RRAC_tree = proto_item_add_subtree(ti, ett_RRAC);


#if 0
        proto_tree_add_text(RRAC_tree, tvb, offset, 0, "(DEBUG) can_desegment: %i", pinfo->can_desegment);
        proto_tree_add_text(RRAC_tree, tvb, offset, 0, "(DEBUG) desegment_offset: %04x", pinfo->desegment_offset);
        proto_tree_add_text(RRAC_tree, tvb, offset, 0, "(DEBUG) desegment_len: %04x", pinfo->desegment_len);
        proto_tree_add_text(RRAC_tree, tvb, offset, 4, "(DEBUG) Offset: %04x", offset);
        proto_tree_add_text(RRAC_tree, tvb, offset + 4, available_packet_data, "(DEBUG) Bytes: %04x", available_packet_data);
        /*proto_tree_add_text(RRAC_tree, tvb, offset, 2, "(DEBUG) My command: %04x", command);*/
        proto_tree_add_text(RRAC_tree, tvb, offset + 2, 2, "(DEBUG) My packet size: %04x", total_packet_data);
#endif

        proto_tree_add_item(RRAC_tree, hf_RRAC_command, tvb, offset,     2, TRUE);
        proto_tree_add_item(RRAC_tree, hf_RRAC_size,    tvb, offset + 2, 2, TRUE);

        if (available_packet_data < total_packet_data) {
          proto_tree_add_text(RRAC_tree, tvb, offset, -1, 
              "Part of RRAC packet: %i available of %i total", 
              available_packet_data, 4 + total_packet_data);

#if 0
          pinfo->desegment_offset = offset;
          pinfo->desegment_len = 4 + total_packet_data;
          return;
#endif
        }

        offset += 4;

        switch (command)
        {
          case 0x65:
            proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Object type: %08x", 
                tvb_get_letohl(tvb, offset));
            offset += 4;
            proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Previous identifier: %08x", 
                tvb_get_letohl(tvb, offset));
            offset += 4;
            proto_tree_add_text(RRAC_tree, tvb, offset, 4, "New identifier: %08x", 
                tvb_get_letohl(tvb, offset));
            offset += 4;
            proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Flags: %08x", 
                tvb_get_letohl(tvb, offset));
            offset += 4;
            total_packet_data -= 4*4;
            break;
            
          case 0x66:
            proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Unknown: %08x", 
                tvb_get_letohl(tvb, offset));
            offset += 4;
            proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Object type: %08x", 
                tvb_get_letohl(tvb, offset));
            offset += 4;
            proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Identifier: %08x", 
                tvb_get_letohl(tvb, offset));
            offset += 4;
            proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Unknown: %08x", 
                tvb_get_letohl(tvb, offset));
            offset += 4;
            total_packet_data -= 4*4;
            break;
            
          case 0x69:
            proto_tree_add_item(RRAC_tree, hf_RRAC_subcommand, tvb, offset, 4, TRUE);
            offset += 4;
            total_packet_data -= 4;

            switch (tvb_get_letohl(tvb, offset - 4))
            {
              case 0x02000000:
                proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Unknown: %08x", 
                    tvb_get_letohl(tvb, offset));
                offset += 4;
                proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Unknown: %08x", 
                    tvb_get_letohl(tvb, offset));
                offset += 4;
                proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Maybe size of remaining data: %08x", 
                    tvb_get_letohl(tvb, offset));
                offset += 4;
                proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Current partner index: %08x", 
                    tvb_get_letohl(tvb, offset));
                offset += 4;
                proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Partner 1 identifier: %08x", 
                    tvb_get_letohl(tvb, offset));
                offset += 4;
                proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Partner 2 identifier: %08x", 
                    tvb_get_letohl(tvb, offset));
                offset += 4;
                total_packet_data -= 4*6;
                break;

              case 0:
              case 0x04000000:
              case 0x06000000:
                proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Object type: %08x", 
                    tvb_get_letohl(tvb, offset));
                offset += 4;
                proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Count: %08x", 
                    tvb_get_letohl(tvb, offset));
                offset += 4;

                {
                  guint size = tvb_get_letohl(tvb, offset);

                  proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Size: %08x", size);
                  offset += 4;
                  total_packet_data -= 4*3;

                  while (size >= 4)
                  {
                    proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Identifier: %08x", 
                        tvb_get_letohl(tvb, offset));
                    offset += 4;
                    total_packet_data -= 4;
                    size -= 4;
                  }
                }
                break;
            }
            break;

          case 0x6c:
            proto_tree_add_item(RRAC_tree, hf_RRAC_reply_to, tvb, offset, 4, TRUE);
            offset += 4;
            total_packet_data -= 4;
            break;

          case 0x6f:
            proto_tree_add_item(RRAC_tree, hf_RRAC_subcommand, tvb, offset, 4, TRUE);
            offset += 4;
            total_packet_data -= 4;
            break;

          case 0x70:
            proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Size of remaining packet: %08x", 
                tvb_get_letohl(tvb, offset));
            offset += 4;
            proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Unknown: %08x", 
                tvb_get_letohl(tvb, offset));
            offset += 4;
            
            {
              guint subcommand = tvb_get_letohl(tvb, offset);
              proto_tree_add_item(RRAC_tree, hf_RRAC_subcommand, tvb, offset, 4, TRUE);
              offset += 4;
              total_packet_data -= 4*3;

              if (subcommand == 3) {
                unsigned i;
                guint count;

                for (i = 0; i < 4; i++) {
                  proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Unknown: %08x", 
                      tvb_get_letohl(tvb, offset));
                  offset += 4;
                  total_packet_data -= 4;
                }

                count = tvb_get_letohl(tvb, offset);
                proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Count: %08x", count);
                offset += 4;
                total_packet_data -= 4;

                for (i = 0; i < count; i++) {
                  proto_tree_add_text(RRAC_tree, tvb, offset, 4, "Identifier: %08x", 
                      tvb_get_letohl(tvb, offset));
                  offset += 4;
                  total_packet_data -= 4;
                }
              } /* subcommand == 3 */  
            }
            break;
        }

        if (total_packet_data > 0)
        {
          data = tvb_get_ptr(tvb, offset, total_packet_data);
          proto_tree_add_bytes_format(RRAC_tree, hf_RRAC_data, tvb,
              offset,
              total_packet_data,
              data,
              "Data (%i bytes)", total_packet_data);
          offset += total_packet_data;
        }
      }

      /* XXX only show the first command */
      break;
    } /* while */
  } /* if (tree) */

  /* If this protocol has a sub-dissector call it here, see section 1.8 */
}
예제 #13
0
static void
dissect_nflog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    const int start_tlv_offset = 4;

    proto_tree *nflog_tree = NULL;
    proto_item *ti;

    int offset = 0;

    tvbuff_t *next_tvb = NULL;
    int aftype;

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

    aftype = tvb_get_guint8(tvb, 0);

    /* Header */
    if (proto_field_is_referenced(tree, hfi_nflog->id)) {
        ti = proto_tree_add_item(tree, hfi_nflog, tvb, 0, -1, ENC_NA);
        nflog_tree = proto_item_add_subtree(ti, ett_nflog);

        proto_tree_add_item(nflog_tree, &hfi_nflog_family, tvb, offset, 1, ENC_NA);
        offset += 1;

        proto_tree_add_item(nflog_tree, &hfi_nflog_version, tvb, offset, 1, ENC_NA);
        offset += 1;

        proto_tree_add_item(nflog_tree, &hfi_nflog_resid, tvb, offset, 2, ENC_BIG_ENDIAN);
        /*offset += 2;*/
    }

    offset = start_tlv_offset;
    /* TLVs */
    while (tvb_reported_length_remaining(tvb, offset) >= 4) {
        guint16 tlv_len = tvb_get_h_guint16(tvb, offset + 0);
        guint16 tlv_type;
        guint16 value_len;

        proto_tree *tlv_tree;

        /* malformed */
        if (tlv_len < 4)
            return;

        value_len = tlv_len - 4;
        tlv_type = (tvb_get_h_guint16(tvb, offset + 2) & 0x7fff);

        if (nflog_tree) {
            gboolean handled = FALSE;

            ti = proto_tree_add_bytes_format(nflog_tree, hfi_nflog_tlv.id,
                             tvb, offset, tlv_len, NULL,
                             "TLV Type: %s (%u), Length: %u",
                             val_to_str_const(tlv_type, nflog_tlv_vals, "Unknown"),
                             tlv_type, tlv_len);
            tlv_tree = proto_item_add_subtree(ti, ett_nflog_tlv);

            proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_length, tvb, offset + 0, 2, ENC_HOST_ENDIAN);
            proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_type, tvb, offset + 2, 2, ENC_HOST_ENDIAN);
            switch (tlv_type) {
                case WS_NFULA_PAYLOAD:
                    handled = TRUE;
                    break;

                case WS_NFULA_PREFIX:
                    if (value_len >= 1) {
                        proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_prefix,
                                    tvb, offset + 4, value_len, ENC_NA);
                        handled = TRUE;
                    }
                    break;

                case WS_NFULA_UID:
                    if (value_len == 4) {
                        proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_uid,
                                    tvb, offset + 4, value_len, ENC_BIG_ENDIAN);
                        handled = TRUE;
                    }
                    break;

                case WS_NFULA_GID:
                    if (value_len == 4) {
                        proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_gid,
                                    tvb, offset + 4, value_len, ENC_BIG_ENDIAN);
                        handled = TRUE;
                    }
                    break;

                case WS_NFULA_TIMESTAMP:
                    if (value_len == 16) {
                        nstime_t ts;

                        ts.secs  = (time_t)tvb_get_ntoh64(tvb, offset + 4);
                        /* XXX - add an "expert info" warning if this is >= 10^9? */
                        ts.nsecs = (int)tvb_get_ntoh64(tvb, offset + 12);
                        proto_tree_add_time(tlv_tree, &hfi_nflog_tlv_timestamp,
                                    tvb, offset + 4, value_len, &ts);
                        handled = TRUE;
                    }
                    break;
            }

            if (!handled)
                    proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_unknown,
                                        tvb, offset + 4, value_len, ENC_NA);
        }

        if (tlv_type == WS_NFULA_PAYLOAD)
            next_tvb = tvb_new_subset_length(tvb, offset + 4, value_len);

        offset += ((tlv_len + 3) & ~3); /* next TLV aligned to 4B */
    }

    if (next_tvb) {
        switch (aftype) {
            case LINUX_AF_INET:
                call_dissector(ip_handle, next_tvb, pinfo, tree);
                break;
            case LINUX_AF_INET6:
                call_dissector(ip6_handle, next_tvb, pinfo, tree);
                break;
            default:
                call_dissector(data_handle, next_tvb, pinfo, tree);
                break;
        }
    }
}
/*
 * Name: isis_dissect_isis_hello()
 *
 * Description:
 *	This procedure rips apart the various types of ISIS hellos.  L1H and
 *	L2H's are identical for the most part, while the PTP hello has
 *	a shorter header.
 *
 * Input:
 *	tvbuff_t * : tvbuffer for packet data
 *	proto_tree * : protocol display tree to add to.  May be NULL.
 *	int offset : our offset into packet data.
 *	int : hello type, a la packet-isis.h ISIS_TYPE_* values
 *	int : header length of packet.
 *	int : length of IDs in packet.
 *
 * Output:
 *	void, will modify proto_tree if not NULL.
 */
void
isis_dissect_isis_hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
                        int hello_type, int header_length, int id_length)
{
    proto_item	*ti;
    proto_tree	*hello_tree = NULL;
    int 		len;
    guint8		octet;
    const guint8	*source_id;
    guint16		pdu_length;
    const guint8	*lan_id;

    if (tree) {
        ti = proto_tree_add_text(tree, tvb, offset, -1, "ISIS HELLO");
        hello_tree = proto_item_add_subtree(ti, ett_isis_hello);
        octet = tvb_get_guint8(tvb, offset);
        proto_tree_add_uint_format(hello_tree,
                                   hf_isis_hello_circuit_reserved,
                                   tvb, offset, 1, octet,
                                   "Circuit type              : %s, reserved(0x%02x == 0)",
                                   val_to_str(octet&ISIS_HELLO_CTYPE_MASK,
                                              isis_hello_circuit_type_vals,
                                              "Unknown (0x%x)"),
                                   octet&ISIS_HELLO_CT_RESERVED_MASK
                                  );
    }
    offset += 1;

    if (tree) {
        source_id = tvb_get_ptr(tvb, offset, id_length);
        proto_tree_add_bytes_format(hello_tree, hf_isis_hello_source_id, tvb,
                                    offset, id_length, source_id,
                                    "System-ID {Sender of PDU} : %s",
                                    print_system_id( source_id, id_length ) );
    }
    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_append_fstr(pinfo->cinfo, COL_INFO, ", System-ID: %s",
                        print_system_id( tvb_get_ptr(tvb, offset, id_length), id_length ) );
    }
    offset += id_length;

    if (tree) {
        proto_tree_add_item(hello_tree, hf_isis_hello_holding_timer, tvb,
                            offset, 2, ENC_BIG_ENDIAN);
    }
    offset += 2;

    pdu_length = tvb_get_ntohs(tvb, offset);
    if (tree) {
        proto_tree_add_uint(hello_tree, hf_isis_hello_pdu_length, tvb,
                            offset, 2, pdu_length);
    }
    offset += 2;

    if (hello_type == ISIS_TYPE_PTP_HELLO) {
        if (tree) {
            proto_tree_add_item(hello_tree, hf_isis_hello_local_circuit_id, tvb,
                                offset, 1, ENC_BIG_ENDIAN );
        }
        offset += 1;
    } else {
        if (tree) {
            octet = tvb_get_guint8(tvb, offset);
            proto_tree_add_uint_format(hello_tree, hf_isis_hello_priority_reserved, tvb,
                                       offset, 1, octet,
                                       "Priority                  : %d, reserved(0x%02x == 0)",
                                       octet&ISIS_HELLO_PRIORITY_MASK,
                                       octet&ISIS_HELLO_P_RESERVED_MASK );
        }
        offset += 1;

        if (tree) {
            lan_id = tvb_get_ptr(tvb, offset, id_length+1);
            proto_tree_add_bytes_format(hello_tree, hf_isis_hello_lan_id, tvb,
                                        offset, id_length + 1, lan_id,
                                        "System-ID {Designated IS} : %s",
                                        print_system_id( lan_id, id_length + 1 ) );
        }
        offset += id_length + 1;
    }

    len = pdu_length;
    len -= header_length;
    if (len < 0) {
        isis_dissect_unknown(tvb, tree, offset,
                             "Packet header length %d went beyond packet",
                             header_length );
        return;
    }
    /*
     * Now, we need to decode our CLVs.  We need to pass in
     * our list of valid ones!
     */
    if (hello_type == ISIS_TYPE_L1_HELLO) {
        isis_dissect_clvs(tvb, hello_tree, offset,
                          clv_l1_hello_opts, len, id_length,
                          ett_isis_hello_clv_unknown);
    } else if (hello_type == ISIS_TYPE_L2_HELLO) {
        isis_dissect_clvs(tvb, hello_tree, offset,
                          clv_l2_hello_opts, len, id_length,
                          ett_isis_hello_clv_unknown);
    } else {
        isis_dissect_clvs(tvb, hello_tree, offset,
                          clv_ptp_hello_opts, len, id_length,
                          ett_isis_hello_clv_unknown);
    }
}
예제 #15
0
/*
 * Function for AVP dissector.
 */
static void
dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
{

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

       guint16 buffer_length;
       int bad_avp = FALSE;

       tvbuff_t *group_tvb;
       tvbuff_t *eap_tvb;
       proto_item *single_avp_item;
       proto_tree *single_avp_tree;
       proto_item *avp_group_item;
       proto_tree *avp_group_tree;
       proto_item *avp_eap_item;
       proto_tree *avp_eap_tree;

       offset = 0;
       buffer_length = tvb_reported_length(tvb);

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

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

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

               /* Check AVP length */
               if (avp_length < avp_hdr_length) {
                       single_avp_item = proto_tree_add_text(avp_tree, tvb, offset, avp_length,
                                                             "%s (%s) length: %d bytes (shorter than header length %d)",
                                                             val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                             val_to_str(avp_type, avp_type_names, "Unknown (%d)"),
                                                             avp_length,
                                                             avp_hdr_length);

                       single_avp_tree = proto_item_add_subtree(single_avp_item, ett_pana_avp_info);

                       if (single_avp_tree != NULL) {
                               /* AVP Code */
                               proto_tree_add_uint_format_value(single_avp_tree, hf_pana_avp_code, tvb,
                                                                offset, 2, avp_code, "%s (%u)",
                                                                val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                                avp_code);
                               offset += 2;
                               /* AVP Flags */
                               dissect_pana_avp_flags(single_avp_tree, tvb, offset, avp_flags);
                               offset += 2;
                               /* AVP Length */
                               proto_tree_add_item(single_avp_tree, hf_pana_avp_length, tvb, offset, 2, FALSE);
                               offset += 2;
                       }
                       return;
               }

               /* Check AVP flags */
               if (avp_flags & PANA_AVP_FLAG_RES) bad_avp = TRUE;

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

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

               single_avp_tree = proto_item_add_subtree(single_avp_item, ett_pana_avp_info);

               /* AVP data length */
               avp_data_length = avp_length - avp_hdr_length;

               if (single_avp_tree != NULL) {
                       /* AVP Code */
                       proto_tree_add_uint_format_value(single_avp_tree, hf_pana_avp_code, tvb,
                                                       offset, 2, avp_code, "%s (%u)",
                                                       val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                       avp_code);
               }
               offset += 2;
               if (single_avp_tree != NULL) {
                       /* AVP Flags */
                       dissect_pana_avp_flags(single_avp_tree, tvb, offset, avp_flags);
               }
               offset += 2;
               if (single_avp_tree != NULL) {
                       /* AVP Length */
                       proto_tree_add_item(single_avp_tree, hf_pana_avp_length, tvb, offset, 2, FALSE);
               }
               offset += 2;
               if (single_avp_tree != NULL) {
                       /* Reserved */
                       proto_tree_add_item(single_avp_tree, hf_pana_avp_reserved, tvb, offset, 2, FALSE);
               }
               offset += 2;
               if (avp_flags & PANA_AVP_FLAG_V) {
                       if (single_avp_tree != NULL) {
                               /* Vendor ID */
                               proto_tree_add_item(single_avp_tree, hf_pana_avp_vendorid, tvb, offset, 4, FALSE);
                       }
                       offset += 4;
               }
               if (avp_flags & PANA_AVP_FLAG_V) {
                       /* AVP Value */
                       switch(avp_type) {
                               case PANA_GROUPED: {
                                       avp_group_item = proto_tree_add_text(single_avp_tree,
                                                                         tvb, offset, avp_data_length,
                                                                         "Grouped AVP");
                                       avp_group_tree = proto_item_add_subtree(avp_group_item, ett_pana_avp);
                                       group_tvb = tvb_new_subset(tvb, offset,
                                                                       MIN(avp_data_length, tvb_length(tvb)-offset), avp_data_length);
                                       if (avp_group_tree != NULL) {
                                               dissect_avps(group_tvb, pinfo, avp_group_tree);
                                       }
                                       break;
                               }
                               case PANA_UTF8STRING: {
                                       const guint8 *data;
                                       data = tvb_get_ptr(tvb, offset, avp_data_length);
                                       proto_tree_add_string_format(single_avp_tree, hf_pana_avp_data_string, tvb,
                                                       offset, avp_data_length, data,
                                                       "UTF8String: %*.*s",
                                                       avp_data_length, avp_data_length, data);
                                       break;
                               }
                               case PANA_OCTET_STRING: {
                                       proto_tree_add_bytes_format(single_avp_tree, hf_pana_avp_data_bytes, tvb,
                                                       offset, avp_data_length,
                                                   tvb_get_ptr(tvb, offset, avp_data_length),
                                                       "Hex Data Highlighted Below");
                                       break;
                               }
                               case PANA_INTEGER32: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int32, tvb,
                                                       offset, 4, FALSE);
                                       break;
                               }
                               case PANA_UNSIGNED32: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint32, tvb,
                                                       offset, 4, FALSE);
                                       break;
                               }
                               case PANA_INTEGER64: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int64, tvb,
                                                       offset, 8, FALSE);
                                       break;
                               }
                               case PANA_UNSIGNED64: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint64, tvb,
                                                       offset, 8, FALSE);
                                       break;
                               }
                               case PANA_ENUMERATED: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_enumerated, tvb,
                                                       offset, 4, FALSE);
                                       break;
                               }
                               case PANA_RESULT_CODE: {
                                       proto_tree_add_text(single_avp_tree, tvb, offset, avp_data_length,
                                                               "Value: %d (%s)",
                                                               tvb_get_ntohl(tvb, offset),
                                                               val_to_str(tvb_get_ntohs(tvb, offset), avp_code_names, "Unknown (%d)"));
                                       break;
                               }
                               case PANA_EAP: {
                                       avp_eap_item = proto_tree_add_text(single_avp_tree,
                                                                         tvb, offset, avp_data_length,
                                                                         "AVP Value (EAP packet)");
                                       avp_eap_tree = proto_item_add_subtree(avp_eap_item, ett_pana_avp);
                                       eap_tvb = tvb_new_subset(tvb, offset, avp_data_length, avp_data_length);
                                       if (eap_handle != NULL) {
                                               call_dissector(eap_handle, eap_tvb, pinfo, avp_eap_tree);
                                       }
                                       break;
                               }
                       }
               }
               offset += avp_data_length + padding;

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

}
예제 #16
0
static int dissect_pbb_addressblock(tvbuff_t *tvb, proto_tree *tree, guint offset, guint maxoffset,
    guint8 addressType, guint8 addressSize) {
  guint8 addr[MAX_ADDR_SIZE];

  guint8 numAddr;
  guint8 address_flags;
  guint8 head_length = 0, tail_length = 0;
  guint block_length = 0, midSize = 0;
  guint block_index = 0, head_index = 0, tail_index = 0, mid_index = 0, prefix_index = 0;

  proto_tree *addr_tree = NULL;
  proto_tree *addrFlags_tree = NULL;
  proto_tree *addrValue_tree = NULL;

  proto_item *addr_item = NULL;
  proto_item *addrFlags_item = NULL;
  proto_item *addrValue_item = NULL;

  int i = 0;

  if (maxoffset - offset < 2) {
    proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
        tvb_get_ptr(tvb, offset, maxoffset - offset), "Not enough octets for minimal addressblock header");
    return tvb_reported_length(tvb);
  }

  DISSECTOR_ASSERT(addressSize <= MAX_ADDR_SIZE);

  memset(addr, 0, addressSize);

  block_length = 2;
  block_index = offset;
  midSize = addressSize;

  numAddr = tvb_get_guint8(tvb, offset++);
  address_flags = tvb_get_guint8(tvb, offset++);

  if ((address_flags & ADDR_HASHEAD) != 0) {
    head_index = offset;

    if (maxoffset - offset <= 0) {
      proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
          tvb_get_ptr(tvb, offset, maxoffset - offset), "Not enough octets for addressblock head");
      return tvb_reported_length(tvb);
    }
    head_length = tvb_get_guint8(tvb, offset++);

    if (head_length > addressSize-1) {
      proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
          tvb_get_ptr(tvb, offset, maxoffset - offset), "address head length is too long");
      return tvb_reported_length(tvb);
    }
    if (maxoffset - offset < head_length) {
      proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
          tvb_get_ptr(tvb, offset, maxoffset - offset), "Not enough octets for addressblock head");
      return tvb_reported_length(tvb);
    }
    tvb_memcpy(tvb, addr, offset, head_length);

    midSize -= head_length;
    block_length += (head_length+1);
    offset += head_length;
  }
  if ((address_flags & ADDR_HASZEROTAIL) != 0) {
    tail_index = offset;

    if (maxoffset - offset <= 0) {
      proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
          tvb_get_ptr(tvb, offset, maxoffset - offset), "Not enough octets for addressblock tail");
      return tvb_reported_length(tvb);
    }
    tail_length = tvb_get_guint8(tvb, offset++);
    if (tail_length > addressSize-1-head_length) {
      proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
          tvb_get_ptr(tvb, offset, maxoffset - offset), "address tail length is too long");
      return tvb_reported_length(tvb);
    }
    midSize -= tail_length;
    block_length++;
  }
  else if ((address_flags & ADDR_HASFULLTAIL) != 0) {
    tail_index = offset;

    if (maxoffset - offset <= 0) {
      proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
          tvb_get_ptr(tvb, offset, maxoffset - offset), "Not enough octets for addressblock tail");
      return tvb_reported_length(tvb);
    }
    tail_length = tvb_get_guint8(tvb, offset++);
    if (tail_length > addressSize-1-head_length) {
      proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
          tvb_get_ptr(tvb, offset, maxoffset - offset), "address tail length is too long");
      return tvb_reported_length(tvb);
    }

    if (maxoffset - offset < tail_length) {
      proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
          tvb_get_ptr(tvb, offset, maxoffset - offset), "Not enough octets for addressblock tail");
      return tvb_reported_length(tvb);
    }
    tvb_memcpy(tvb, &addr[addressSize - tail_length], offset, tail_length);

    midSize -= tail_length;
    block_length += (tail_length+1);
    offset += tail_length;
  }

  mid_index = offset;
  block_length += numAddr * midSize;
  offset += numAddr * midSize;

  if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) {
    prefix_index = offset;
    block_length++;
  }
  else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) {
    prefix_index = offset;
    block_length += numAddr;
  }

  if (maxoffset < block_index + block_length) {
    proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
        tvb_get_ptr(tvb, offset, maxoffset - offset), "Not enough octets for address block");
    return maxoffset;
  }

  /* add address tree */
  addr_item = proto_tree_add_item(tree, hf_packetbb_addr, tvb, block_index, block_length, FALSE);
  addr_tree = proto_item_add_subtree(addr_item, ett_packetbb_addr);
  proto_item_append_text(addr_item, " (%d addresses)", numAddr);

  /* add num-addr */
  proto_tree_add_item(addr_tree, hf_packetbb_addr_num, tvb, block_index, 1, FALSE);

  /* add flags */
  addrFlags_item = proto_tree_add_item(addr_tree, hf_packetbb_addr_flags, tvb, block_index+1, 1, FALSE);
  addrFlags_tree = proto_item_add_subtree(addrFlags_item, ett_packetbb_addr_flags);

  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hashead, tvb, block_index+1, 1, FALSE);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasfulltail, tvb, block_index+1, 1, FALSE);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_haszerotail, tvb, block_index+1, 1, FALSE);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hassingleprelen, tvb, block_index+1, 1, FALSE);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasmultiprelen, tvb, block_index+1, 1, FALSE);

  if ((address_flags & ADDR_HASHEAD) != 0) {
    /* add head */
    proto_tree_add_item(addr_tree, hf_packetbb_addr_head, tvb, head_index, head_length+1, FALSE);
  }

  if ((address_flags & ADDR_HASFULLTAIL) != 0) {
    /* add full tail */
    proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, tail_length+1, FALSE);
  }
  else if ((address_flags & ADDR_HASZEROTAIL) != 0) {
    /* add zero tail */
    proto_tree_add_item(addr_tree, hf_packetbb_addr_head, tvb, tail_index, 1, FALSE);
  }
  for (i=0; i<numAddr; i++) {
    guint32 ipv4 = (addr[0] << 24) + (addr[1] << 16) + (addr[2] << 8) + addr[3];
    guint8 prefix = addressSize * 8;

    tvb_memcpy(tvb, &addr[head_length], mid_index + midSize*i, midSize);

    switch (addressType) {
      case 0:
        addrValue_item = proto_tree_add_ipv4(addr_tree, hf_packetbb_addr_value[addressType],
            tvb, mid_index, block_index + block_length - mid_index, ipv4);
        break;
      case 1:
        addrValue_item = proto_tree_add_ipv6(addr_tree, hf_packetbb_addr_value[addressType],
            tvb, mid_index, block_index + block_length - mid_index, addr);
        break;
      case 2:
        addrValue_item = proto_tree_add_ether(addr_tree, hf_packetbb_addr_value[addressType],
            tvb, mid_index, block_index + block_length - mid_index, addr);
        break;
      default:
        addrValue_item = proto_tree_add_bytes(addr_tree, hf_packetbb_addr_value[addressType],
            tvb, mid_index, block_index + block_length - mid_index, addr);
        break;
    }
    addrValue_tree = proto_item_add_subtree(addrValue_item, ett_packetbb_addr_value);

    proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_mid, tvb,
        mid_index + midSize*i, midSize, FALSE);

    if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) {
      prefix = tvb_get_guint8(tvb, prefix_index);
      proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index, 1, FALSE);
    }
    else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) {
      prefix = tvb_get_guint8(tvb, prefix_index + i);
      proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index + i, 1, FALSE);
    }
    proto_item_append_text(addrValue_item, "/%d", prefix);
  }

  offset = dissect_pbb_tlvblock(tvb, addr_tree, block_index + block_length, maxoffset, numAddr);
  return offset;
}
예제 #17
0
/* Code to actually dissect the packets */
static int
dissect_wol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    guint len;
    gint offset;
    guint8 sync[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    guint8 *mac;
    const guint8 *passwd;

/* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti;
    proto_item *mti;
    proto_tree *wol_tree;
    proto_tree *mac_tree;

/*  First, if at all possible, do some heuristics to check if the packet cannot
 *  possibly belong to your protocol.  This is especially important for
 *  protocols directly on top of TCP or UDP where port collisions are
 *  common place (e.g., even though your protocol uses a well known port,
 *  someone else may set up, for example, a web server on that port which,
 *  if someone analyzed that web server's traffic in Wireshark, would result
 *  in Wireshark handing an HTTP packet to your dissector).  For example:
 */
    /* Check that there's enough data */
    len = tvb_length(tvb);
    if ( len < 102 )    /* wol's smallest packet size is 102 */
        return (0);

    /* Get some values from the packet header, probably using tvb_get_*() */

    /* Regardless of what the AMD white paper states, don't search the entire
     * tvb for the synchronization stream.  My feeling is that this could be
     * quite expensive and seriously hinder Wireshark performance.  For now,
     * unless we need to change it later, just compare the 1st 6 bytes. */
    if ( tvb_memeql(tvb, 0, sync, 6) != 0 )
        return (0);

    /* So far so good.  Now get the next 6 bytes, which we'll assume is the
     * target's MAC address, and do 15 memory chunk comparisons, since if this
     * is a real MagicPacket, the target's MAC will be duplicated 16 times. */
    mac = ep_tvb_memdup(tvb, 6, 6);
    for ( offset = 12; offset < 102; offset += 6 )
        if ( tvb_memeql(tvb, offset, mac, 6) != 0 )
            return (0);

    /* OK, we're going to assume it's a MagicPacket.  If there's a password,
     * grab it now, and in case there's any extra bytes after the only 3 valid
     * and expected lengths, truncate the length so the extra byte(s) aren't
     * included as being part of the WOL payload. */
    if ( len >= 106 && len < 108 )
    {
        len = 106;
        passwd = tvb_ip_to_str(tvb, 102);
    }
    else if ( len >= 108 )
    {
        len = 108;
        passwd = ether_to_str(ep_tvb_memdup(tvb, 102, 6));
    }
    else
    {
        len = 102;
        passwd = NULL;
    }

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

/* This field shows up as the "Info" column in the display; you should use
   it, if possible, to summarize what's in the packet, so that a user looking
   at the list of packets can tell what type of packet it is. See section 1.5
   for more information.

   Before changing the contents of a column you should make sure the column is
   active by calling "check_col(pinfo->cinfo, COL_*)". If it is not active
   don't bother setting it.

   If you are setting the column to a constant string, use "col_set_str()",
   as it's more efficient than the other "col_set_XXX()" calls.

   If you're setting it to a string you've constructed, or will be
   appending to the column later, use "col_add_str()".

   "col_add_fstr()" can be used instead of "col_add_str()"; it takes
   "printf()"-like arguments.  Don't use "col_add_fstr()" with a format
   string of "%s" - just use "col_add_str()" or "col_set_str()", as it's
   more efficient than "col_add_fstr()".

   If you will be fetching any data from the packet before filling in
   the Info column, clear that column first, in case the calls to fetch
   data from the packet throw an exception because they're fetching data
   past the end of the packet, so that the Info column doesn't have data
   left over from the previous dissector; do

    col_clear(pinfo->cinfo, COL_INFO);

   */

    if ( check_col(pinfo->cinfo, COL_INFO) )
    {
        col_add_fstr(pinfo->cinfo, COL_INFO, "MagicPacket for %s (%s)",
            get_ether_name(mac), ether_to_str(mac));

        /* NOTE: ether-wake uses a dotted-decimal format for specifying a
         * 4-byte password or an Ethernet mac address format for specifying
         * a 6-byte password, so display them in that format, even if the
         * password isn't really an IP or MAC address. */
        if ( passwd )
            col_append_fstr(pinfo->cinfo, COL_INFO, ", password %s", passwd);
    }

/* A protocol dissector can be called in 2 different ways:

    (a) Operational dissection

        In this mode, Wireshark is only interested in the way protocols
        interact, protocol conversations are created, packets are
        reassembled and handed over to higher-level protocol dissectors.
        In this mode Wireshark does not build a so-called "protocol
        tree".

    (b) Detailed dissection

        In this mode, Wireshark is also interested in all details of
        a given protocol, so a "protocol tree" is created.

   Wireshark distinguishes between the 2 modes with the proto_tree pointer:
    (a) <=> tree == NULL
    (b) <=> tree != NULL

   In the interest of speed, if "tree" is NULL, avoid building a
   protocol tree and adding stuff to it, or even looking at any packet
   data needed only if you're building the protocol tree, if possible.

   Note, however, that you must fill in column information, create
   conversations, reassemble packets, build any other persistent state
   needed for dissection, and call subdissectors regardless of whether
   "tree" is NULL or not.  This might be inconvenient to do without
   doing most of the dissection work; the routines for adding items to
   the protocol tree can be passed a null protocol tree pointer, in
   which case they'll return a null item pointer, and
   "proto_item_add_subtree()" returns a null tree pointer if passed a
   null item pointer, so, if you're careful not to dereference any null
   tree or item pointers, you can accomplish this by doing all the
   dissection work.  This might not be as efficient as skipping that
   work if you're not building a protocol tree, but if the code would
   have a lot of tests whether "tree" is null if you skipped that work,
   you might still be better off just doing all that work regardless of
   whether "tree" is null or not. */
    if (tree) {

/* NOTE: The offset and length values in the call to
   "proto_tree_add_item()" define what data bytes to highlight in the hex
   display window when the line in the protocol tree display
   corresponding to that item is selected.

   Supplying a length of -1 is the way to highlight all data from the
   offset to the end of the packet. */

/* create display subtree for the protocol */
        ti = proto_tree_add_item(tree, proto_wol, tvb, 0, len, FALSE);
        proto_item_append_text(ti, ", MAC: %s (%s)", get_ether_name(mac),
            ether_to_str(mac));
        if ( passwd )
            proto_item_append_text(ti, ", password: %s", passwd);
        wol_tree = proto_item_add_subtree(ti, ett_wol);

/* add an item to the subtree, see section 1.6 for more information */
        proto_tree_add_item(wol_tree, hf_wol_sync, tvb, 0, 6, FALSE);

/* Continue adding tree items to process the packet here */
        mti = proto_tree_add_text(wol_tree, tvb, 6, 96, "MAC: %s (%s)",
            get_ether_name(mac), ether_to_str(mac));
        mac_tree = proto_item_add_subtree(mti, ett_wol_macblock);
        for ( offset = 6; offset < 102; offset += 6 )
            proto_tree_add_ether(mac_tree, hf_wol_mac, tvb, offset, 6, mac);

        if ( len == 106 )
            proto_tree_add_bytes_format(wol_tree, hf_wol_passwd, tvb, offset,
                4, passwd, "Password: %s", passwd);
        else if ( len == 108 )
            proto_tree_add_bytes_format(wol_tree, hf_wol_passwd, tvb, offset,
                6, passwd, "Password: %s", passwd);
    }

/* If this protocol has a sub-dissector call it here, see section 1.8 */

/* Return the amount of data this dissector was able to dissect */
    if ( pinfo->ethertype == ETHERTYPE_WOL )
        return (len);

    /* Heuristic dissectors return TRUE/FALSE. */
    return (TRUE);
}
예제 #18
0
static int dissect_pbb_tlvblock(tvbuff_t *tvb, proto_tree *tree, guint offset,
    guint maxoffset, gint8 addrCount) {
  guint16 tlvblockLength;
  guint tlvblockEnd;

  proto_tree *tlvblock_tree = NULL;
  proto_tree *tlv_tree = NULL;
  proto_tree *tlv_flags_tree = NULL;
  proto_tree *tlvValue_tree = NULL;

  proto_item *tlvBlock_item = NULL;
  proto_item *tlv_item = NULL;
  proto_item *tlvFlags_item = NULL;
  proto_item *tlvValue_item = NULL;
  proto_item *ti = NULL;

  int tlvCount = 0;

  if (maxoffset < offset + 2) {
    proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
        tvb_get_ptr(tvb, offset, maxoffset - offset), "Not enough octets for minimal tlvblock");
    return maxoffset;
  }

  tlvblockLength = tvb_get_ntohs(tvb, offset);

  tlvblockEnd = offset + 2 + tlvblockLength;
  if (maxoffset < tlvblockEnd) {
    proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, maxoffset - offset,
        tvb_get_ptr(tvb, offset, maxoffset - offset), "Not enough octets for tlvblock");
    return maxoffset;
  }

  tlvBlock_item = proto_tree_add_item(tree, hf_packetbb_tlvblock, tvb, offset, tlvblockEnd - offset, FALSE);
  tlvblock_tree = proto_item_add_subtree(tlvBlock_item, ett_packetbb_tlvblock);

  proto_tree_add_item(tlvblock_tree, hf_packetbb_tlvblock_length, tvb, offset, 2, FALSE);

  offset += 2;
  while (offset < tlvblockEnd) {
    guint tlvStart, tlvLength;
    guint8 tlvType, tlvFlags, tlvExtType, indexStart, indexEnd;
    guint16 length = 0;

    tlvStart = offset;
    tlvType = tvb_get_guint8(tvb, offset++);
    tlvFlags = tvb_get_guint8(tvb, offset++);

    indexStart = 0;
    indexEnd = addrCount;
    tlvExtType = 0;

    if ((tlvFlags & TLV_HAS_TYPEEXT) != 0) {
      tlvExtType = tvb_get_guint8(tvb, offset++);
    }

    if ((tlvFlags & TLV_HAS_SINGLEINDEX) != 0) {
      indexStart = indexEnd = tvb_get_guint8(tvb, offset++);
    }
    else if ((tlvFlags & TLV_HAS_MULTIINDEX) != 0) {
      indexStart = tvb_get_guint8(tvb, offset++);
      indexEnd = tvb_get_guint8(tvb, offset++);
    }

    if ((tlvFlags & TLV_HAS_VALUE) != 0) {
      if ((tlvFlags & TLV_HAS_EXTLEN) != 0) {
        length = tvb_get_ntohs(tvb, offset++);
      }
      else {
        length = tvb_get_guint8(tvb, offset++);
      }
    }

    tlvLength = offset - tlvStart + length;
    offset = tlvStart;

    tlv_item = proto_tree_add_item(tlvBlock_item, hf_packetbb_tlv, tvb, tlvStart, tlvLength, FALSE);
    tlv_tree = proto_item_add_subtree(tlv_item, ett_packetbb_tlv[tlvType]);

    if ((tlvFlags & TLV_HAS_TYPEEXT) == 0) {
      proto_item_append_text(tlv_item, " (%d)", tlvType);
    }
    else {
      proto_item_append_text(tlv_item, " (%d/%d)", tlvType, tlvExtType);
    }

    /* add type */
    proto_tree_add_item(tlv_tree, hf_packetbb_tlv_type, tvb, offset++, 1, FALSE);

    /* add flags */
    tlvFlags_item = proto_tree_add_item(tlv_tree, hf_packetbb_tlv_flags, tvb, offset, 1, FALSE);
    tlv_flags_tree = proto_item_add_subtree(tlvFlags_item, ett_packetbb_tlv_flags);

    proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hastypext, tvb, offset, 1, FALSE);
    proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hassingleindex, tvb, offset, 1, FALSE);
    proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasmultiindex, tvb, offset, 1, FALSE);
    proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasvalue, tvb, offset, 1, FALSE);
    proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasextlen, tvb, offset, 1, FALSE);
    proto_tree_add_item(tlv_flags_tree, hf_packetbb_tlv_flags_hasmultivalue, tvb, offset, 1, FALSE);
    offset++;

    if ((tlvFlags & TLV_HAS_TYPEEXT) != 0) {
      /* add ext-type */
      proto_tree_add_item(tlv_tree, hf_packetbb_tlv_typeext, tvb, offset++, 1, FALSE);
    }

    if (addrCount > 0) {
      /* add index values */
      if ((tlvFlags & TLV_HAS_SINGLEINDEX) != 0) {
        proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexstart, tvb, offset++, 1, indexStart);

        ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexend, tvb, offset, 0, indexEnd);
        proto_item_append_text(ti, " (implicit)");
      }
      else if ((tlvFlags & TLV_HAS_MULTIINDEX) != 0) {
        proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexstart, tvb, offset++, 1, indexStart);
        proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexend, tvb, offset++, 1, indexEnd);
      }
      else {
        ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexstart, tvb, offset, 0, indexStart);
        proto_item_append_text(ti, " (implicit)");

        ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_indexend, tvb, offset, 0, indexEnd);
        proto_item_append_text(ti, " (implicit)");
      }
    }

    /* add length */
    if ((tlvFlags & TLV_HAS_VALUE) != 0) {
      if ((tlvFlags & TLV_HAS_EXTLEN) != 0) {
        proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_length, tvb, offset, 2, length);
        offset += 2;
      }
      else {
        proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_length, tvb, offset++, 1, length);
      }
    }
    else {
      ti = proto_tree_add_uint(tlv_tree, hf_packetbb_tlv_length, tvb, offset, 0, 0);
      proto_item_append_text(ti, " (implicit)");
    }

    if (length > 0) {
      /* add value */
      tlvValue_item = proto_tree_add_item(tlv_tree, hf_packetbb_tlv_value, tvb, offset, length, FALSE);

      if ((tlvFlags & TLV_HAS_MULTIVALUE) == 0) {
        offset += length;
      }
      else {
        int i;
        guint8 c = indexEnd - indexStart + 1;
        tlvValue_tree = proto_item_add_subtree(tlvValue_item, ett_packetbb_tlv_value);

        for (i=indexStart; i<=indexEnd; i++) {
          proto_tree_add_item(tlvValue_tree, hf_packetbb_tlv_multivalue, tvb, offset, length/c, FALSE);
          offset += (length/c);
        }
      }
    }
    tlvCount++;
  }

  proto_item_append_text(tlvBlock_item, " (%d TLVs)", tlvCount);

  return offset;
}
예제 #19
0
static void
dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_tree     *clnp_tree = NULL;
  proto_item     *ti;
  guint8          cnf_proto_id;
  guint8          cnf_hdr_len;
  guint8          cnf_vers;
  guint8          cnf_ttl;
  guint8          cnf_type;
  char            flag_string[6+1];
  const char     *pdu_type_string;
  proto_tree     *type_tree;
  guint16         segment_length;
  guint16         du_id = 0;
  guint16         segment_offset = 0;
  guint16         cnf_cksum;
  cksum_status_t  cksum_status;
  int             offset;
  guchar          src_len, dst_len, nsel, opt_len = 0;
  const guint8   *dst_addr, *src_addr;
  guint           next_length;
  proto_tree     *discpdu_tree;
  gboolean        save_in_error_pkt;
  fragment_data  *fd_head;
  tvbuff_t       *next_tvb;
  gboolean        update_col_info = TRUE;
  gboolean        save_fragmented;

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

  cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
  if (cnf_proto_id == NLPID_NULL) {
    col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
    if (tree) {
      ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA);
      clnp_tree = proto_item_add_subtree(ti, ett_clnp);
      proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
                                 cnf_proto_id,
                                 "Inactive subset");
    }
    next_tvb = tvb_new_subset_remaining(tvb, 1);
    if (call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree) == 0)
      call_dissector(data_handle,tvb, pinfo, tree);
    return;
  }

  /* return if version not known */
  cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
  if (cnf_vers != ISO8473_V1) {
    call_dissector(data_handle,tvb, pinfo, tree);
    return;
  }

  /* fixed part decoding */
  cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
  opt_len = cnf_hdr_len;

  if (tree) {
    ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA);
    clnp_tree = proto_item_add_subtree(ti, ett_clnp);
    proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
                        cnf_proto_id);
    proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
                        cnf_hdr_len);
    proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
                        cnf_vers);
    cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
    proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
                               cnf_ttl,
                               "Holding Time : %u (%u.%u secs)",
                               cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
  }

  cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
  pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
                               "Unknown (0x%02x)");
  flag_string[0] = '\0';
  if (cnf_type & CNF_SEG_OK)
    g_strlcat(flag_string, "S ", 7);
  if (cnf_type & CNF_MORE_SEGS)
    g_strlcat(flag_string, "M ", 7);
  if (cnf_type & CNF_ERR_OK)
    g_strlcat(flag_string, "E ", 7);
  if (tree) {
    ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
                                    cnf_type,
                                    "PDU Type     : 0x%02x (%s%s)",
                                    cnf_type,
                                    flag_string,
                                    pdu_type_string);
    type_tree = proto_item_add_subtree(ti, ett_clnp_type);
    proto_tree_add_item(type_tree, hf_clnp_cnf_segmentation, tvb, P_CLNP_TYPE, 1, ENC_NA);
    proto_tree_add_item(type_tree, hf_clnp_cnf_more_segments, tvb, P_CLNP_TYPE, 1, ENC_NA);
    proto_tree_add_item(type_tree, hf_clnp_cnf_report_error, tvb, P_CLNP_TYPE, 1, ENC_NA);
    proto_tree_add_item(type_tree, hf_clnp_cnf_type, tvb, P_CLNP_TYPE, 1, ENC_NA);
  }

  /* If we don't have the full header - i.e., not enough to see the
     segmentation part and determine whether this datagram is segmented
     or not - set the Info column now; we'll get an exception before
     we set it otherwise. */

  if (tvb_length(tvb) < cnf_hdr_len) {
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
  }

  segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
  cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
  cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
  if (tree) {
    proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
                        segment_length);
    switch (cksum_status) {

    default:
      /*
       * No checksum present, or not enough of the header present to
       * checksum it.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x",
                                 cnf_cksum);
      break;

    case CKSUM_OK:
      /*
       * Checksum is correct.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x (correct)",
                                 cnf_cksum);
      break;

    case CKSUM_NOT_OK:
      /*
       * Checksum is not correct.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x (incorrect)",
                                 cnf_cksum);
      break;
    }
    opt_len -= 9; /* Fixed part of Hesder */
  } /* tree */

  /* address part */

  offset = P_CLNP_ADDRESS_PART;
  dst_len  = tvb_get_guint8(tvb, offset);
  dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len);
  nsel     = tvb_get_guint8(tvb, offset + dst_len);
  src_len  = tvb_get_guint8(tvb, offset + dst_len + 1);
  src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);

  if (tree) {
    proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
                        dst_len);
    proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len,
                                dst_addr,
                                " DA : %s",
                                print_nsap_net(dst_addr, dst_len));
    proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
                        offset + 1 + dst_len, 1, src_len);
    proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
                                offset + dst_len + 2, src_len,
                                src_addr,
                                " SA : %s",
                                print_nsap_net(src_addr, src_len));

    opt_len -= dst_len + src_len +2;
  }

  SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
  SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
  SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
  SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);

  /* Segmentation Part */

  offset += dst_len + src_len + 2;

  if (cnf_type & CNF_SEG_OK) {
#if 0
    struct clnp_segment seg;                                /* XXX - not used */
    tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg));   /* XXX - not used */
#endif

    segment_offset = tvb_get_ntohs(tvb, offset + 2);
    du_id = tvb_get_ntohs(tvb, offset);
    if (tree) {
      proto_tree_add_text(clnp_tree, tvb, offset, 2,
                          "Data unit identifier: %06u",
                          du_id);
      proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
                          "Segment offset      : %6u",
                          segment_offset);
      proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
                          "Total length        : %6u",
                          tvb_get_ntohs(tvb, offset + 4));
    }

    offset  += 6;
    opt_len -= 6;
  }

  if (tree) {
    /* To do : decode options  */
#if 0
    proto_tree_add_text(clnp_tree, tvb, offset,
                        cnf_hdr_len - offset,
                        "Options/Data: <not shown>");
#endif
/* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/

    dissect_osi_options( opt_len,
                         tvb, offset, clnp_tree );
  }

  offset += opt_len;

  /* If clnp_reassemble is on, this is a segment, we have all the
   * data in the segment, and the checksum is valid, then just add the
   * segment to the hashtable.
   */
  save_fragmented = pinfo->fragmented;
  if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
      ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
      tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
      segment_length > cnf_hdr_len &&
      cksum_status != CKSUM_NOT_OK) {
    fd_head = fragment_add_check(tvb, offset, pinfo, du_id, clnp_segment_table,
                                 clnp_reassembled_table, segment_offset,
                                 segment_length - cnf_hdr_len,
                                 cnf_type & CNF_MORE_SEGS);

    next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
                                        fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
  } else {
    /* If this is the first segment, dissect its contents, otherwise
       just show it as a segment.

       XXX - if we eventually don't save the reassembled contents of all
       segmented datagrams, we may want to always reassemble. */
    if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
      /* Not the first segment - don't dissect it. */
      next_tvb = NULL;
    } else {
      /* First segment, or not segmented.  Dissect what we have here. */

      /* Get a tvbuff for the payload. */
      next_tvb = tvb_new_subset_remaining(tvb, offset);

      /*
       * If this is the first segment, but not the only segment,
       * tell the next protocol that.
       */
      if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
        pinfo->fragmented = TRUE;
      else
        pinfo->fragmented = FALSE;
    }
  }

  if (next_tvb == NULL) {
    /* Just show this as a segment. */
    col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
                 pdu_type_string, flag_string, segment_offset);

    /* As we haven't reassembled anything, we haven't changed "pi", so
       we don't have to restore it. */
    call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo,
                   tree);
    pinfo->fragmented = save_fragmented;
    return;
  }

  if (tvb_offset_exists(tvb, offset)) {
    switch (cnf_type & CNF_TYPE) {

    case DT_NPDU:
    case MD_NPDU:
      /* Continue with COTP if any data.
         XXX - if this isn't the first Derived PDU of a segmented Initial
         PDU, skip that? */

      if (nsel == (guchar)tp_nsap_selector || always_decode_transport) {
        if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) {
          pinfo->fragmented = save_fragmented;
          return;       /* yes, it appears to be COTP or CLTP */
        }
      }
      if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
                                  pinfo, tree, NULL)) {
          pinfo->fragmented = save_fragmented;
          return;       /* yes, it appears to be one of the protocols in the heuristic list */
      }

      break;

    case ER_NPDU:
      /* The payload is the header and "none, some, or all of the data
         part of the discarded PDU", i.e. it's like an ICMP error;
         dissect it as a CLNP PDU. */

      col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
      next_length = tvb_length_remaining(tvb, offset);
      if (next_length != 0) {
          /* We have payload; dissect it. */
          ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length,
            "Discarded PDU");
          discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu);

          /* Save the current value of the "we're inside an error packet"
             flag, and set that flag; subdissectors may treat packets
             that are the payload of error packets differently from
             "real" packets. */
          save_in_error_pkt = pinfo->flags.in_error_pkt;
          pinfo->flags.in_error_pkt = TRUE;

          call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);

          /* Restore the "we're inside an error packet" flag. */
          pinfo->flags.in_error_pkt = save_in_error_pkt;
      }
      pinfo->fragmented = save_fragmented;
      return;   /* we're done with this PDU */

    case ERQ_NPDU:
    case ERP_NPDU:
      /* XXX - dissect this */
      break;
    }
  }
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
  call_dissector(data_handle,next_tvb, pinfo, tree);
  pinfo->fragmented = save_fragmented;
} /* dissect_clnp */
예제 #20
0
static int dissect_pbb_message(tvbuff_t *tvb, proto_tree *tree, guint offset) {
  proto_tree *message_tree = NULL;
  proto_tree *header_tree = NULL;
  proto_tree *headerFlags_tree = NULL;

  proto_item *message_item = NULL;
  proto_item *header_item = NULL;
  proto_item *headerFlags_item = NULL;

  guint8 messageType;
  guint8 messageFlags;
  guint16 messageLength, headerLength, messageEnd;
  guint8 addressSize, addressType;

  if (tvb_reported_length(tvb) - offset < 6) {
    proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, -1,
        tvb_get_ptr(tvb, offset, -1), "Not enough octets for minimal message header");
    return tvb_reported_length(tvb);
  }

  messageType = tvb_get_guint8(tvb, offset);
  messageFlags = tvb_get_guint8(tvb, offset+1);
  messageLength = tvb_get_ntohs(tvb, offset+2);
  addressSize = (messageFlags & 0x0f) + 1;

  switch (addressSize) {
    case 4:
      addressType = 0;
      break;
    case 16:
      addressType = 1;
      break;
    case 6:
      addressType = 2;
      break;
    default:
      addressType = 3;
      break;
  }

  messageEnd = offset + messageLength;

  headerLength = 4;

  /* calculate header size */
  if ((messageFlags & MSG_HEADER_HASORIG) != 0) {
    headerLength += addressSize;
  }
  if ((messageFlags & MSG_HEADER_HASHOPLIMIT) != 0) {
    headerLength ++;
  }
  if ((messageFlags & MSG_HEADER_HASHOPCOUNT) != 0) {
    headerLength ++;
  }
  if ((messageFlags & MSG_HEADER_HASSEQNR) != 0) {
    headerLength += 2;
  }

  /* test length for message size */
  if (tvb_reported_length(tvb) - offset < messageLength) {
    proto_tree_add_bytes_format(tree, hf_packetbb_error, tvb, offset, -1,
        tvb_get_ptr(tvb, offset, -1), "Not enough octets for message");
    return tvb_reported_length(tvb);
  }

  message_item = proto_tree_add_item(tree, hf_packetbb_msg, tvb, offset, messageLength, FALSE);
  message_tree = proto_item_add_subtree(message_item, ett_packetbb_msg[messageType]);
  proto_item_append_text(message_item, " (type %d)", messageType);

  header_item = proto_tree_add_item(message_tree, hf_packetbb_msgheader, tvb, offset, headerLength, FALSE);
  header_tree = proto_item_add_subtree(header_item, ett_packetbb_msgheader);

  /* type */
  proto_tree_add_item(header_tree, hf_packetbb_msgheader_type, tvb, offset, 1, FALSE);

  /* flags */
  headerFlags_item = proto_tree_add_uint(header_tree, hf_packetbb_msgheader_flags,
      tvb, offset+1, 1, messageFlags & 0xf8);

  headerFlags_tree = proto_item_add_subtree(headerFlags_item, ett_packetbb_msgheader_flags);
  proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhasorig,
      tvb, offset+1, 1, messageFlags);
  proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhashoplimit,
      tvb, offset+1, 1, messageFlags);
  proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhashopcount,
      tvb, offset+1, 1, messageFlags);
  proto_tree_add_boolean(headerFlags_tree, hf_packetbb_msgheader_flags_mhasseqnr,
      tvb, offset+1, 1, messageFlags);

  proto_tree_add_uint(header_tree, hf_packetbb_msgheader_addresssize,
      tvb, offset + 1, 1, (messageFlags & 0x0f) + 1);

  /* size */
  proto_tree_add_item(header_tree, hf_packetbb_msgheader_size, tvb, offset+2, 2, FALSE);

  offset += 4;

  /* originator address */
  if ((messageFlags & MSG_HEADER_HASORIG) != 0) {
    proto_tree_add_item(header_tree, hf_packetbb_msgheader_origaddr[addressType],
        tvb, offset, addressSize, FALSE);
    offset += addressSize;
  }

  /* hop limit */
  if ((messageFlags & MSG_HEADER_HASHOPLIMIT) != 0) {
    proto_tree_add_item(header_tree, hf_packetbb_msgheader_hoplimit, tvb, offset++, 1, FALSE);
  }

  /* hop count */
  if ((messageFlags & MSG_HEADER_HASHOPCOUNT) != 0) {
    proto_tree_add_item(header_tree, hf_packetbb_msgheader_hopcount, tvb, offset++, 1, FALSE);
  }

  /* sequence number */
  if ((messageFlags & MSG_HEADER_HASSEQNR) != 0) {
    proto_tree_add_item(header_tree, hf_packetbb_msgheader_seqnr, tvb, offset, 2, FALSE);
    offset += 2;
  }

  offset = dissect_pbb_tlvblock(tvb, message_tree, offset, messageEnd, 0);
  while (offset < messageEnd) {
    offset = dissect_pbb_addressblock(tvb, message_tree, offset, messageEnd, addressType, addressSize);
  }
  return offset;
}
예제 #21
0
void dissect_nhrp_ext(tvbuff_t *tvb,
					  packet_info *pinfo,
					  proto_tree *tree,
					  gint *pOffset,
					  gint extLen,
					  e_nhrp_hdr *hdr,
					  guint srcLen,
					  gboolean nested)
{
	gint	offset = *pOffset;
	gint	extEnd = offset + extLen;

	proto_item *nhrp_tree_item = NULL;
	proto_tree *nhrp_tree = NULL;
	proto_item *ti = NULL;

	tvb_ensure_bytes_exist(tvb, offset, extLen);

	while ((offset + 4) <= extEnd)
	{
		gint extTypeC = tvb_get_ntohs(tvb, offset);
		gint extType = extTypeC & 0x3FFF;
		guint len  = tvb_get_ntohs(tvb, offset+2);

		if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) {
			/* Assume it's not really a Cisco NAT extension, but a device
			 * capabilities extension instead (see RFC 2735). */
			nhrp_tree_item =  proto_tree_add_text(tree, tvb, offset,
				len + 4, "Device Capabilities Extension");
		}
		else {
			nhrp_tree_item =  proto_tree_add_text(tree, tvb, offset,
				len + 4, "%s",
				val_to_str(extType, ext_type_vals, "Unknown (%u)"));
		}
		nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_ext);
		proto_tree_add_boolean(nhrp_tree, hf_nhrp_ext_C, tvb, offset, 2, extTypeC);
		proto_tree_add_item(nhrp_tree, hf_nhrp_ext_type, tvb, offset, 2, FALSE);
		offset += 2;

		proto_tree_add_item(nhrp_tree, hf_nhrp_ext_len, tvb, offset, 2, FALSE);
		offset += 2;

		if (len && (extType != NHRP_EXT_NULL)) {
			tvb_ensure_bytes_exist(tvb, offset, len);
			if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) {
				/* Assume it's not really a Cisco NAT extension, but a device
				 * capabilities extension instead (see RFC 2735). */
				proto_item *devcap_item;
				proto_tree *devcap_tree;
				proto_item *cap_item;
				proto_tree *cap_tree;

				devcap_item = proto_tree_add_text(nhrp_tree, tvb, offset, len,
					"Extension Data: Src is %sVPN-aware; Dst is %sVPN-aware",
					tvb_get_ntohl(tvb, offset) & 1 ? "" : "non-",
					tvb_get_ntohl(tvb, offset + 4) & 1 ? "" : "non-");
				devcap_tree = proto_item_add_subtree(devcap_item, ett_nhrp_devcap_ext);
				cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_srccap, tvb, offset, 4, FALSE);
				cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_srccap);
				proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_srccap_V, tvb, offset, 4, FALSE);

				cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_dstcap, tvb, offset + 4, 4, FALSE);
				cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_dstcap);
				proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_dstcap_V, tvb, offset + 4, 4, FALSE);
				goto skip_switch;
			}

			switch (extType) {
			case NHRP_EXT_RESP_ADDR:
			case NHRP_EXT_FWD_RECORD:
			case NHRP_EXT_REV_RECORD:
			case NHRP_EXT_NAT_ADDRESS:
				dissect_cie_list(tvb, pinfo, nhrp_tree,
				    offset, offset + len, hdr, 0, FALSE);
				break;

			case NHRP_EXT_AUTH:
			case NHRP_EXT_MOBILE_AUTH:
				if (len < (4 + srcLen)) {
					ti = proto_tree_add_text(nhrp_tree, tvb, offset, len,
						"Malformed Extension: %s",
						tvb_bytes_to_str(tvb, offset, len));
					expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
						"Incomplete Authentication Extension");
				}
				else {
					proto_item *auth_item;
					proto_tree *auth_tree;

					auth_item = proto_tree_add_text(nhrp_tree, tvb, offset, len,
						"Extension Data: SPI=%u: Data=%s", tvb_get_ntohs(tvb, offset + 2),
						tvb_bytes_to_str(tvb, offset + 4, len - 4));
					auth_tree = proto_item_add_subtree(auth_item, ett_nhrp_auth_ext);
					proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_reserved, tvb, offset, 2, FALSE);
					proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_spi, tvb, offset + 2, 2, FALSE);
					if (srcLen == 4)
						proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_src_addr, tvb, offset + 4, 4, FALSE);
					else if (srcLen) {
						proto_tree_add_text(auth_tree, tvb, offset + 4, srcLen,
							"Source Address: %s",
							tvb_bytes_to_str(tvb, offset + 4, srcLen));
					}
					if (len > (4 + srcLen)) {
						proto_tree_add_text(auth_tree, tvb, offset + 4 + srcLen, len - (4 + srcLen),
							"Data: %s", tvb_bytes_to_str(tvb, offset + 4 + srcLen, len - (4 + srcLen)));
					}
				}
				break;

			case NHRP_EXT_VENDOR_PRIV:
				if (len < 3) {
					ti = proto_tree_add_text(nhrp_tree, tvb, offset, len,
						"Malformed Extension: %s",
						tvb_bytes_to_str(tvb, offset, len));
					expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
						"Incomplete Vendor-Private Extension");
				}
				else {
					proto_item *vendor_item;
					proto_tree *vendor_tree;
					gchar manuf[3];

					tvb_memcpy(tvb, manuf, offset, 3);
					vendor_item = proto_tree_add_text(nhrp_tree, tvb, offset, len,
						"Extension Data: Vendor ID=%s, Data=%s", get_manuf_name(manuf),
						tvb_bytes_to_str(tvb, offset + 3, len - 3));
					vendor_tree = proto_item_add_subtree(vendor_item, ett_nhrp_vendor_ext);
					proto_tree_add_bytes_format(vendor_tree, hf_nhrp_vendor_ext_id, tvb,
						offset, 3, manuf, "Vendor ID: %s", get_manuf_name(manuf));
					if (len > 3) {
						proto_tree_add_text(vendor_tree, tvb, offset + 3, len - 3,
							"Data: %s", tvb_bytes_to_str(tvb, offset + 3, len - 3));
					}
				}
				break;

			default:
				proto_tree_add_text(nhrp_tree, tvb, offset, len,
					"Extension Value: %s",
					tvb_bytes_to_str(tvb, offset, len));
				break;
			}
skip_switch:
			offset += len;
		}

		if (!nested) {
			len = tvb_reported_length_remaining(tvb, offset);
			if ((extType == NHRP_EXT_NULL) && len) {
				ti = proto_tree_add_text(tree, tvb, offset, len,
					"Unknown Data (%d bytes)", len);
				expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
					"Superfluous data follows End Extension");
				break;
			}
		}
	}

	*pOffset = extEnd;
}
예제 #22
0
/*
 * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
 */
static void
dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint16     ar_hrd;
  guint16     ar_pro;
  guint8      ar_shtl;
  guint8      ar_shl;
  guint8      ar_sstl;
  guint8      ar_ssl;
  guint16     ar_op;
  guint8      ar_spln;
  guint8      ar_thtl;
  guint8      ar_thl;
  guint8      ar_tstl;
  guint8      ar_tsl;
  guint8      ar_tpln;
  int         tot_len;
  proto_tree  *arp_tree;
  proto_item  *ti;
  const gchar *op_str;
  int         sha_offset, ssa_offset, spa_offset;
  int         tha_offset, tsa_offset, tpa_offset;
  const guint8      *sha_val, *ssa_val, *spa_val;
  const guint8      *tha_val, *tsa_val, *tpa_val;
  const gchar       *sha_str, *ssa_str, *spa_str;
  const gchar       *tha_str, *tsa_str, *tpa_str;
  proto_tree  *tl_tree;
  proto_item  *tl;

  /* Override the setting to "ARP/RARP". */
  pinfo->current_proto = "ATMARP";

  ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
  ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
  ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
  ar_shl = ar_shtl & ATMARP_LEN_MASK;
  ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
  ar_ssl = ar_sstl & ATMARP_LEN_MASK;
  ar_op  = tvb_get_ntohs(tvb, AR_OP);
  ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
  ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
  ar_thl = ar_thtl & ATMARP_LEN_MASK;
  ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
  ar_tsl = ar_tstl & ATMARP_LEN_MASK;
  ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);

  tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
    ar_thl + ar_tsl + ar_tpln;

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

  /* Extract the addresses.  */
  sha_offset = MIN_ATMARP_HEADER_SIZE;
  if (ar_shl != 0) {
    sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
    sha_str = atmarpnum_to_str(sha_val, ar_shtl);
  } else {
    sha_val = NULL;
    sha_str = "<No address>";
  }

  ssa_offset = sha_offset + ar_shl;
  if (ar_ssl != 0) {
    ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
    ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
  } else {
    ssa_val = NULL;
    ssa_str = NULL;
  }

  spa_offset = ssa_offset + ar_ssl;
  spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
  spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);

  tha_offset = spa_offset + ar_spln;
  if (ar_thl != 0) {
    tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
    tha_str = atmarpnum_to_str(tha_val, ar_thtl);
  } else {
    tha_val = NULL;
    tha_str = "<No address>";
  }

  tsa_offset = tha_offset + ar_thl;
  if (ar_tsl != 0) {
    tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
    tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
  } else {
    tsa_val = NULL;
    tsa_str = NULL;
  }

  tpa_offset = tsa_offset + ar_tsl;
  tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
  tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);

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

      case ARPOP_REQUEST:
      case ARPOP_REPLY:
      case ATMARPOP_NAK:
      default:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
        break;

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

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

  if (check_col(pinfo->cinfo, COL_INFO)) {
    switch (ar_op) {
      case ARPOP_REQUEST:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
                     tpa_str, spa_str);
        break;
      case ARPOP_REPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
                     ((ssa_str != NULL) ? "," : ""),
                     ((ssa_str != NULL) ? ssa_str : ""));
        break;
      case ARPOP_IREQUEST:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s?  Tell %s%s%s",
                     tha_str,
                     ((tsa_str != NULL) ? "," : ""),
                     ((tsa_str != NULL) ? tsa_str : ""),
                     sha_str,
                     ((ssa_str != NULL) ? "," : ""),
                     ((ssa_str != NULL) ? ssa_str : ""));
        break;
      case ARPOP_IREPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
                     sha_str,
                     ((ssa_str != NULL) ? "," : ""),
                     ((ssa_str != NULL) ? ssa_str : ""),
                     spa_str);
        break;
      case ATMARPOP_NAK:
        col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
        break;
      default:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
        break;
    }
  }

  if (tree) {
    if ((op_str = match_strval(ar_op, atmop_vals)))
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "ATM Address Resolution Protocol (%s)",
                                          op_str);
    else
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "ATM 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, ATM_AR_HRD, 2, ar_hrd);

    proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
                             "Sender ATM number type/length: %s/%u",
                             (ar_shtl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_shl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
    proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
                             "Sender ATM subaddress type/length: %s/%u",
                             (ar_sstl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_ssl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
    proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);

    proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);


    proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
                             "Target ATM number type/length: %s/%u",
                             (ar_thtl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_thl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
    proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
                             "Target ATM subaddress type/length: %s/%u",
                             (ar_tstl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_tsl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
    proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);

    proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);

    if (ar_shl != 0)
      dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
                         hf_atmarp_src_atm_num_nsap, arp_tree);

    if (ar_ssl != 0)
      proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
                                  ar_ssl,
                                  ssa_val,
                                  "Sender ATM subaddress: %s", ssa_str);

    if (ar_spln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
                          : hf_arp_src_proto,
                          tvb, spa_offset, ar_spln, FALSE);
    }

    if (ar_thl != 0)
      dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
                         hf_atmarp_dst_atm_num_nsap, arp_tree);

    if (ar_tsl != 0)
      proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
                                  ar_tsl,
                                  tsa_val,
                                  "Target ATM subaddress: %s", tsa_str);

    if (ar_tpln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
                          : hf_arp_dst_proto,
                          tvb, tpa_offset, ar_tpln, FALSE);
    }
  }
}
예제 #23
0
/* Transfers happen in response to broadcasts, they are always TCP and are
 * used to send the file to the port mentioned in the broadcast. There are
 * 2 types of transfers: Pushes, which are direct responses to searches,
 * in which the peer that has the file connects to the peer that doesn't and
 * sends it, then disconnects. The other type of transfer is a pull, where
 * the peer that doesn't have the file connects to the peer that does and
 * requests it be sent.
 *
 * Pulls have a file request which identifies the desired file,
 * while pushes simply send the file. In practice this works because every
 * file the implementation sends searches for is on a different TCP port
 * on the searcher's machine. */
static int
dissect_ldss_transfer (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
	conversation_t *transfer_conv;
	ldss_transfer_info_t *transfer_info;
	struct tcpinfo *transfer_tcpinfo;
	proto_tree *ti, *line_tree = NULL, *ldss_tree = NULL;
	nstime_t broadcast_response_time;

	/* Reject the packet if data is NULL */
	if (data == NULL)
		return 0;
	transfer_tcpinfo = (struct tcpinfo *)data;

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

	/* Look for the transfer conversation; this was created during
	 * earlier broadcast dissection (see prepare_ldss_transfer_conv) */
	transfer_conv = find_conversation (pinfo->num, &pinfo->src, &pinfo->dst,
					   PT_TCP, pinfo->srcport, pinfo->destport, 0);
	transfer_info = (ldss_transfer_info_t *)conversation_get_proto_data(transfer_conv, proto_ldss);

	/* For a pull, the first packet in the TCP connection is the file request.
	 * First packet is identified by relative seq/ack numbers of 1.
	 * File request only appears on a pull (triggered by an offer - see above
	 * about broadcasts) */
	if (transfer_tcpinfo->seq == 1 &&
	    transfer_tcpinfo->lastackseq == 1 &&
	    transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND) {
		/* LDSS pull transfers look a lot like HTTP.
		 * Sample request:
		 * md5:01234567890123...
		 * Size: 2550
		 * Start: 0
		 * Compression: 0
		 * (remote end sends the file identified by the digest) */
		guint offset = 0;
		gboolean already_dissected = TRUE;

		col_set_str(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Requesting file - pull)");

		if (highest_num_seen == 0 ||
		    highest_num_seen < pinfo->num) {

			already_dissected = FALSE;
			transfer_info->req = wmem_new0(wmem_file_scope(), ldss_file_request_t);
			transfer_info->req->file = wmem_new0(wmem_file_scope(), ldss_file_t);
			highest_num_seen = pinfo->num;
		}

		if (tree) {
			ti = proto_tree_add_item(tree, proto_ldss,
						 tvb, 0, tvb_reported_length(tvb), ENC_NA);
			ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer);
		}

		/* Populate digest data into the file struct in the request */
		transfer_info->file = transfer_info->req->file;

		/* Grab each line from the packet, there should be 4 but lets
		 * not walk off the end looking for more. */
		while (tvb_offset_exists(tvb, offset)) {
			gint next_offset;
			const guint8 *line;
			int linelen;
			gboolean is_digest_line;
			guint digest_type_len;

			linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);

			/* Include new-line in line */
			line = (guint8 *)tvb_memdup(NULL, tvb, offset, linelen+1); /* XXX - memory leak? */

			line_tree = proto_tree_add_subtree(ldss_tree, tvb, offset, linelen,
							 ett_ldss_transfer_req, NULL,
							 tvb_format_text(tvb, offset, next_offset-offset));

			/* Reduce code duplication processing digest lines.
			 * There are too many locals to pass to a function - the signature
			 * looked pretty ugly when I tried! */
			is_digest_line = FALSE;

			if (strncmp(line,"md5:",4)==0) {
				is_digest_line = TRUE;
				digest_type_len = 4;
				transfer_info->file->digest_type = DIGEST_TYPE_MD5;
			}
			else if (strncmp(line, "sha1:", 5)==0) {
				is_digest_line = TRUE;
				digest_type_len = 5;
				transfer_info->file->digest_type = DIGEST_TYPE_SHA1;
			}
			else if (strncmp(line, "sha256:", 7)==0) {
				is_digest_line = TRUE;
				digest_type_len = 7;
				transfer_info->file->digest_type = DIGEST_TYPE_SHA256;
			}
			else if (strncmp(line, "unknown:", 8)==0) {
				is_digest_line = TRUE;
				digest_type_len = 8;
				transfer_info->file->digest_type = DIGEST_TYPE_UNKNOWN;
			}
			else if (strncmp(line, "Size: ", 6)==0) {
				/* Sample size line:
				 * Size: 2550\n */
				transfer_info->req->size = g_ascii_strtoull(line+6, NULL, 10);
				if (tree) {
					ti = proto_tree_add_uint64(line_tree, hf_ldss_size,
								   tvb, offset+6, linelen-6, transfer_info->req->size);
					PROTO_ITEM_SET_GENERATED(ti);
				}
			}
			else if (strncmp(line, "Start: ", 7)==0) {
				/* Sample offset line:
				 * Start: 0\n */
				transfer_info->req->offset = g_ascii_strtoull(line+7, NULL, 10);
				if (tree) {
					ti = proto_tree_add_uint64(line_tree, hf_ldss_offset,
								   tvb, offset+7, linelen-7, transfer_info->req->offset);
					PROTO_ITEM_SET_GENERATED(ti);
				}
			}
			else if (strncmp(line, "Compression: ", 13)==0) {
				/* Sample compression line:
				 * Compression: 0\n */
				transfer_info->req->compression = (gint8)strtol(line+13, NULL, 10); /* XXX - bad cast */
				if (tree) {
					ti = proto_tree_add_uint(line_tree, hf_ldss_compression,
								 tvb, offset+13, linelen-13, transfer_info->req->compression);
					PROTO_ITEM_SET_GENERATED(ti);
				}
			}
			else {
				proto_tree_add_expert(line_tree, pinfo, &ei_ldss_unrecognized_line, tvb, offset, linelen);
			}

			if (is_digest_line) {
				/* Sample digest-type/digest line:
				 * md5:0123456789ABCDEF\n */
				if (!already_dissected) {
					GByteArray *digest_bytes;

					digest_bytes = g_byte_array_new();
					hex_str_to_bytes(
						tvb_get_ptr(tvb, offset+digest_type_len, linelen-digest_type_len),
						digest_bytes, FALSE);

					if(digest_bytes->len >= DIGEST_LEN)
						digest_bytes->len = (DIGEST_LEN-1);
					/* Ensure the digest is zero-padded */
					transfer_info->file->digest = (guint8 *)wmem_alloc0(wmem_file_scope(), DIGEST_LEN);
					memcpy(transfer_info->file->digest, digest_bytes->data, digest_bytes->len);

					g_byte_array_free(digest_bytes, TRUE);
				}
				if (tree) {
					proto_item *tii = NULL;

					tii = proto_tree_add_uint(line_tree, hf_ldss_digest_type,
								 tvb, offset, digest_type_len, transfer_info->file->digest_type);
					PROTO_ITEM_SET_GENERATED(tii);
					tii = proto_tree_add_bytes(line_tree, hf_ldss_digest,
								  tvb, offset+digest_type_len, MIN(linelen-digest_type_len, DIGEST_LEN),
								  transfer_info->file->digest);
					PROTO_ITEM_SET_GENERATED(tii);
				}
			}

			offset = next_offset;
		}

		/* Link forwards to the response for this pull. */
		if (tree && transfer_info->resp_num != 0) {
			ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_in,
						 tvb, 0, 0, transfer_info->resp_num);
			PROTO_ITEM_SET_GENERATED(ti);
		}

		transfer_info->req->num = pinfo->num;
		transfer_info->req->ts = pinfo->abs_ts;
	}
	/* Remaining packets are the file response */
	else {
		guint64 size;
		guint64 offset;
		guint8 compression;

		/* size, digest, compression come from the file request for a pull but
		 * they come from the broadcast for a push. Pushes don't bother
		 * with a file request - they just send the data. We have to get file
		 * info from the offer broadcast which triggered this transfer.
		 * If we cannot find the file request, default to the broadcast. */
		if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND &&
		    transfer_info->req != NULL) {
			transfer_info->file = transfer_info->req->file;
			size = transfer_info->req->size;
			offset = transfer_info->req->offset;
			compression = transfer_info->req->compression;
		}
		else {
			transfer_info->file = transfer_info->broadcast->file;
			size = transfer_info->broadcast->size;
			offset = transfer_info->broadcast->offset;
			compression = transfer_info->broadcast->compression;
		}

		/* Remaining data in this TCP connection is all file data.
		 * Always desegment if the size is 0 (ie. unknown)
		 */
		if (pinfo->can_desegment) {
			if (size == 0 || tvb_captured_length(tvb) < size) {
				pinfo->desegment_offset = 0;
				pinfo->desegment_len = DESEGMENT_UNTIL_FIN;
				return 0;
			}
		}

		/* OK. Now we have the whole file that was transferred. */
		transfer_info->resp_num = pinfo->num;
		transfer_info->resp_ts = pinfo->abs_ts;

		col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Sending file - %s)",
				     transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND
				     ? "pull"
				     : "push");

		if (tree) {
			ti = proto_tree_add_item(tree, proto_ldss,
						 tvb, 0, tvb_reported_length(tvb), ENC_NA);
			ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer);
			proto_tree_add_bytes_format(ldss_tree, hf_ldss_file_data,
						    tvb, 0, tvb_captured_length(tvb), NULL,
						    compression == COMPRESSION_GZIP
						    ? "Gzip compressed data: %d bytes"
						    : "File data: %d bytes",
						    tvb_captured_length(tvb));
#ifdef HAVE_ZLIB
			/* Be nice and uncompress the file data. */
			if (compression == COMPRESSION_GZIP) {
				tvbuff_t *uncomp_tvb;
				uncomp_tvb = tvb_child_uncompress(tvb, tvb, 0, tvb_captured_length(tvb));
				if (uncomp_tvb != NULL) {
					/* XXX: Maybe not a good idea to add a data_source for
					        what may very well be a large buffer since then
						the full uncompressed buffer will be shown in a tab
						in the hex bytes pane ?
						However, if we don't, bytes in an unrelated tab will
						be highlighted.
					*/
					add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Data");
					proto_tree_add_bytes_format_value(ldss_tree, hf_ldss_file_data,
									  uncomp_tvb, 0, tvb_captured_length(uncomp_tvb),
									  NULL, "Uncompressed data: %d bytes",
									  tvb_captured_length(uncomp_tvb));
				}
			}
#endif
			ti = proto_tree_add_uint(ldss_tree, hf_ldss_digest_type,
						 tvb, 0, 0, transfer_info->file->digest_type);
			PROTO_ITEM_SET_GENERATED(ti);
			if (transfer_info->file->digest != NULL) {
				/* This is ugly. You can't add bytes of nonzero length and have
				 * filtering work correctly unless you give a valid location in
				 * the packet. This hack pretends the first 32 bytes of the packet
				 * are the digest, which they aren't: they're actually the first 32
				 * bytes of the file that was sent. */
				ti = proto_tree_add_bytes(ldss_tree, hf_ldss_digest,
							  tvb, 0, DIGEST_LEN, transfer_info->file->digest);
			}
			PROTO_ITEM_SET_GENERATED(ti);
			ti = proto_tree_add_uint64(ldss_tree, hf_ldss_size,
						   tvb, 0, 0, size);
			PROTO_ITEM_SET_GENERATED(ti);
			ti = proto_tree_add_uint64(ldss_tree, hf_ldss_offset,
						   tvb, 0, 0, offset);
			PROTO_ITEM_SET_GENERATED(ti);
			ti = proto_tree_add_uint(ldss_tree, hf_ldss_compression,
						 tvb, 0, 0, compression);
			PROTO_ITEM_SET_GENERATED(ti);
			/* Link to the request for a pull. */
			if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND &&
			    transfer_info->req != NULL &&
			    transfer_info->req->num != 0) {
				ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_to,
							 tvb, 0, 0, transfer_info->req->num);
				PROTO_ITEM_SET_GENERATED(ti);
			}
		}
	}

	/* Print the pull response time */
	if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND &&
	    transfer_info->req != NULL &&
	    transfer_info->resp_num != 0) {
		nstime_t pull_response_time;
		nstime_delta(&pull_response_time, &transfer_info->resp_ts,
			     &transfer_info->req->ts);
		ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_response_time,
					 tvb, 0, 0, &pull_response_time);
		PROTO_ITEM_SET_GENERATED(ti);
	}

	/* Link the transfer back to the initiating broadcast. Response time is
	 * calculated as the time from broadcast to completed transfer. */
	ti = proto_tree_add_uint(ldss_tree, hf_ldss_initiated_by,
				 tvb, 0, 0, transfer_info->broadcast->num);
	PROTO_ITEM_SET_GENERATED(ti);

	if (transfer_info->resp_num != 0) {
		nstime_delta(&broadcast_response_time, &transfer_info->resp_ts,
			     &transfer_info->broadcast->ts);
		ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_completed_in,
					 tvb, 0, 0, &broadcast_response_time);
		PROTO_ITEM_SET_GENERATED(ti);
	}

	/* This conv got its addr2/port2 set by the TCP dissector because a TCP
	 * connection was established. Make a new one to handle future connections
	 * to the addr/port mentioned in the broadcast, because that socket is
	 * still open. */
	if (transfer_tcpinfo->seq == 1 &&
	    transfer_tcpinfo->lastackseq == 1) {

		prepare_ldss_transfer_conv(transfer_info->broadcast);
	}

	return tvb_captured_length(tvb);
}
예제 #24
0
static void
dissect_fip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    guint       op;
    guint       sub;
    guint       rlen;
    proto_item *ti;
    proto_item *item;
    proto_tree *fip_tree;
    proto_tree *subtree;
    guint       dtype;
    guint       dlen;
    guint       desc_offset;
    guint       val;
    tvbuff_t   *desc_tvb;
    const char *info;

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

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

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

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

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

    rlen = tvb_get_ntohs(tvb, 6);

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

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

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

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

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

            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_caps, &item);
            ls_tvb = tvb_new_subset(desc_tvb, 4, dlen - 4, -1);
            call_dissector_with_data(fc_handle, ls_tvb, pinfo, subtree, &fc_data);
            proto_item_append_text(item, "%u bytes", dlen - 4);
        }
            break;
        case FIP_DT_VN:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vn, &item);
            proto_tree_add_item(subtree, hf_fip_desc_vn_mac, desc_tvb,
                    2, 6, ENC_NA);
            proto_tree_add_item(subtree, hf_fip_desc_vn_fid, desc_tvb,
                    9, 3, ENC_BIG_ENDIAN);
            proto_tree_add_item(subtree, hf_fip_desc_vn_wwpn,
                    desc_tvb, 12, 8, ENC_NA);
            proto_item_append_text(item, "MAC %s  FC_ID %6.6x",
                    tvb_bytes_to_str_punct(wmem_packet_scope(), desc_tvb, 2, 6, ':'),
                    tvb_get_ntoh24(desc_tvb, 9));
            break;
        case FIP_DT_FKA:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fka, &item);
            val = tvb_get_ntohl(desc_tvb, 4);
            proto_tree_add_uint_format_value(subtree, hf_fip_desc_fka,
                    desc_tvb, 4, 4, val, "%u ms", val);
            proto_item_append_text(item, "%u ms", val);
            break;
        case FIP_DT_VEND:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vend, &item);
            proto_tree_add_item(subtree, hf_fip_desc_vend, desc_tvb,
                    4, 8, ENC_NA);
            if (tvb_bytes_exist(desc_tvb, 9, -1)) {
                proto_tree_add_item(subtree, hf_fip_desc_vend_data,
                     desc_tvb, 9, -1, ENC_NA);
            }
            break;
        case FIP_DT_VLAN:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vlan, &item);
            proto_tree_add_item(subtree, hf_fip_desc_vlan, desc_tvb,
                    2, 2, ENC_BIG_ENDIAN);
            proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2));
            break;
        case FIP_DT_FC4F:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fc4f, &item);
            fip_desc_fc4f(desc_tvb, subtree, item);
            break;
        default:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_unk, &item);
            proto_tree_add_item(subtree, hf_fip_desc_unk, desc_tvb,
                    2, -1, ENC_NA);
            break;
        }
    }
}
예제 #25
0
/* Function to dissect EDP portion of ISMP message */
static void
dissect_ismp_edp(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *ismp_tree)
{
	/* local variables used for EDP dissection */ 
	int neighbors_count = 0;
	int tuples_count = 0;
	guint16 device_type = 0; 
	guint32	options = 0;
	guint16 num_neighbors = 0;
	guint16 num_tuples = 0;
	guint16 tuple_type = 0;
	guint16 tuple_length = 0;
	const guint8 *neighbors_ptr;
	const guint8 *tuples_ptr;

	/* Set up structures needed to add the protocol subtree and manage it */
	proto_item *edp_ti;
	proto_tree *edp_tree;
	
	proto_item *edp_options_ti;
	proto_tree *edp_options_tree;

	proto_item *edp_neighbors_ti;
	proto_tree *edp_neighbors_tree;

	proto_item *edp_neighbors_leaf_ti;
	proto_tree *edp_neighbors_leaf_tree;

	proto_item *edp_tuples_ti;
	proto_tree *edp_tuples_tree;

	proto_item *edp_tuples_leaf_ti;
	proto_tree *edp_tuples_leaf_tree;

	/* add column iformation marking this as EDP (Enterasys Discover Protocol */
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISMP.EDP");
	col_clear(pinfo->cinfo, COL_INFO);

	/* create display subtree for EDP */
	if (ismp_tree) {
		edp_ti  = proto_tree_add_item(ismp_tree, hf_ismp_edp, tvb, offset,
			tvb_length_remaining(tvb, offset), FALSE);
		edp_tree = proto_item_add_subtree(edp_ti, ett_ismp_edp);

		col_add_fstr(pinfo->cinfo, COL_INFO, "MIP %s, MMAC %s, ifIdx %d",
			ip_to_str(tvb_get_ptr(tvb, offset+2, 4)),
			ether_to_str(tvb_get_ptr(tvb, offset+6, 6)),
			tvb_get_ntohl(tvb, offset+12));

		proto_tree_add_item(edp_tree, hf_ismp_edp_version, tvb, offset, 2, FALSE);
		offset += 2;
		proto_tree_add_item(edp_tree, hf_ismp_edp_module_ip, tvb, offset, 4, FALSE);
		offset += 4;
		proto_tree_add_item(edp_tree, hf_ismp_edp_module_mac, tvb, offset, 6, FALSE);
		offset += 6;
		proto_tree_add_item(edp_tree, hf_ismp_edp_module_port, tvb, offset, 4, FALSE);
		offset += 4;
		proto_tree_add_item(edp_tree, hf_ismp_edp_chassis_mac, tvb, offset, 6, FALSE);
		offset += 6;
		proto_tree_add_item(edp_tree, hf_ismp_edp_chassis_ip, tvb, offset, 4, FALSE);
		offset += 4;
		device_type = tvb_get_ntohs(tvb, offset);
		proto_tree_add_item(edp_tree, hf_ismp_edp_device_type, tvb, offset, 2, FALSE);
		offset += 2;
		proto_tree_add_uint_format(edp_tree, hf_ismp_edp_module_rev, tvb, offset, 4, tvb_get_ntohl(tvb, offset),
			"Module Firmware Revision: %02x.%02x.%02x.%02x", tvb_get_guint8(tvb, offset),
			tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3));
		offset += 4;

		/* create display subtree for EDP options */
		options = tvb_get_ntohl(tvb, offset);
		edp_options_ti = proto_tree_add_uint_format(edp_tree, hf_ismp_edp_options, tvb, offset, 4,
			options,"Options: 0x%08x",options);
		edp_options_tree = proto_item_add_subtree(edp_options_ti, ett_ismp_edp_options);

		/* depending on device_type, show the appropriate options */
		switch (device_type) {
			case EDP_DEVICE_TYPE_SFS17:
			case EDP_DEVICE_TYPE_SFS18:
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_flood, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_port, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_core, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_switch, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_isolated, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_redun, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_conmsg, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_calltap, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_tagflood, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_unused2, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_resolve, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_flood, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_lsp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_sfssup, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_unused1, tvb, offset, 4, FALSE);
				break;
			case EDP_DEVICE_TYPE_ROUTER:
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_level1, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_trans, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_route, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_igmp_snoop, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_gmrp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_gvrp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_8021q, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_dvmrp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_ospf, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_bgp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_rip, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_igmp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_ssr, tvb, offset, 4, FALSE);
				break;
			case EDP_DEVICE_TYPE_BRIDGE:
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_level1, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_trans, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_route, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_igmp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_gmrp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_gvrp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_8021q, tvb, offset, 4, FALSE);
				break;
			case EDP_DEVICE_TYPE_VLANMAN:
				break;
			case EDP_DEVICE_TYPE_NTSERVER:
			case EDP_DEVICE_TYPE_NTCLIENT:
			case EDP_DEVICE_TYPE_WIN95:
			case EDP_DEVICE_TYPE_WIN98:
			case EDP_DEVICE_TYPE_UNIXSERVER:
			case EDP_DEVICE_TYPE_UNIXCLIENT:
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_ad, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_dns, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_dhcp, tvb, offset, 4, FALSE);
				break;
			case EDP_DEVICE_TYPE_ACCESSPOINT:
			default:
				break;
		}
		offset += 4;
		
		/* determine the number of neighbors and create EDP neighbors subtree */
		num_neighbors = tvb_get_ntohs(tvb, offset);
		proto_tree_add_item(edp_tree, hf_ismp_edp_num_neighbors, tvb, offset, 2, FALSE);
		offset += 2;
		if (num_neighbors > 0)
		{
			tvb_ensure_bytes_exist(tvb, offset, num_neighbors*10);
			if (tvb_reported_length_remaining(tvb, offset) >= (num_neighbors *10))
			{
				neighbors_ptr = tvb_get_ptr( tvb, offset, (num_neighbors*10) );
				edp_neighbors_ti = proto_tree_add_bytes_format(edp_tree, hf_ismp_edp_neighbors, tvb, 
					offset, num_neighbors*10, neighbors_ptr, "Neighbors:");
			}
			else
			{
				neighbors_ptr = tvb_get_ptr( tvb, offset, tvb_reported_length_remaining(tvb, offset) );
				edp_neighbors_ti = proto_tree_add_bytes_format(edp_tree, hf_ismp_edp_neighbors, tvb, 
					offset, num_neighbors *10, neighbors_ptr, "Neighbors:");
			}
			edp_neighbors_tree = proto_item_add_subtree(edp_neighbors_ti, ett_ismp_edp_neighbors);
			while ( neighbors_count < num_neighbors && tvb_reported_length_remaining(tvb, offset) >= 10)
			{
				edp_neighbors_leaf_ti = proto_tree_add_text(edp_neighbors_tree, tvb, offset, 10,
                        		        "Neighbor%d", (neighbors_count+1));
				edp_neighbors_leaf_tree = proto_item_add_subtree(edp_neighbors_leaf_ti, ett_ismp_edp_neighbors_leaf);

				proto_tree_add_text(edp_neighbors_leaf_tree, tvb, offset, 6,
					"MAC Address: %s", ether_to_str(tvb_get_ptr(tvb, offset, 6)));
				proto_tree_add_text(edp_neighbors_leaf_tree, tvb, offset, 4,
					"Assigned Neighbor State 0x%04x",tvb_get_ntohl(tvb, offset));
				offset += 10;
				neighbors_count++;
			}
			if (neighbors_count != num_neighbors)
			{
				proto_tree_add_text(edp_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset),
				"MALFORMED PACKET");
				return;
			}
		}
		
		/* determine data remains, if so, count tuples
		   and create EDP tuples subtree */
		if (tvb_reported_length_remaining(tvb, offset) != 0 && 
			tvb_reported_length_remaining(tvb, offset) >= 2) 
		{
			num_tuples = tvb_get_ntohs(tvb, offset);
			proto_tree_add_item(edp_tree, hf_ismp_edp_num_tuples, tvb, offset, 2, FALSE);
			offset += 2;
		}
		else if (tvb_reported_length_remaining(tvb, offset) > 0) {
			proto_tree_add_text(edp_tree, tvb, offset, 
				tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET");
			return;
		}
		else
		{
			return;
		}

		/* start populating tuple information */
		if (num_tuples && tvb_reported_length_remaining(tvb, offset) >= 4)
		{
			tuples_ptr = tvb_get_ptr(tvb, offset, tvb_reported_length_remaining(tvb, offset));
			edp_tuples_ti = proto_tree_add_bytes_format(edp_tree, hf_ismp_edp_tuples, tvb,
				offset, tvb_reported_length_remaining(tvb, offset), tuples_ptr, "Tuples");
			edp_tuples_tree = proto_item_add_subtree(edp_tuples_ti, ett_ismp_edp_tuples);

			while ( (tuples_count < num_tuples) && (tvb_reported_length_remaining(tvb, offset) >= 4) )
			{

				tuple_length = tvb_get_ntohs(tvb, offset+2);
				edp_tuples_leaf_ti = proto_tree_add_text(edp_tuples_tree, tvb, offset, tuple_length,
					"Tuple%d", tuples_count+1);

				edp_tuples_leaf_tree = proto_item_add_subtree(edp_tuples_leaf_ti, ett_ismp_edp_tuples_leaf);

				tuple_type = tvb_get_ntohs(tvb, offset);
				proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, 2,
					"Tuple Type: %s(%d)", val_to_str( tuple_type, edp_tuple_types, "Unknown"), tuple_type );
				offset += 2;
				proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, 2,
					"Tuple Length: %d", tuple_length);
				tuple_length -= 4;
				offset += 2;
				
				if (tvb_reported_length_remaining(tvb, offset) >= tuple_length)
				{
					tvb_ensure_bytes_exist(tvb, offset, tuple_length);
					switch (tuple_type)
					{						
						case EDP_TUPLE_HOLD:
							proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
								"Hold Time = %d", tvb_get_ntohs(tvb, offset));
							break;
						case EDP_TUPLE_INT_NAME:
							proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
								"Interface Name = %s", tvb_format_text(tvb, offset, tuple_length));
							col_append_fstr(pinfo->cinfo, COL_INFO, ", ifName %s",
								tvb_format_text(tvb, offset, tuple_length));
							break;
						case EDP_TUPLE_SYS_DESCRIPT:
							proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
								"System Description = %s", tvb_format_text(tvb, offset, tuple_length));
							break;
						case EDP_TUPLE_IPX_ADDR:
							proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
								"Interface IPX_address = %s", 
								ipx_addr_to_str(tvb_get_ntohl(tvb, offset), 
								tvb_get_ptr(tvb, offset+4, tuple_length-4)));
							break;
						case EDP_TUPLE_UNKNOWN:
						default:
							proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
								"Unknown Tuple Data %s", tvb_format_text(tvb, offset, tuple_length));
							break;
					}  
				}
				offset += tuple_length;

				tuples_count++;
				tuple_type = 0;
				tuple_length = 0;
			} 
			if (tuples_count != num_tuples)
			{
				proto_tree_add_text(edp_tree, tvb, offset, 
					tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET");
				return;
			}
			else
			{
				return;
			}
		}
			
	}
		

}
예제 #26
0
static void
dissect_pgmopts(ptvcursor_t* cursor, const char *pktname)
{
	proto_item *tf;
	proto_tree *opts_tree = NULL;
	proto_tree *opt_tree = NULL;
	tvbuff_t *tvb = ptvcursor_tvbuff(cursor);

	gboolean theend = FALSE;

	guint16 opts_total_len;
	guint8 genopts_type;
	guint8 genopts_len;
	guint8 opts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));

	if (opts_type != PGM_OPT_LENGTH) {
		proto_tree_add_text(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), 1,
		    "%s Options - initial option is %s, should be %s",
		    pktname,
		    val_to_str(opts_type, opt_vals, "Unknown (0x%02x)"),
		    val_to_str(PGM_OPT_LENGTH, opt_vals, "Unknown (0x%02x)"));
		return;
	}

	opts_total_len = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)+2);

	if (opts_total_len < 4) {
		proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor)+2, 2,
			"%s Options (Total Length %u - invalid, must be >= 4)",
			pktname, opts_total_len);
		return;
	}

	tf = proto_tree_add_text(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), opts_total_len,
		"%s Options (Total Length %d)", pktname, opts_total_len);
	opts_tree = proto_item_add_subtree(tf, ett_pgm_opts);
	ptvcursor_set_tree(cursor, opts_tree);
	ptvcursor_add(cursor, hf_pgm_opt_type, 1, ENC_BIG_ENDIAN);
	ptvcursor_add(cursor, hf_pgm_opt_len, 1, ENC_BIG_ENDIAN);
	ptvcursor_add(cursor, hf_pgm_opt_tlen, 2, ENC_BIG_ENDIAN);

	for (opts_total_len -= 4; !theend && opts_total_len != 0;){
		if (opts_total_len < 4) {
			proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), opts_total_len,
			    "Remaining total options length doesn't have enough for an options header");
			break;
		}

		genopts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
		genopts_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)+1);

		if (genopts_type & PGM_OPT_END)  {
			genopts_type &= ~PGM_OPT_END;
			theend = TRUE;
		}
		if (genopts_len < 4) {
			proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len,
				"Option: %s, Length: %u (invalid, must be >= 4)",
				val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"),
				genopts_len);
			break;
		}
		if (opts_total_len < genopts_len) {
			proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len,
			    "Option: %s, Length: %u (> remaining total options length)",
			    val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"),
			    genopts_len);
			break;
		}
		tf = proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len,
			"Option: %s, Length: %u",
			val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"),
			genopts_len);

		switch(genopts_type) {
		case PGM_OPT_JOIN:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_join);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_JOIN_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_JOIN_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_join_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_join_minjoin, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_PARITY_PRM:{
			guint8 optdata_po;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_parityprm);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);


			if (genopts_len < PGM_OPT_PARITY_PRM_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, ptvcursor_tvbuff(cursor),
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PARITY_PRM_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			optdata_po = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
			proto_tree_add_uint_format(opt_tree, hf_pgm_opt_parity_prm_po, tvb,
				ptvcursor_current_offset(cursor), 1, optdata_po, "Parity Parameters: %s (0x%x)",
				paritystr(optdata_po), optdata_po);
			ptvcursor_advance(cursor, 1);

			ptvcursor_add(cursor, hf_pgm_opt_parity_prm_prmtgsz, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_PARITY_GRP:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_paritygrp);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PARITY_GRP_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PARITY_GRP_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_parity_grp_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_parity_grp_prmgrp, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_NAK_LIST:{
			guint8 optdata_len;
			guint32 naklist[PGM_MAX_NAK_LIST_SZ+1];
			unsigned char *nakbuf;
			gboolean firsttime;
			int i, j, naks, soffset;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_naklist);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			optdata_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_res, 1, ENC_BIG_ENDIAN);

			optdata_len -= PGM_OPT_NAK_LIST_SIZE;
			tvb_memcpy(tvb, (guint8 *)naklist, ptvcursor_current_offset(cursor), optdata_len);
			firsttime = TRUE;
			soffset = 0;
			naks = (optdata_len/sizeof(guint32));
			nakbuf = ep_alloc(8192);
			j = 0;
			/*
			 * Print out 8 per line
			 */
			for (i=0; i < naks; i++) {
				soffset += MIN(8192-soffset,
					g_snprintf(nakbuf+soffset, 8192-soffset, "0x%lx ",
						(unsigned long)g_ntohl(naklist[i])));
				if ((++j % 8) == 0) {
					if (firsttime) {
						proto_tree_add_bytes_format(opt_tree,
							hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
							nakbuf, "List(%d): %s", naks, nakbuf);
						soffset = 0;
						firsttime = FALSE;
					} else {
						proto_tree_add_bytes_format(opt_tree,
							hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
							nakbuf, "List: %s", nakbuf);
						soffset = 0;
					}
					ptvcursor_advance(cursor, j*4);
					j = 0;
				}
			}
			if (j) {
				if (firsttime) {
					proto_tree_add_bytes_format(opt_tree,
						hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
						nakbuf, "List(%d): %s", naks, nakbuf);
				} else {
					proto_tree_add_bytes_format(opt_tree,
						hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
						nakbuf, "List: %s", nakbuf);
				}
				ptvcursor_advance(cursor, j*4);
			}
			break;
		}
		case PGM_OPT_PGMCC_DATA:{
			guint16 optdata_afi;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PGMCC_DATA_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PGMCC_DATA_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_tsp, 4, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_res2, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker6, 16, ENC_NA);
				break;

			default:
				proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			break;
		}
		case PGM_OPT_PGMCC_FEEDBACK:{
			guint16 optdata_afi;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PGMCC_FEEDBACK_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PGMCC_FEEDBACK_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_tsp, 4, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_lossrate, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker6, 16, ENC_NA);
				break;

			default:
				proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			break;
		}
		case PGM_OPT_NAK_BO_IVL:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_ivl);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_NAK_BO_IVL_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_NAK_BO_IVL_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl_sqn, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_NAK_BO_RNG:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_rng);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_NAK_BO_RNG_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_NAK_BO_RNG_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_min_bo_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_max_bo_ivl, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_REDIRECT:{
			guint16 optdata_afi;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_redirect);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_REDIRECT_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_REDIRECT_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_redirect_res, 1, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_opt_redirect_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_redirect_res2, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr6, 16, ENC_NA);
				break;

			default:
				proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			break;
		}
		case PGM_OPT_FRAGMENT:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_fragment);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_FRAGMENT_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_FRAGMENT_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_first_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_offset, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_total_length, 4, ENC_BIG_ENDIAN);

			break;
		}
		default:{
			ptvcursor_advance(cursor, genopts_len);
			break;
		}
		}

		opts_total_len -= genopts_len;
	}
	return;
}
예제 #27
0
파일: packet-mip.c 프로젝트: flaub/HotFuzz
/* Code to actually dissect the packets */
static void
dissect_mip( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  /* Set up structures we will need to add the protocol subtree and manage it */
  proto_item	*ti;
  proto_tree	*mip_tree=NULL;
  proto_item    *tf;
  proto_tree    *flags_tree;
  guint8         type;
  guint16        flags;
  gint           offset=0;
  const guint8  *reftime;
  tvbuff_t      *next_tvb;

  /* Make entries in Protocol column and Info column on summary display */

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

  type = tvb_get_guint8(tvb, offset);
  switch (type) {
  case MIP_REGISTRATION_REQUEST:
	col_add_fstr(pinfo->cinfo, COL_INFO,
		       "Reg Request: HoA=%s HA=%s CoA=%s",
		       ip_to_str(tvb_get_ptr(tvb,4,4)),
		       ip_to_str(tvb_get_ptr(tvb,8,4)),
		       ip_to_str(tvb_get_ptr(tvb,12,4)));

	if (tree) {
	  ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
	  mip_tree = proto_item_add_subtree(ti, ett_mip);

	  /* type */
	  proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
	  offset++;

	  /* flags */
	  flags = tvb_get_guint8(tvb, offset);
	  tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 1, flags);
	  flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_s, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_b, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_d, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_m, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_g, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_v, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_t, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_x, tvb, offset, 1, flags);
	  offset++;

	  /* lifetime */
	  proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE);
	  offset += 2;

	  /* home address */
	  proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* home agent address */
	  proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* Care of Address */
	  proto_tree_add_item(mip_tree, hf_mip_coa, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* Identifier - assumed to be an NTP time here */
	  reftime = tvb_get_ptr(tvb, offset, 8);
	  proto_tree_add_bytes_format(mip_tree, hf_mip_ident, tvb, offset, 8,
				      reftime,
				      "Identification: %s",
				      ntp_fmt_ts(reftime));
	  offset += 8;

	} /* if tree */
	break;
  case MIP_REGISTRATION_REPLY:
	col_add_fstr(pinfo->cinfo, COL_INFO,
		       "Reg Reply: HoA=%s HA=%s, Code=%u",
		       ip_to_str(tvb_get_ptr(tvb,4,4)), 
		       ip_to_str(tvb_get_ptr(tvb,8,4)), 
		       tvb_get_guint8(tvb,1));

	if (tree) {
	  /* Add Subtree */
	  ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
	  mip_tree = proto_item_add_subtree(ti, ett_mip);

	  /* Type */
  	  proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
	  offset++;

	  /* Reply Code */
	  proto_tree_add_item(mip_tree, hf_mip_code, tvb, offset, 1, FALSE);
	  offset++;

	  /* Registration Lifetime */
	  proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE);
	  offset += 2;

	  /* Home address */
	  proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* Home Agent Address */
	  proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* Identifier - assumed to be an NTP time here */
	  reftime = tvb_get_ptr(tvb, offset, 8);
	  proto_tree_add_bytes_format(mip_tree, hf_mip_ident, tvb, offset, 8,
				      reftime,
				      "Identification: %s",
				      ntp_fmt_ts(reftime));
	  offset += 8;
	} /* if tree */
	break;
  case MIP_NATT_TUNNEL_DATA:
	col_add_fstr(pinfo->cinfo, COL_INFO, "Tunnel Data: Next Header=%u",
		       tvb_get_guint8(tvb,1));

	if (tree) {
	  /* Add Subtree */
	  ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
	  mip_tree = proto_item_add_subtree(ti, ett_mip);

	  /* Type */
  	  proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
	  offset++;

	  /* Next Header */
	  proto_tree_add_item(mip_tree, hf_mip_nattt_nexthdr, tvb, offset, 1, FALSE);
	  offset++;

	  /* reserved */
	  proto_tree_add_item(mip_tree, hf_mip_nattt_reserved, tvb, offset, 2, FALSE);
	  offset += 2;
	} /* if tree */
	else {
	  offset += 4;
	}
	/* encapsulated payload */
	next_tvb = tvb_new_subset_remaining(tvb, 4);
	call_dissector(ip_handle, next_tvb, pinfo, mip_tree);
	offset += tvb_reported_length_remaining(tvb, offset);
	break;
  case MIP_REGISTRATION_REVOCATION:
	col_add_fstr(pinfo->cinfo, COL_INFO,
		       "Reg Revocation: HoA=%s HDA=%s FDA=%s",
		       ip_to_str(tvb_get_ptr(tvb,4,4)),
		       ip_to_str(tvb_get_ptr(tvb,8,4)),
		       ip_to_str(tvb_get_ptr(tvb,12,4)));

	if (tree) {
	  ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
	  mip_tree = proto_item_add_subtree(ti, ett_mip);

	  /* type */
	  proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
	  offset++;

	  /* reserved */
	  proto_tree_add_item(mip_tree, hf_mip_rev_reserved, tvb, offset, 1, FALSE);
	  offset++;

	  /* flags */
	  flags = tvb_get_ntohs(tvb, offset);
	  tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 2, flags);
	  flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_rev_a, tvb, offset, 2, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_rev_i, tvb, offset, 2, flags);

	  /* reserved */
	  proto_tree_add_uint(flags_tree, hf_mip_rev_reserved, tvb, offset, 2, flags);
	  offset += 2;

	  /* home address */
	  proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* home domain address */
	  proto_tree_add_item(mip_tree, hf_mip_hda, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* foreign domain address */
	  proto_tree_add_item(mip_tree, hf_mip_fda, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* revocation identifier */
	  proto_tree_add_item(mip_tree, hf_mip_revid, tvb, offset, 4, FALSE);
	  offset += 4;
	} /* if tree */
	break;
  case MIP_REGISTRATION_REVOCATION_ACK:
	  col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Revocation Ack: HoA=%s",
		       ip_to_str(tvb_get_ptr(tvb,4,4)));

	if (tree) {
	  ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
	  mip_tree = proto_item_add_subtree(ti, ett_mip);

	  /* type */
	  proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
	  offset++;

	  /* reserved */
	  proto_tree_add_item(mip_tree, hf_mip_ack_reserved, tvb, offset, 1, FALSE);
	  offset++;

	  /* flags */
	  flags = tvb_get_ntohs(tvb, offset);
	  tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 2, flags);
	  flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_ack_i, tvb, offset, 2, flags);

	  /* reserved */
	  proto_tree_add_uint(flags_tree, hf_mip_ack_reserved, tvb, offset, 2, flags);
	  offset += 2;

	  /* home address */
	  proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* revocation identifier */
	  proto_tree_add_item(mip_tree, hf_mip_revid, tvb, offset, 4, FALSE);
	  offset += 4;
	} /* if tree */
	break;
  } /* End switch */

  if (tree) {
	if (tvb_reported_length_remaining(tvb, offset) > 0)
	  dissect_mip_extensions(tvb, offset, mip_tree);
  }
} /* dissect_mip */