static void
dissect_rtacser_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures needed to add the protocol subtree and manage it */
    proto_item    *rtacser_item, *ts_item, *cl_item, *data_payload;
    proto_tree    *rtacser_tree, *cl_tree;
    int           offset = 0, len;
    guint         event_type;
    guint32       timestamp1, timestamp2;
    gboolean      cts, dcd, dsr, rts, dtr, ring, mbok;
    tvbuff_t      *payload_tvb;

    len = RTACSER_HEADER_LEN;

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

    rtacser_item = proto_tree_add_protocol_format(tree, proto_rtacser, tvb, 0, len, "RTAC Serial Line");
    rtacser_tree = proto_item_add_subtree(rtacser_item, ett_rtacser);

    /* Time-stamp is stored as 2 x 32-bit unsigned integers, the left and right-hand side of the decimal point respectively */
    /* The format mirrors the timeval struct - absolute Epoch time (seconds since 1/1/1970) with an added microsecond component */
    timestamp1 = tvb_get_ntohl(tvb, offset);
    timestamp2 = tvb_get_ntohl(tvb, offset+4);
    ts_item = proto_tree_add_item(rtacser_tree, hf_rtacser_timestamp, tvb, offset, 8, ENC_BIG_ENDIAN);
    proto_item_set_text(ts_item, "Arrived At Time: %u.%u" , timestamp1, timestamp2);
    offset += 8;

    /* Set INFO column with RTAC Serial Event Type */
    event_type = tvb_get_guint8(tvb, offset);
    col_add_fstr(pinfo->cinfo, COL_INFO, "%-21s", val_to_str_const(event_type, rtacser_eventtype_vals, "Unknown Type"));

    /* Add event type to tree */
    proto_tree_add_item(rtacser_tree, hf_rtacser_event_type, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset += 1;

    /* Retrieve EIA-232 serial control line states */
    cts  = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_CTS;
    dcd  = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_DCD;
    dsr  = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_DSR;
    rts  = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_RTS;
    dtr  = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_DTR;
    ring = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_RING;
    mbok = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_MBOK;

    cl_item = proto_tree_add_text(rtacser_tree, tvb, offset, 1, "Control Lines");
    cl_tree = proto_item_add_subtree(cl_item, ett_rtacser_cl);

    /* Add UART Control Line information to INFO column */
    col_append_str(pinfo->cinfo, COL_INFO, " ( ");
    (cts)  ? col_append_str(pinfo->cinfo, COL_INFO, "CTS") : col_append_str(pinfo->cinfo, COL_INFO, "/CTS");
    (dcd)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DCD")  : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/DCD");
    (dsr)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DSR")  : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/DSR");
    (rts)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RTS")  : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/RTS");
    (dtr)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DTR")  : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/DTR");
    (ring) ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RING") : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/RING");
    (mbok) ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "MBOK") : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/MBOK");
    col_append_str(pinfo->cinfo, COL_INFO, " )");

    /* Add UART Control Line information to tree */
    proto_item_append_text(cl_item, " (");
    (cts)  ? proto_item_append_text(cl_item, "CTS, ") : proto_item_append_text(cl_item, "/CTS, ");
    (dcd)  ? proto_item_append_text(cl_item, "DCD, ") : proto_item_append_text(cl_item, "/DCD, ");
    (dsr)  ? proto_item_append_text(cl_item, "DSR, ") : proto_item_append_text(cl_item, "/DSR, ");
    (rts)  ? proto_item_append_text(cl_item, "RTS, ") : proto_item_append_text(cl_item, "/RTS, ");
    (dtr)  ? proto_item_append_text(cl_item, "DTR, ") : proto_item_append_text(cl_item, "/DTR, ");
    (ring) ? proto_item_append_text(cl_item, "RING, ") : proto_item_append_text(cl_item, "/RING, ");
    (mbok) ? proto_item_append_text(cl_item, "MBOK") : proto_item_append_text(cl_item, "/MBOK");
    proto_item_append_text(cl_item, ")");

    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_cts,  tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_dcd,  tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_dsr,  tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_rts,  tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_dtr,  tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_ring, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_mbok, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset += 1;

    /* 2-byte footer */
    proto_tree_add_item(rtacser_tree, hf_rtacser_footer, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    /* If no payload dissector has been selected, indicate to the user the preferences options */
    if ((tvb_reported_length_remaining(tvb, offset) > 0) && (global_rtacser_payload_proto == RTACSER_PAYLOAD_NONE)) {
        data_payload = proto_tree_add_item(tree, hf_rtacser_data, tvb, offset, -1, ENC_NA);
        proto_item_set_text(data_payload,"Payload Protocol not selected.  Check 'Preferences-> Protocols-> RTAC Serial' for options");
        return;
    }


    /* Determine correct message type and call appropriate dissector */
    if (tvb_reported_length_remaining(tvb, RTACSER_HEADER_LEN) > 0) {

        switch (global_rtacser_payload_proto) {
            case RTACSER_PAYLOAD_SELFM:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(selfm_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_DNP3:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(dnp3_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_MODBUS:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(modbus_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_SYNPHASOR:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(synphasor_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_LG8979:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(lg8979_handle, payload_tvb, pinfo, tree);
                break;
            default:
                break;
        }
    }

}
Example #2
0
static void dissect_srv_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
{
    guint32 i, curr;
    guint16 /*len, namelen,*/ priority, weight, port, dlen;
    const guchar *dname;

    proto_item* srv_rec_item, *rec_item;
    proto_item* srv_rec_tree, *rec_tree;

    if(tree)
    {
        srv_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "SRV records");
        srv_rec_tree = proto_item_add_subtree(srv_rec_item, ett_srv_rec);
                   proto_item_set_text(srv_rec_item, "SRV records (%d)", nrec);
    }
    else return;

    curr = offset;

    for(i=0; i < nrec; i++)
    {
        /*len =      tvb_get_ntohs(tvb, curr);*/
        priority = tvb_get_ntohs(tvb, curr + 2);
        weight   = tvb_get_ntohs(tvb, curr + 4);
        port     = tvb_get_ntohs(tvb, curr + 6);
        /*namelen = len - 8;*/

        dlen = get_dns_name(tvb, curr + 8, 0, curr + 8, &dname);

        if(srv_rec_tree)
        {
            rec_item = proto_tree_add_text(srv_rec_tree, tvb, curr, 6,"  ");
            rec_tree = proto_item_add_subtree(rec_item, ett_srv_rec_item);
            proto_item_set_text(rec_item,
                        "SRV record:pri=%d,w=%d,port=%d,dname=%s",
                        priority,
                        weight,
                        port,
                        dname);
        }
        else return;

        proto_tree_add_uint(rec_tree,
                        hf_srv_prio,
                        tvb,
                        curr + 2,
                        2,
                        priority);

        proto_tree_add_uint(rec_tree,
                        hf_srv_weight,
                        tvb,
                        curr + 4,
                        2,
                        weight);

        proto_tree_add_uint(rec_tree,
                        hf_srv_port,
                        tvb,
                        curr + 6,
                        2,
                        port);


        proto_tree_add_text(rec_tree,
                            tvb,
                            curr + 8,
                            dlen,
                            "DNAME: %s", dname);

        curr+=(int)((sizeof(short)*4) + dlen);

    }

}
Example #3
0
static void
dissect_hpsw_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length,
                 proto_tree *tree, proto_item *ti, guint8 type)
{
    switch (type) {

    case HPFOO_DEVICE_NAME:
        if (length > 0) {
            proto_tree_add_item(tree, hf_hpsw_device_name, tvb, offset, length, ENC_NA|ENC_ASCII);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Device Name: Bad length %u", length);
        }
        break;

    case HPFOO_DEVICE_VERSION:
        if (length > 0) {
            proto_tree_add_item(tree, hf_hpsw_device_version, tvb, offset, length, ENC_NA|ENC_ASCII);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Version: Bad length %u", length);
        }
        break;

    case HPFOO_CONFIG_NAME:
        if (length > 0) {
            proto_tree_add_item(tree, hf_hpsw_config_name, tvb, offset, length, ENC_NA|ENC_ASCII);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Config Name: Bad length %u", length);
        }
        break;

    case HPFOO_ROOT_MAC_ADDR:
        if (length == 6) {
            proto_tree_add_item(tree, hf_hpsw_root_mac_addr, tvb, offset, length, ENC_NA);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Root MAC Addr: Bad length %u", length);
        }
        break;

    case HPFOO_IP_ADDR:
        if (length == 4) {
            proto_tree_add_item(tree, hf_hpsw_ip_addr, tvb, offset, length, ENC_BIG_ENDIAN);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "IP Addr: Bad length %u", length);
        }
        break;

    case HPFOO_FIELD_6:
        if (length == 2) {
            proto_tree_add_item(tree, hf_hpsw_field_6, tvb, offset, length, ENC_BIG_ENDIAN);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Field 6: Bad length %u", length);
        }
        break;

    case HPFOO_DOMAIN:
        if (length > 0) {
            proto_tree_add_item(tree, hf_hpsw_domain, tvb, offset, length, ENC_NA|ENC_ASCII);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Domain: Bad length %u", length);
        }
        break;

    case HPFOO_FIELD_8:
        if (length == 2) {
            proto_tree_add_item(tree, hf_hpsw_field_8, tvb, offset, length, ENC_BIG_ENDIAN);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Field 8: Bad length %u", length);
        }
        break;

    case HPFOO_FIELD_9:
        if (length == 2) {
            proto_tree_add_item(tree, hf_hpsw_field_9, tvb, offset, length, ENC_BIG_ENDIAN);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Field 9: Bad length %u", length);
        }
        break;

    case HPFOO_FIELD_10:
        if (length == 4) {
            proto_tree_add_item(tree, hf_hpsw_field_10, tvb, offset, length, ENC_BIG_ENDIAN);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Field 10: Bad length %u", length);
        }
        break;

    case HPFOO_NEIGHBORS:
        if (!(length % 6))
        {   int i = length/6;
            proto_item_set_text(ti, "Number of neighbor MAC Addresses: %u", i);
            for ( ; i; i--)
            {
                proto_tree_add_item(tree, hf_hpsw_neighbor_mac_addr, tvb, offset, length, ENC_NA);
                offset += 6;
            }
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Neighbors: Bad length %u", length);
        }
        break;

    case HPFOO_FIELD_12:
        if (length == 1) {
            proto_tree_add_item(tree, hf_hpsw_field_12, tvb, offset, length, ENC_NA);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Field 12: Bad length %u", length);
        }
        break;

    case HPFOO_DEVICE_ID:
        if (length > 6) {
            proto_tree_add_item(tree, hf_hpsw_device_id, tvb, offset, 6, ENC_NA);
            proto_tree_add_item(tree, hf_hpsw_device_id_data, tvb, offset+6, length-6, ENC_NA);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Device ID: Bad length %u", length);
        }
        break;

    case HPFOO_OWN_MAC_ADDR:
        if (length == 6) {
            proto_tree_add_item(tree, hf_hpsw_own_mac_addr, tvb, offset, length, ENC_NA);
        } else {
            expert_add_info_format(pinfo, ti, &ei_hpsw_tlvlength_bad, "Own MAC Addr: Bad length %u", length);
        }
        break;

    default:
        proto_tree_add_text(tree, tvb, offset, length, "Data");
        break;
    }
}
Example #4
0
/*
 * Dissect ASCII TPKT-encapsulated data in a TCP stream.
 */
void
dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
          dissector_handle_t subdissector_handle)
{
    proto_item *ti = NULL;
    proto_tree *tpkt_tree = NULL;
    volatile int offset = 0;
    int length_remaining;
    int data_len;
    volatile int mgcp_packet_len = 0;
    int mgcp_version = 0;
    int mgcp_reserved = 0;
    volatile int length;
    tvbuff_t *volatile next_tvb;
    const char *saved_proto;
    guint8 string[4];

    /*
     * If we're reassembling segmented TPKT PDUs, empty the COL_INFO
     * column, so subdissectors can append information
     * without having to worry about emptying the column.
     *
     * We use "col_add_str()" because the subdissector
     * might be appending information to the column, in
     * which case we'd have to zero the buffer out explicitly
     * anyway.
     */
    if (tpkt_desegment)
        col_set_str(pinfo->cinfo, COL_INFO, "");

    while (tvb_reported_length_remaining(tvb, offset) != 0) {
        /*
         * Is the first byte of this putative TPKT header
         * a valid TPKT version number, i.e. 3?
         */
        if (tvb_get_guint8(tvb, offset) != 48) {
            /*
             * No, so don't assume this is a TPKT header;
             * we might be in the middle of TPKT data,
             * so don't get the length and don't try to
             * do reassembly.
             */
            col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
            col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
            if (tree) {
                ti = proto_tree_add_item(tree, proto_tpkt, tvb,
                             offset, -1, ENC_NA);
                tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);

                proto_tree_add_item(tpkt_tree, hf_tpkt_continuation_data, tvb, offset, -1, ENC_NA);
            }
            return;
        }

        length_remaining = tvb_captured_length_remaining(tvb, offset);

        /*
         * Get the length from the TPKT header.
         */

        tvb_memcpy(tvb, (guint8 *)string, offset, 2);
        mgcp_version = parseVersionText(string);
        tvb_memcpy(tvb, (guint8 *)string, offset +2, 2);
        mgcp_reserved = parseReservedText(string);
        tvb_memcpy(tvb, (guint8 *)string, offset + 4, 4);
        mgcp_packet_len = parseLengthText(string);
        data_len = mgcp_packet_len;

        /*
         * Dissect the TPKT header.
         * Save and restore "pinfo->current_proto".
         */
        saved_proto = pinfo->current_proto;
        pinfo->current_proto = "TPKT";

        col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
        /*
         * Don't add the TPKT header information if we're
         * reassembling segmented TPKT PDUs or if this
         * PDU isn't reassembled.
         *
         * XXX - the first is so that subdissectors can append
         * information without getting TPKT stuff in the middle;
         * why the second?
         */
        if (!tpkt_desegment && !pinfo->fragmented) {
            col_add_fstr(pinfo->cinfo, COL_INFO,
                     "TPKT Data length = %u", data_len);
        }

        if (tree) {
            ti = proto_tree_add_item(tree, proto_tpkt, tvb,
                         offset, 8, ENC_NA);
            tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
            proto_item_set_text(ti, "TPKT");

            /* Version */
            proto_tree_add_uint(tpkt_tree, hf_tpkt_version, tvb,
                        offset, 2, mgcp_version);

            /* Reserved octet*/
            proto_tree_add_uint(tpkt_tree, hf_tpkt_reserved, tvb,
                        offset + 2, 2, mgcp_reserved);

            /* Length */
            proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb,
                        offset + 4, 4, mgcp_packet_len);
        }
        pinfo->current_proto = saved_proto;

        /* Skip the TPKT header. */
        offset += TEXT_LAYER_LENGTH;
        length = length_remaining - TEXT_LAYER_LENGTH;
        if (length > data_len)
            length = data_len;

        next_tvb = tvb_new_subset(tvb, offset,length, data_len);

        /*
         * Call the subdissector.
         *
         * If it gets an error that means there's no point in
         * dissecting any more TPKT messages, rethrow the
         * exception in question.
         *
         * If it gets any other error, report it and continue, as that
         * means that TPKT message got an error, but that doesn't mean
         * we should stop dissecting TPKT messages within this frame
         * or chunk of reassembled data.
         */
        TRY {
            call_dissector(subdissector_handle, next_tvb, pinfo,
                       tree);
        }
        CATCH_NONFATAL_ERRORS {

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

        /*
         * Skip the payload.
         */
        offset += data_len;
    }
}
Example #5
0
/*
 * Dissect TPKT-encapsulated data in a TCP stream.
 */
void
dissect_tpkt_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
           gboolean desegment, dissector_handle_t subdissector_handle)
{
    proto_item *ti = NULL;
    proto_tree *tpkt_tree = NULL;
    volatile int offset = 0;
    int length_remaining;
    int data_len;
    volatile int length;
    tvbuff_t *volatile next_tvb;
    const char *saved_proto;

    /*
     * If we're reassembling segmented TPKT PDUs, empty the COL_INFO
     * column, so subdissectors can append information
     * without having to worry about emptying the column.
     *
     * We use "col_add_str()" because the subdissector
     * might be appending information to the column, in
     * which case we'd have to zero the buffer out explicitly
     * anyway.
     */
    if (desegment)
        col_set_str(pinfo->cinfo, COL_INFO, "");

    while (tvb_reported_length_remaining(tvb, offset) != 0) {
        /*
         * Is the first byte of this putative TPKT header
         * a valid TPKT version number, i.e. 3?
         */
        if (tvb_get_guint8(tvb, offset) != 3) {
            /*
             * No, so don't assume this is a TPKT header;
             * we might be in the middle of TPKT data,
             * so don't get the length and don't try to
             * do reassembly.
             */
            col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
            col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
            if (tree) {
                ti = proto_tree_add_item(tree, proto_tpkt, tvb,
                    offset, -1, ENC_NA);
                tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);

                proto_tree_add_item(tpkt_tree, hf_tpkt_continuation_data, tvb, offset, -1, ENC_NA);
            }
            return;
        }

        length_remaining = tvb_captured_length_remaining(tvb, offset);

        /*
         * Can we do reassembly?
         */
        if (desegment && pinfo->can_desegment) {
            /*
             * Yes - is the TPKT header split across segment
             * boundaries?
             */
            if (length_remaining < 4) {
                /*
                 * Yes.  Tell the TCP dissector where the data
                 * for this message starts in the data it
                 * handed us and that we need "some more data."
                 * Don't tell it exactly how many bytes we need
                 * because if/when we ask for even more (after
                 * the header) that will break reassembly.
                 */
                pinfo->desegment_offset = offset;
                pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
                return;
            }
        }

        /*
         * Get the length from the TPKT header.
         */
        data_len = tvb_get_ntohs(tvb, offset + 2);

        /*
         * Can we do reassembly?
         */
        if (desegment && pinfo->can_desegment) {
            /*
             * Yes - is the payload split across segment
             * boundaries?
             */
            if (length_remaining < data_len) {
                /*
                 * Yes.  Tell the TCP dissector where
                 * the data for this message starts in
                 * the data it handed us, and how many
                 * more bytes we need, and return.
                 */
                pinfo->desegment_offset = offset;
                pinfo->desegment_len =
                    data_len - length_remaining;
                return;
            }
        }

        /*
         * Dissect the TPKT header.
         * Save and restore "pinfo->current_proto".
         */
        saved_proto = pinfo->current_proto;
        pinfo->current_proto = "TPKT";

        col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
        /*
         * Don't add the TPKT header information if we're
         * reassembling segmented TPKT PDUs or if this
         * PDU isn't reassembled.
         *
         * XXX - the first is so that subdissectors can append
         * information without getting TPKT stuff in the middle;
         * why the second?
         */
        if (!desegment && !pinfo->fragmented) {
            col_add_fstr(pinfo->cinfo, COL_INFO,
                "TPKT Data length = %u", data_len);
        }

        if (tree) {
            ti = proto_tree_add_item(tree, proto_tpkt, tvb,
                offset, 4, ENC_NA);
            tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
            proto_item_set_text(ti, "TPKT");

            /* Version */
            proto_tree_add_item(tpkt_tree, hf_tpkt_version, tvb,
                offset, 1, ENC_BIG_ENDIAN);
            proto_item_append_text(ti, ", Version: 3");

            /* Reserved octet*/
            proto_tree_add_item(tpkt_tree, hf_tpkt_reserved, tvb,
                offset + 1, 1, ENC_BIG_ENDIAN);

            /* Length */
            proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb,
                offset + 2, 2, data_len);
            proto_item_append_text(ti, ", Length: %u", data_len);
        }
        pinfo->current_proto = saved_proto;

        /* Skip the TPKT header. */
        offset += 4;
        data_len -= 4;

        /*
         * Construct a tvbuff containing the amount of the payload
         * we have available.  Make its reported length the
         * amount of data in this TPKT packet.
         *
         * XXX - if reassembly isn't enabled. the subdissector
         * will throw a BoundsError exception, rather than a
         * ReportedBoundsError exception.  We really want
         * a tvbuff where the length is "length", the reported
         * length is "plen + 2", and the "if the snapshot length
         * were infinite" length were the minimum of the
         * reported length of the tvbuff handed to us and "plen+2",
         * with a new type of exception thrown if the offset is
         * within the reported length but beyond that third length,
         * with that exception getting the "Unreassembled Packet"
         * error.
         */
        length = length_remaining - 4;
        if (length > data_len)
            length = data_len;
        next_tvb = tvb_new_subset(tvb, offset, length, data_len);

        /*
         * Call the subdissector.
         *
         * If it gets an error that means there's no point in
         * dissecting any more TPKT messages, rethrow the
         * exception in question.
         *
         * If it gets any other error, report it and continue,
         * as that means that TPKT message got an error, but
         * that doesn't mean we should stop dissecting TPKT
         * messages within this frame or chunk of reassembled
         * data.
         */
        TRY {
            call_dissector(subdissector_handle, next_tvb, pinfo,
                tree);
        }
        CATCH_NONFATAL_ERRORS {
            show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
        }
        ENDTRY;

        /*
         * Skip the payload.
         */
        offset += length;
    }
}
Example #6
0
static int
dissect_dvmrp_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
{
	guint8 code;
	guint8 af=2; /* default */

	/* version */
	proto_tree_add_uint(parent_tree, hf_version, tvb, 0, 0, 1);

	/* type of command */
	proto_tree_add_uint(parent_tree, hf_type, tvb, offset, 1, 0x13);
	offset += 1;

	/* code */
	code = tvb_get_guint8(tvb, offset);
	proto_tree_add_uint(parent_tree, hf_code_v1, tvb, offset, 1, code);
	offset += 1;
	if (check_col(pinfo->cinfo, COL_INFO)) {
		col_add_fstr(pinfo->cinfo, COL_INFO,
			"V%d %s",1 ,val_to_str(code, code_v1,
				"Unknown Type:0x%02x"));
	}

	/* checksum */
	igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
	offset += 2;

	/* decode all the v1 commands */
	while (tvb_reported_length_remaining(tvb, offset) > 0) {
		proto_tree *tree;
		proto_item *item;
		guint8 cmd,count;
		int old_offset = offset;

		item = proto_tree_add_item(parent_tree, hf_commands,
				tvb, offset, -1, ENC_NA);
		tree = proto_item_add_subtree(item, ett_commands);

		cmd = tvb_get_guint8(tvb, offset);
		proto_tree_add_uint(tree, hf_command, tvb,
			offset, 1, cmd);
		offset += 1;

		switch (cmd){
		case V1_COMMAND_NULL:
			offset += 1; /* skip ignored/pad byte*/
			if (item) {
				proto_item_set_text(item, "Command: NULL");
			}
			break;
		case V1_COMMAND_AFI:
			af = tvb_get_guint8(tvb, offset);
			proto_tree_add_uint(tree, hf_afi, tvb,
				offset, 1, af);
			offset += 1;
			if (item) {
				proto_item_set_text(item, "%s: %s",
					val_to_str(cmd, command, "Unknown Command:0x%02x"),
					val_to_str(af, afi, "Unknown Family:0x%02x")
				);
			}
			break;
		case V1_COMMAND_SUBNETMASK:
			count = tvb_get_guint8(tvb, offset);
			proto_tree_add_uint(tree, hf_count, tvb,
				offset, 1, count);
			offset += 1;
			if (count) { /* must be 0 or 1 */
				proto_tree_add_item(tree, hf_netmask,
					tvb, offset, 4, ENC_BIG_ENDIAN);
				if (item) {
					proto_item_set_text(item, "%s: %d.%d.%d.%d",
						val_to_str(cmd, command, "Unknown Command:0x%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;
			} else {
				if (item) {
					proto_item_set_text(item, "%s: <no mask supplied>",
						val_to_str(cmd, command, "Unknown Command:0x%02x"));
				}
			}
			break;
		case V1_COMMAND_METRIC:
			proto_tree_add_item(tree, hf_metric, tvb,
				offset, 1, ENC_BIG_ENDIAN);
			if (item) {
				proto_item_set_text(item, "%s: %d",
					val_to_str(cmd, command, "Unknown Command:0x%02x"),
					tvb_get_guint8(tvb, offset));
			}
			offset += 1;
			break;
		case V1_COMMAND_FLAGS0:
			count = tvb_get_guint8(tvb, offset);
			proto_tree_add_boolean(tree, hf_dest_unr, tvb, offset, 1, count);
			proto_tree_add_boolean(tree, hf_split_horiz, tvb, offset, 1, count);
			if (item) {
				proto_item_set_text(item, "%s: 0x%02x",
					val_to_str(cmd, command, "Unknown Command:0x%02x"), count);
			}
			offset += 1;
			break;
		case V1_COMMAND_INFINITY:
			proto_tree_add_item(tree, hf_infinity, tvb,
				offset, 1, ENC_BIG_ENDIAN);
			if (item) {
				proto_item_set_text(item, "%s: %d",
					val_to_str(cmd, command, "Unknown Command:0x%02x"), tvb_get_guint8(tvb, offset));
			}
			offset += 1;
			break;
		case V1_COMMAND_DA:
		case V1_COMMAND_RDA: /* same as DA */
			count = tvb_get_guint8(tvb, offset);
			proto_tree_add_uint(tree, hf_count, tvb,
				offset, 1, count);
			offset += 1;
			while (count--) {
				proto_tree_add_item(tree, hf_daddr,
					tvb, offset, 4, ENC_BIG_ENDIAN);
				offset += 4;
			}
			if (item) {
				proto_item_set_text(item, "%s",
					val_to_str(cmd, command, "Unknown Command:0x%02x"));
			}
			break;
		case V1_COMMAND_NMR:
			count = tvb_get_guint8(tvb, offset);
			proto_tree_add_uint(tree, hf_count, tvb,
				offset, 1, count);
			offset += 1;
			while (count--) {
				proto_tree_add_item(tree, hf_maddr,
					tvb, offset, 4, ENC_BIG_ENDIAN);
				offset += 4;
				proto_tree_add_item(tree, hf_hold, tvb,
					offset, 4, ENC_BIG_ENDIAN);
				offset += 4;
			}
			if (item) {
				proto_item_set_text(item, "%s",
					val_to_str(cmd, command, "Unknown Command:0x%02x"));
			}
			break;
		case V1_COMMAND_NMR_CANCEL:
			count = tvb_get_guint8(tvb, offset);
			proto_tree_add_uint(tree, hf_count, tvb,
				offset, 1, count);
			offset += 1;
			while (count--) {
				proto_tree_add_item(tree, hf_maddr,
					tvb, offset, 4, ENC_BIG_ENDIAN);
				offset += 4;
			}
			if (item) {
				proto_item_set_text(item, "%s",
					val_to_str(cmd, command, "Unknown Command:0x%02x"));
			}
			break;
		}

		proto_item_set_len(item, offset-old_offset);
	}

	return offset;
}
Example #7
0
static int
dissect_adwin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item *ti, *ti2;
	proto_tree *adwin_tree, *adwin_debug_tree;
	gchar *info_string;
	guint32 length;

	length = tvb_reported_length(tvb);

	/* First do some heuristics to see if this packet belongs to us */
	if(! (length == UDPH1_OLD_LENGTH
	      || length == UDPH1_NEW_LENGTH
	      || length == UDPR1_LENGTH
	      || length == UDPH2_LENGTH
	      || length == UDPR2_LENGTH
	      || length == UDPR3_LENGTH
	      || length == UDPR4_LENGTH
	      || length == GetDataSHPacket_LENGTH
	      || length == GetDataSHRequest_LENGTH))
		return(0);

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

	if (tree) {
		ti = proto_tree_add_item(tree, proto_adwin, tvb, 0, -1, ENC_NA);
		adwin_tree = proto_item_add_subtree(ti, ett_adwin);

		ti2 = proto_tree_add_item(adwin_tree, proto_adwin, tvb, 0, -1, ENC_NA);
		adwin_debug_tree = proto_item_add_subtree(ti2, ett_adwin_debug);
		proto_item_set_text(ti2, "ADwin Debug information");
	} else {
		adwin_tree = NULL;
		adwin_debug_tree = NULL;
	}

	switch (length) {
	case UDPH1_OLD_LENGTH:
		dissect_UDPH1_old(tvb, pinfo, adwin_tree, adwin_debug_tree, &info_string);
		break;
	case UDPH1_NEW_LENGTH:
		dissect_UDPH1_new(tvb, pinfo, adwin_tree, adwin_debug_tree, &info_string);
		break;
	case UDPR1_LENGTH:
		dissect_UDPR1(tvb, pinfo, adwin_tree, adwin_debug_tree, &info_string);
		break;
	case UDPH2_LENGTH: /* to the best of my knowledge, this struct
			    * has never been used publically! */
		/* dissect_UDPH2(tvb, pinfo, adwin_tree, adwin_debug_tree); */
		info_string = ep_strdup("UDPH2 - UNUSED");
		break;
	case UDPR2_LENGTH:
		dissect_UDPR2(tvb, pinfo, adwin_tree, adwin_debug_tree, &info_string);
		break;
	case UDPR3_LENGTH:
		dissect_UDPR3(tvb, pinfo, adwin_tree, adwin_debug_tree);
		info_string = ep_strdup("UDPR3");
		break;
	case UDPR4_LENGTH:
		dissect_UDPR4(tvb, pinfo, adwin_tree, adwin_debug_tree, &info_string);
		break;
	case GetDataSHPacket_LENGTH:
		dissect_GDSHP(tvb, pinfo, adwin_tree, adwin_debug_tree);
		info_string = ep_strdup("GDSHP");
		break;
	case GetDataSHRequest_LENGTH:
		dissect_GDSHR(tvb, pinfo, adwin_tree, adwin_debug_tree);
		info_string = ep_strdup("GDSHR");
		break;
	default:
		info_string = ep_strdup_printf("Unknown ADwin packet, length: %d", length);
		break;
	}

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

	return (tvb_reported_length(tvb));
}
Example #8
0
static void
dissect_hpsw_tlv(tvbuff_t *tvb, int offset, int length,
    proto_tree *tree, proto_item *ti, guint8 type)
{
    switch (type) {

    case HPFOO_DEVICE_NAME:
        if (length > 0) {
            proto_item_set_text(ti, "Device Name: %s", tvb_format_text(tvb, offset, length - 1));
            proto_tree_add_text(tree, tvb, offset, length, "Device Name: %s", tvb_format_text(tvb, offset, length - 1));
        } else {
            proto_item_set_text(ti, "Device Name: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "Device Name: Bad length %u", length);
        }
        break;

    case HPFOO_DEVICE_VERSION:
        if (length > 0) {
            proto_item_set_text(ti, "Version: %s", tvb_format_text(tvb, offset, length - 1));
            proto_tree_add_text(tree, tvb, offset, length, "Version: %s", tvb_format_text(tvb, offset, length - 1));
        } else {
            proto_item_set_text(ti, "Version: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "Version: Bad length %u", length);
        }
        break;

    case HPFOO_CONFIG_NAME:
        if (length > 0) {
            proto_item_set_text(ti, "Config: %s", tvb_format_text(tvb, offset, length - 1));
            proto_tree_add_text(tree, tvb, offset, length, "Config: %s", tvb_format_text(tvb, offset, length - 1));
        } else {
            proto_item_set_text(ti, "Config: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "Config: Bad length %u", length);
        }
        break;

    case HPFOO_IP_ADDR:
        if (length == 4) {
	    const char *ipstr = tvb_ip_to_str(tvb, offset);
            proto_item_set_text(ti, "IP Addr: %s", ipstr);
            proto_tree_add_text(tree, tvb, offset, length, "IP Addr: %s", ipstr);
        } else {
            proto_item_set_text(ti, "IP Addr: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "IP Addr: Bad length %u", length);
        }
        break;

    case HPFOO_FIELD_7:
        if (length == 1) {
            proto_item_set_text(ti, "Field 7: 0x%02x", tvb_get_guint8(tvb,offset));
            proto_tree_add_text(tree, tvb, offset, length, "Field 7: 0x%02x", tvb_get_guint8(tvb,offset));
        } else {
            proto_item_set_text(ti, "Field 7: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "Field 7: Bad length %u", length);
        }
        break;

    case HPFOO_FIELD_8:
        if (length == 2) {
            proto_item_set_text(ti, "Field 8: 0x%04x", tvb_get_ntohs(tvb,offset));
            proto_tree_add_text(tree, tvb, offset, length, "Field 8: 0x%04x", tvb_get_ntohs(tvb,offset));
        } else {
            proto_item_set_text(ti, "Field 8: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "Field 8: Bad length %u", length);
        }
        break;

    case HPFOO_FIELD_9:
        if (length == 2) {
            proto_item_set_text(ti, "Field 9: 0x%04x", tvb_get_ntohs(tvb,offset));
            proto_tree_add_text(tree, tvb, offset, length, "Field 9: 0x%04x", tvb_get_ntohs(tvb,offset));
        } else {
            proto_item_set_text(ti, "Field 9: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "Field 9: Bad length %u", length);
        }
        break;

    case HPFOO_FIELD_10:
        if (length == 4) {
            proto_item_set_text(ti, "Field 10: 0x%08x", tvb_get_ntohl(tvb,offset));
            proto_tree_add_text(tree, tvb, offset, length, "Field 10: 0x%08x", tvb_get_ntohl(tvb,offset));
        } else {
            proto_item_set_text(ti, "Field 10: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "Field 10: Bad length %u", length);
        }
        break;

    case HPFOO_FIELD_12:
        if (length == 1) {
            proto_item_set_text(ti, "Field 12: 0x%02x", tvb_get_guint8(tvb,offset));
            proto_tree_add_text(tree, tvb, offset, length, "Field 12: 0x%02x", tvb_get_guint8(tvb,offset));
        } else {
            proto_item_set_text(ti, "Field 12: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "Field 12: Bad length %u", length);
        }
        break;

    case HPFOO_DEVICE_ID:
        if (length == 10) {
	    const gchar *macstr = tvb_ether_to_str(tvb, offset);
            guint32 id=tvb_get_ntohl(tvb, offset+6);
            proto_item_set_text(ti, "Device ID: %s / %u", macstr, id);
            proto_tree_add_text(tree, tvb, offset, 10, "Device ID: %s / %u", macstr, id);
        } else {
            proto_item_set_text(ti, "Device ID: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "Device ID: Bad length %u", length);
        }
        break;

    case HPFOO_MAC_ADDR:
        if (length == 6) {
            const gchar *macstr = tvb_ether_to_str(tvb, offset);
            proto_item_set_text(ti, "MAC Addr: %s", macstr);
            proto_tree_add_text(tree, tvb, offset, length, "MAC Addr: %s", macstr);
        } else {
            proto_item_set_text(ti, "MAC Addr: Bad length %u", length);
            proto_tree_add_text(tree, tvb, offset, length, "MAC Addr: Bad length %u", length);
        }
        break;

    default:
        proto_tree_add_text(tree, tvb, offset, length, "Data");
        break;
    }
}
Example #9
0
static void dissect_nv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
   proto_item *ti;
   proto_tree *nv_tree, *nv_header_tree, *nv_var_tree,*nv_varheader_tree;
   gint offset = 0;
   char szText[200];
   int nMax = (int)sizeof(szText)-1;

   gint i;

   col_set_str(pinfo->cinfo, COL_PROTOCOL, "TC-NV");

   col_clear(pinfo->cinfo, COL_INFO);

   NvSummaryFormater(tvb, offset, szText, nMax);
   col_append_str(pinfo->cinfo, COL_INFO, szText);

   if (tree)
   {
      guint16 nv_count;

      ti = proto_tree_add_item(tree, proto_nv, tvb, 0, -1, ENC_NA);
      nv_tree = proto_item_add_subtree(ti, ett_nv);
      proto_item_append_text(ti,": %s",szText);

      ti = proto_tree_add_item(nv_tree, hf_nv_header, tvb, offset, NvParserHDR_Len, ENC_NA);

      nv_header_tree = proto_item_add_subtree(ti, ett_nv_header);

      ti= proto_tree_add_item(nv_header_tree, hf_nv_publisher, tvb, offset, (int)sizeof(guint8)*6, ENC_NA);
      NvPublisherFormater(tvb, offset, szText, nMax);
      proto_item_set_text(ti, "%s", szText);
      offset+=((int)sizeof(guint8)*6);

      proto_tree_add_item(nv_header_tree, hf_nv_count, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN);
      nv_count = tvb_get_letohs(tvb, offset);
      offset+=(int)sizeof(guint16);

      proto_tree_add_item(nv_header_tree, hf_nv_cycleindex, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN);
      offset = NvParserHDR_Len;

      for ( i=0; i < nv_count; i++ )
      {
         guint16 var_length = tvb_get_letohs(tvb, offset+4);

         ti = proto_tree_add_item(nv_tree, hf_nv_variable, tvb, offset, ETYPE_88A4_NV_DATA_HEADER_Len+var_length, ENC_NA);
         NvVarHeaderFormater(tvb, offset, szText, nMax);
         proto_item_set_text(ti, "%s", szText);

         nv_var_tree = proto_item_add_subtree(ti, ett_nv_var);
         ti = proto_tree_add_item(nv_var_tree, hf_nv_varheader, tvb, offset, ETYPE_88A4_NV_DATA_HEADER_Len, ENC_NA);

         nv_varheader_tree = proto_item_add_subtree(ti, ett_nv_varheader);
         proto_tree_add_item(nv_varheader_tree, hf_nv_id, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN);
         offset+=(int)sizeof(guint16);

         proto_tree_add_item(nv_varheader_tree, hf_nv_hash, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN);
         offset+=(int)sizeof(guint16);

         proto_tree_add_item(nv_varheader_tree, hf_nv_length, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN);
         offset+=(int)sizeof(guint16);

         proto_tree_add_item(nv_varheader_tree, hf_nv_quality, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN);
         offset+=(int)sizeof(guint16);

         proto_tree_add_item(nv_var_tree, hf_nv_data, tvb, offset, var_length, ENC_NA);
         offset+=var_length;
      }
   }
}
Example #10
0
static void
dissect_wai(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Format of WAPI protocol packet in WAI authentication system

0      2      3         4         6         8        10        11      12
-------------------------------------------------------------------------------
| Ver. | Type | Subtype | Reserved | Length | packet  |  fragm. | flag | data |
|                                           | seq. no | seq. no |             |
|-----------------------------------------------------------------------------|
Figure 18 from [ref:1]
*/
#define WAI_MESSAGE_LENGTH 12   /*Length of all fields without 'Data' field*/
#define WAI_DATA_OFFSET    WAI_MESSAGE_LENGTH
    guint16        version;
    guint8         subtype;
    guint16        length;
    guint16        packet_num;
    guint8         fragment_num;
    guint8         flags;
    fragment_head *frag_msg;
    proto_tree    *wai_tree     = NULL;
    tvbuff_t      *next_tvb;
    tvbuff_t      *new_tvb;
    const gchar   *subtype_name = "Unknown type";

    length = tvb_get_ntohs(tvb, 6)-WAI_MESSAGE_LENGTH;
    subtype = tvb_get_guint8(tvb, 3);

    /* quick sanity check */
    if ((length != tvb_reported_length (tvb)-WAI_MESSAGE_LENGTH) ||
        (subtype > WAI_SUB_MULTICAST_ANNOUNCE_RESP)) {
        return;
    }

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "WAI");
    col_clear(pinfo->cinfo, COL_INFO);
    version = tvb_get_ntohs(tvb, 0);

    if (version == 1) {
        subtype_name = val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type");
    }
    col_append_fstr(pinfo->cinfo, COL_INFO, "%s", subtype_name);

    /* Field lengths and offsets in WAI protocol described above */
    packet_num   = tvb_get_ntohs(tvb, 8);
    fragment_num = tvb_get_guint8(tvb, 10);
    flags        = tvb_get_guint8(tvb, 11);

    if (tree) {
        proto_item *wai_item;

        wai_item = proto_tree_add_item(tree, proto_wai, tvb, 0, -1, ENC_NA);

        proto_item_set_text (wai_item, "WAI Protocol (%s)",
                                val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type"));
        wai_tree = proto_item_add_subtree(wai_item, ett_wai);

        /* Field lengths and offsets in WAI protocol described above */
        proto_tree_add_item(wai_tree, hf_wai_version,   tvb, 0,  2, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_type,      tvb, 2,  1, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_subtype,   tvb, 3,  1, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_reserved,  tvb, 4,  2, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_length,    tvb, 6,  2, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_seq,       tvb, 8,  2, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_fragm_seq, tvb, 10, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_flag,      tvb, 11, 1, ENC_BIG_ENDIAN);
    }

    frag_msg =  fragment_add_seq_check (&wai_reassembly_table,
                                        tvb, WAI_DATA_OFFSET,
                                        pinfo,
                                        packet_num,
                                        NULL,
                                        fragment_num,
                                        length,
                                        flags);

    next_tvb = tvb_new_subset_remaining(tvb, WAI_DATA_OFFSET);

    /* Replace INFO column if message is fragmented and call data_handle */
    if (flags) {
        col_add_fstr(pinfo->cinfo, COL_INFO,
                     "Fragment (%d) of message, data not dissected", fragment_num);

        process_reassembled_data(tvb, WAI_DATA_OFFSET, pinfo,
                                 "Reassembled WAI", frag_msg, &wai_frag_items,
                                 NULL, wai_tree);

        call_dissector(data_handle, next_tvb, pinfo, tree);
    } else {
        /* If this is the last fragment of fragmented message, then reassamble and dissect
           otherwise only dissect */
        if (fragment_num > 0) {
            new_tvb = process_reassembled_data(tvb, WAI_DATA_OFFSET, pinfo,
                                               "Reassembled WAI", frag_msg, &wai_frag_items,
                                               NULL, wai_tree);

            if (new_tvb) {
                col_add_str(pinfo->cinfo, COL_INFO, "Last fragment of message, data dissected");
                col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", subtype_name);
                next_tvb=new_tvb;
                length = tvb_reported_length (next_tvb);
            }
        }
        /* dissect Data field of WAI packet */
        if (tree) {
            dissect_wai_data(next_tvb, wai_tree, subtype, length);
        }
    }

}
Example #11
0
static void
dissect_dtp_tlv(tvbuff_t *tvb, int offset, int length,
    proto_tree *tree, proto_item *ti, guint8 type)
{
	switch (type) {

	case TYPE_DOMAIN:
		if (length > 0) {
			proto_item_set_text(ti, "Domain: %s", tvb_format_text(tvb, offset, length - 1));
			proto_tree_add_text(tree, tvb, offset, length, "Domain: %s", tvb_format_text(tvb, offset, length - 1));
		} else {
			proto_item_set_text(ti, "Domain: Bad length %u", length);
			proto_tree_add_text(tree, tvb, offset, length, "Domain: Bad length %u", length);
		}
		break;

	case TYPE_STATUS:
		if (length > 0) {
			proto_item_set_text(ti,
			    "Status: 0x%02x",
			    tvb_get_guint8(tvb, offset));
			proto_tree_add_text(tree, tvb, offset, 1,
			    "Status: 0x%02x",
			    tvb_get_guint8(tvb, offset));
		} else {
			proto_item_set_text(ti,
			    "Status: Bad length %u",
			    length);
			proto_tree_add_text(tree, tvb, offset, length,
			    "Status: Bad length %u",
			    length);
		}
		break;

	case TYPE_DTPTYPE:
		if (length > 0) {
			proto_item_set_text(ti,
			    "Dtptype: 0x%02x",
			    tvb_get_guint8(tvb, offset));
			proto_tree_add_text(tree, tvb, offset, 1,
			    "Dtptype: 0x%02x",
			    tvb_get_guint8(tvb, offset));
		} else {
			proto_item_set_text(ti,
			    "Dtptype: Bad length %u",
			    length);
			proto_tree_add_text(tree, tvb, offset, length,
			    "Dtptype: Bad length %u",
			    length);
		}
		break;


	case TYPE_NEIGHBOR:
		if (length == 6) {
			proto_item_set_text(ti, "Neighbor: %s",
				tvb_ether_to_str(tvb, offset));	/* XXX - resolve? */
            		proto_tree_add_item(tree, hf_dtp_some_mac, tvb, offset, length, ENC_NA);
		} else {
			proto_item_set_text(ti,
			    "Neighbor: Bad length %u",
			    length);
			proto_tree_add_text(tree, tvb, offset, length,
			    "Neighbor: Bad length %u",
			    length);
		}
		break;

	default:
		proto_tree_add_text(tree, tvb, offset, length, "Data");
		break;
	}
}
Example #12
0
static void
dissect_wai_data(tvbuff_t *tvb, proto_tree *tree, guint8 subtype, guint16 lenx)
{
    proto_item  *data_item;
    proto_tree  *data_tree;
    const gchar *type_name;

    data_item = proto_tree_add_item(tree, hf_wai_data, tvb, 0, lenx, ENC_NA);
    data_tree = proto_item_add_subtree (data_item, ett_wai_data);

    type_name = val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type");

    proto_item_set_text(data_item, "%s data (%d bytes)", type_name, lenx);

    switch (subtype) {
        case WAI_SUB_PRE_AUTHENTICATION:
        {
            /* Chapter 8.1.4.6 Preauthentication [ref: 1] */
            dissect_flag(tvb, 0, data_tree);
            dissect_uskid(tvb, 1, data_tree);
            dissect_addid(tvb, 2, data_tree);
            dissect_counter(tvb, 14, data_tree);
            dissect_message_auth_code(tvb, 30, data_tree);
            break;
        }
        case WAI_SUB_STAKEY_REQ:
        {
            /* Chapter 8.1.4.5 STAKey Establishment procedure [ref: 1] */
            dissect_flag(tvb, 0, data_tree);
            proto_tree_add_item(data_tree, hf_wai_sta_key_id, tvb, 1, 1, ENC_BIG_ENDIAN);
            dissect_uskid(tvb, 2, data_tree);
            dissect_addid(tvb, 3, data_tree);
            dissect_counter(tvb, 15, data_tree);
            dissect_message_auth_code(tvb, 31, data_tree);
            break;
        }
        case WAI_SUB_AUTH_ACTIVATION:
        {
            /* Chapter 8.1.4.2.1 WAI Authentication Activation  [ref: 1] */
            guint16 offset = 0;

            dissect_flag(tvb, offset, data_tree);
            offset += 1;
            dissect_authentication_id(tvb, offset, data_tree);
            offset += 32;
            offset += dissect_identity(tvb, offset, data_tree, "Local ASU ");
            offset += dissect_certificate(tvb, offset, data_tree, "STE AE ");
            dissect_ecdh_parameter(tvb, offset, data_tree);
            break;
        }
        case WAI_SUB_ACCESS_AUTH_REQ:
        {
            /* Chapter 8.1.4.2.2 Access WAI Authentication Request  [ref: 1] */
            guint16 offset = 0;
            guint8  optional_field;

            optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3;

            dissect_flag(tvb, offset, data_tree);
            offset += 1;
            dissect_authentication_id(tvb, offset, data_tree);
            offset += 32;
            offset += dissect_challenge(tvb, offset, data_tree, "ASUE ");
            offset += dissect_key_data(tvb, offset, data_tree, "ASUE ");
            offset += dissect_identity(tvb, offset, data_tree, "STA AE ");
            offset += dissect_certificate(tvb, offset, data_tree, "STA ASUE ");
            offset += dissect_ecdh_parameter(tvb, offset, data_tree);

            if (optional_field) {
                offset += dissect_identity_list(tvb, offset, data_tree);
            }

            dissect_signature(tvb, offset, data_tree, "ASUE Signature");
            break;
        }
        case WAI_SUB_ACCESS_AUTH_RESP:
        {
            /* Chapter 8.1.4.2.5 Access WAI Authentication Response  [ref: 1] */
            guint16 offset = 0;
            guint8  optional_field;

            optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3;

            dissect_flag(tvb, offset, data_tree);
            offset += 1;
            offset += dissect_challenge(tvb, offset, data_tree, "ASUE ");
            offset += dissect_challenge(tvb, offset, data_tree, "AE ");
            proto_tree_add_item(data_tree, hf_wai_access_res, tvb, offset, 1, ENC_BIG_ENDIAN);
            offset += 1;
            offset += dissect_key_data(tvb, offset, data_tree, "ASUE ");
            offset += dissect_key_data(tvb, offset, data_tree, "AE ");
            offset += dissect_identity(tvb, offset, data_tree, "STA AE ");
            offset += dissect_identity(tvb, offset, data_tree, "STA ASUE ");

            if (optional_field) {
                offset += dissect_multiple_certificate(tvb, offset, data_tree);
            }

            dissect_signature(tvb, offset, data_tree, "AE Signature");
            break;
        }
        case WAI_SUB_CERT_AUTH_REQ:
        {
            /* Chapter 8.1.4.2.3 Certificate Authentication Request  [ref: 1] */
            guint16 offset = 0;

            dissect_addid(tvb, offset, data_tree);
            offset += 12;
            offset += dissect_challenge(tvb, offset, data_tree, "AE ");
            offset += dissect_challenge(tvb, offset, data_tree, "ASUE ");
            offset += dissect_certificate(tvb, offset, data_tree, "STE ASUE ");
            offset += dissect_certificate(tvb, offset, data_tree, "STE AE ");
            dissect_multiple_certificate(tvb, offset, data_tree);
            break;
        }
        case WAI_SUB_CERT_AUTH_RESP:
        {
            /* Chapter 8.1.4.2.4 Certificate Authentication Response  [ref: 1] */
            guint16 offset = 0;

            dissect_addid(tvb, offset, data_tree);
            offset += 12;
            offset += dissect_multiple_certificate(tvb, offset, data_tree);
            offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by ASUE");
            dissect_signature(tvb, offset, data_tree, "Server Signature trusted by AE");
            break;
        }
        case WAI_SUB_UNICAST_KEY_REQ:
        {
            /* Chapter 8.1.4.3.1 Unicast Key Negotiation Request [ref: 1] */
            dissect_flag(tvb, 0, data_tree);
            dissect_bkid(tvb, 1, data_tree);
            dissect_uskid(tvb, 17, data_tree);
            dissect_addid(tvb, 18, data_tree);
            dissect_challenge(tvb, 30, data_tree , "AE ");
            break;
        }
        case WAI_SUB_UNICAST_KEY_RESP:
        {
            /* Chapter 8.1.4.3.2 Unicast Key Negotiation Response [ref: 1] */
            tvbuff_t *next_tvb;
            guint     length = 0;

            dissect_flag(tvb, 0, data_tree);
            dissect_bkid(tvb, 1, data_tree);
            dissect_uskid(tvb, 17, data_tree);
            dissect_addid(tvb, 18, data_tree);
            dissect_challenge(tvb, 30, data_tree, "ASUE ");
            dissect_challenge(tvb, 62, data_tree, "AE ");

            next_tvb = tvb_new_subset_remaining(tvb, 96);
            length = tvb_reported_length(next_tvb);

            dissect_wie(next_tvb, 0, length-20, data_tree);
            dissect_message_auth_code(next_tvb, length-20, data_tree);
            break;
        }
        case WAI_SUB_UNICAST_KEY_CONFIRM:
        {
            /* Chapter 8.1.4.3.3 Unicast Key Negotiation Confirmation [ref: 1] */
            tvbuff_t *next_tvb;
            guint     length = 0;

            dissect_flag(tvb, 0, data_tree);
            dissect_bkid(tvb, 1, data_tree);
            dissect_uskid(tvb, 17, data_tree);
            dissect_addid(tvb, 18, data_tree);
            dissect_challenge(tvb, 30, data_tree, "ASUE ");

            next_tvb = tvb_new_subset_remaining(tvb, 62);
            length = tvb_reported_length(next_tvb);

            dissect_wie(next_tvb, 0, length-20, data_tree);
            dissect_message_auth_code(next_tvb, length-20, data_tree);
            break;
        }
        case WAI_SUB_MULTICAST_ANNOUNCE:
        {
            /* Chapter 8.1.4.4.1 Multicast Key/STAKey Announcement [ref: 1] */
            guint16 offset = 0;

            dissect_flag(tvb, offset, data_tree);
            offset += 1;
            dissect_mskid(tvb, offset, data_tree);
            offset += 1;
            dissect_uskid(tvb, offset, data_tree);
            offset += 1;
            dissect_addid(tvb, offset, data_tree);
            offset += 12;
            proto_tree_add_item(data_tree, hf_wai_data_pack_num, tvb, offset, 16, ENC_NA);
            offset += 16;
            dissect_key_announcement_identifier(tvb, offset, data_tree);
            offset += 16;
            offset += dissect_key_data(tvb, offset, data_tree, NULL);
            dissect_message_auth_code(tvb, offset, data_tree);
            break;
        }
        case WAI_SUB_MULTICAST_ANNOUNCE_RESP:
        {
            /* Chapter 8.1.4.4.2 Multicast Key/STAKey Announcement Response [ref: 1] */
            dissect_flag(tvb,  0, data_tree);
            dissect_mskid(tvb, 1, data_tree);
            dissect_uskid(tvb, 2, data_tree);
            dissect_addid(tvb, 3, data_tree);
            dissect_key_announcement_identifier(tvb, 15, data_tree);
            dissect_message_auth_code(tvb, 31, data_tree);
            break;
        }
        default:
            break;
    }
}
Example #13
0
static int
dissect_bencoded_dict_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset )
{
  proto_item *ti;
  proto_tree *sub_tree;
  gboolean    tohex;
  const char *key;
  const char *val;
  guint       orig_offset = offset;

  key = NULL;
  val = NULL;

  ti       = proto_tree_add_item( tree, hf_bencoded_dict_entry, tvb, offset, 0, ENC_NA );
  sub_tree = proto_item_add_subtree( ti, ett_bencoded_dict_entry);

  /* dissect the key, it must be a string */
  offset   = dissect_bencoded_string( tvb, pinfo, sub_tree, offset, &key, FALSE, "Key" );

  /* If it is a dict, then just do recursion */
  switch( tvb_get_guint8(tvb,offset) )
  {
  case 'd':
    offset = dissect_bencoded_dict( tvb, pinfo, sub_tree, offset, "Value" );
    val    = dict_str;
    break;
  case 'l':
    if( strcmp(key,"e")==0 )
      offset = dissect_bt_dht_error( tvb, pinfo, sub_tree, offset, &val, "Value" );
    else if( strcmp(key,"values")==0 )
      offset = dissect_bt_dht_values( tvb, pinfo, sub_tree, offset, &val, "Value" );
    /* other unfamiliar lists */
    else
    {
      offset = dissect_bencoded_list( tvb, pinfo, sub_tree, offset, "Value" );
      val = list_str;
    }
    break;
  case 'i':
    offset = dissect_bencoded_int( tvb, pinfo, sub_tree, offset, &val, "Value" );
    break;
  /* it's a string */
  default:
    /* special process */
    if( strcmp(key,"nodes")==0 )
    {
      offset = dissect_bt_dht_nodes( tvb, pinfo, sub_tree, offset, &val, "Value" );
    }
    else if( strcmp(key,"ip")==0 )
    {
      /*
       * Not found in BEP 0005 but explained by
       * http://www.rasterbar.com/products/libtorrent/dht_sec.html
       */

      int len, old_offset;
      old_offset = offset;
      len = bencoded_string_length(tvb, &offset);

      if(len == 4) {
        proto_tree_add_item(sub_tree, hf_ip, tvb, offset, len, ENC_BIG_ENDIAN);
        val = tvb_ip_to_str(tvb, offset);
        offset += len;
      }
      else {
        offset = dissect_bencoded_string( tvb, pinfo, sub_tree, old_offset, &val, TRUE, "Value" );
      }
    }
    else
    {
      /* some need to return hex string */
      tohex = strcmp(key,"id")==0 || strcmp(key,"target")==0
           || strcmp(key,"info_hash")==0 || strcmp(key,"t")==0
           || strcmp(key,"v")==0 || strcmp(key,"token")==0;
      offset = dissect_bencoded_string( tvb, pinfo, sub_tree, offset, &val, tohex, "Value" );
    }
  }

  if( strlen(key)==1 )
    key = val_to_str_const( key[0], short_key_name_value_string, key );
  if( strlen(val)==1 )
    val = val_to_str_const( val[0], short_val_name_value_string, val );

  proto_item_set_text( ti, "%s: %s", key, val );
  proto_item_set_len( ti, offset-orig_offset );

  if( strcmp(key,"message_type")==0 || strcmp(key,"request_type")==0 )
    col_append_fstr(pinfo->cinfo, COL_INFO, "%s=%s ", key, val);

  return offset;
}
Example #14
0
static void
dissect_vlan_info_tlv(tvbuff_t *tvb, int offset, int length,
                      proto_tree *tree, proto_item *ti, guint8 type)
{
    switch (type) {

    case SR_RING_NUM:
        if (length == 2) {
            proto_item_set_text(ti,
                                "Source-Routing Ring Number: 0x%04x",
                                tvb_get_ntohs(tvb, offset));
            proto_tree_add_text(tree, tvb, offset, 2,
                                "Source-Routing Ring Number: 0x%04x",
                                tvb_get_ntohs(tvb, offset));
        } else {
            proto_item_set_text(ti,
                                "Source-Routing Ring Number: Bad length %u",
                                length);
            proto_tree_add_text(tree, tvb, offset, length,
                                "Source-Routing Ring Number: Bad length %u",
                                length);
        }
        break;

    case SR_BRIDGE_NUM:
        if (length == 2) {
            proto_item_set_text(ti,
                                "Source-Routing Bridge Number: 0x%04x",
                                tvb_get_ntohs(tvb, offset));
            proto_tree_add_text(tree, tvb, offset, 2,
                                "Source-Routing Bridge Number: 0x%04x",
                                tvb_get_ntohs(tvb, offset));
        } else {
            proto_item_set_text(ti,
                                "Source-Routing Bridge Number: Bad length %u",
                                length);
            proto_tree_add_text(tree, tvb, offset, length,
                                "Source-Routing Bridge Number: Bad length %u",
                                length);
        }
        break;

    case STP_TYPE:
        if (length == 2) {
            proto_item_set_text(ti,
                                "Spanning-Tree Protocol Type: %s",
                                val_to_str(tvb_get_ntohs(tvb, offset), stp_type_vals,
                                           "Unknown (0x%04x)"));
            proto_tree_add_text(tree, tvb, offset, 2,
                                "Spanning-Tree Protocol Type: %s",
                                val_to_str(tvb_get_ntohs(tvb, offset), stp_type_vals,
                                           "Unknown (0x%04x)"));
        } else {
            proto_item_set_text(ti,
                                "Spanning-Tree Protocol Type: Bad length %u",
                                length);
            proto_tree_add_text(tree, tvb, offset, length,
                                "Spanning-Tree Protocol Type: Bad length %u",
                                length);
        }
        break;

    case PARENT_VLAN:
        if (length == 2) {
            proto_item_set_text(ti,
                                "Parent VLAN: 0x%04x",
                                tvb_get_ntohs(tvb, offset));
            proto_tree_add_text(tree, tvb, offset, 2,
                                "Parent VLAN: 0x%04x",
                                tvb_get_ntohs(tvb, offset));
        } else {
            proto_item_set_text(ti,
                                "Parent VLAN: Bad length %u",
                                length);
            proto_tree_add_text(tree, tvb, offset, length,
                                "Parent VLAN: Bad length %u",
                                length);
        }
        break;

    case TR_BRIDGED_VLANS:
        if (length == 2) {
            proto_item_set_text(ti,
                                "Translationally Bridged VLANs: 0x%04x",
                                tvb_get_ntohs(tvb, offset));
            proto_tree_add_text(tree, tvb, offset, 2,
                                "Translationally Bridged VLANs: 0x%04x",
                                tvb_get_ntohs(tvb, offset));
        } else {
            proto_item_set_text(ti,
                                "Translationally Bridged VLANs: Bad length %u",
                                length);
            proto_tree_add_text(tree, tvb, offset, length,
                                "Translationally Bridged VLANs: Bad length %u",
                                length);
        }
        break;

    case PRUNING:
        if (length == 2) {
            proto_item_set_text(ti,
                                "Pruning: %s",
                                val_to_str(tvb_get_ntohs(tvb, offset), pruning_vals,
                                           "Unknown (0x%04x)"));
            proto_tree_add_text(tree, tvb, offset, 2,
                                "Pruning: %s",
                                val_to_str(tvb_get_ntohs(tvb, offset), pruning_vals,
                                           "Unknown (0x%04x)"));
        } else {
            proto_item_set_text(ti,
                                "Pruning: Bad length %u",
                                length);
            proto_tree_add_text(tree, tvb, offset, length,
                                "Pruning: Bad length %u",
                                length);
        }
        break;

    case BRIDGE_TYPE:
        if (length == 2) {
            proto_item_set_text(ti,
                                "Bridge Type: %s",
                                val_to_str(tvb_get_ntohs(tvb, offset), bridge_type_vals,
                                           "Unknown (0x%04x)"));
            proto_tree_add_text(tree, tvb, offset, 2,
                                "Bridge Type: %s",
                                val_to_str(tvb_get_ntohs(tvb, offset), bridge_type_vals,
                                           "Unknown (0x%04x)"));
        } else {
            proto_item_set_text(ti,
                                "Bridge Type: Bad length %u",
                                length);
            proto_tree_add_text(tree, tvb, offset, length,
                                "Bridge Type: Bad length %u",
                                length);
        }
        break;

    case MAX_ARE_HOP_CNT:
        if (length == 2) {
            proto_item_set_text(ti,
                                "Max ARE Hop Count: %u",
                                tvb_get_ntohs(tvb, offset));
            proto_tree_add_text(tree, tvb, offset, 2,
                                "Max ARE Hop Count: %u",
                                tvb_get_ntohs(tvb, offset));
        } else {
            proto_item_set_text(ti,
                                "Max ARE Hop Count: Bad length %u",
                                length);
            proto_tree_add_text(tree, tvb, offset, length,
                                "Max ARE Hop Count: Bad length %u",
                                length);
        }
        break;

    case MAX_STE_HOP_CNT:
        if (length == 2) {
            proto_item_set_text(ti,
                                "Max STE Hop Count: %u",
                                tvb_get_ntohs(tvb, offset));
            proto_tree_add_text(tree, tvb, offset, 2,
                                "Max STE Hop Count: %u",
                                tvb_get_ntohs(tvb, offset));
        } else {
            proto_item_set_text(ti,
                                "Max STE Hop Count: Bad length %u",
                                length);
            proto_tree_add_text(tree, tvb, offset, length,
                                "Max STE Hop Count: Bad length %u",
                                length);
        }
        break;

    case BACKUP_CRF_MODE:
        if (length == 2) {
            proto_item_set_text(ti,
                                "Backup CRF Mode: %s",
                                val_to_str(tvb_get_ntohs(tvb, offset), backup_crf_mode_vals,
                                           "Unknown (0x%04x)"));
            proto_tree_add_text(tree, tvb, offset, 2,
                                "Backup CRF Mode: %s",
                                val_to_str(tvb_get_ntohs(tvb, offset), backup_crf_mode_vals,
                                           "Unknown (0x%04x)"));
        } else {
            proto_item_set_text(ti,
                                "Backup CRF Mode: Bad length %u",
                                length);
            proto_tree_add_text(tree, tvb, offset, length,
                                "Backup CRF Mode: Bad length %u",
                                length);
        }
        break;

    default:
        proto_tree_add_text(tree, tvb, offset, length, "Data");
        break;
    }
}
Example #15
0
static int
dissect_mrdisc_mra(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
{
	guint16 num;

	/* Advertising Interval */
	proto_tree_add_item(parent_tree, hf_advint, tvb, offset, 1, ENC_BIG_ENDIAN);
	offset += 1;

	/* checksum */
	igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
	offset += 2;

	/* skip unused bytes */
	offset += 2;

	/* number of options */
	num = tvb_get_ntohs(tvb, offset);
	proto_tree_add_uint(parent_tree, hf_numopts, tvb,
		offset, 2, num);
	offset += 2;

	/* process any options */
	while (num--) {
		proto_tree *tree;
		proto_item *item;
		guint8 type,len;
		int old_offset = offset;

		item = proto_tree_add_item(parent_tree, hf_options,
			tvb, offset, -1, ENC_NA);
		tree = proto_item_add_subtree(item, ett_options);

		type = tvb_get_guint8(tvb, offset);
		proto_tree_add_uint(tree, hf_option, tvb, offset, 1, type);
		offset += 1;

		len = tvb_get_guint8(tvb, offset);
		proto_tree_add_uint(tree, hf_option_len, tvb, offset, 1, len);
		offset += 1;

		switch (type) {
		case MRDISC_QI:
			proto_item_set_text(item,"Option: %s == %d",
					val_to_str(type, mrdisc_options, "unknown %x"),
					tvb_get_ntohs(tvb, offset));
			proto_tree_add_item(tree, hf_qi, tvb, offset, len,
				ENC_BIG_ENDIAN);
			offset += len;
			break;
		case MRDISC_RV:
			proto_item_set_text(item,"Option: %s == %d",
					val_to_str(type, mrdisc_options, "unknown %x"),
					tvb_get_ntohs(tvb, offset));
			proto_tree_add_item(tree, hf_rv, tvb, offset, len,
				ENC_BIG_ENDIAN);
			offset += len;
			break;
		default:
			proto_item_set_text(item,"Option: unknown");

			proto_tree_add_item(tree, hf_option_bytes,
				tvb, offset, len, ENC_NA);
			offset += len;
		}
		proto_item_set_len(item, offset-old_offset);
	}

	return offset;
}
Example #16
0
/* Code to actually dissect the packets */
static int
dissect_mbtcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures needed to add the protocol subtree and manage it */
	mbtcp_hdr	mh;
	proto_item	*mi, *mf;
	proto_tree	*mbtcp_tree, *modbus_tree, *group_tree;
	int		offset, group_offset, packet_type;
	guint		i;
	gint		packet_len, payload_start, payload_len;
	const char	*func_string = "";
	const char	*pkt_type_str = "";
	const char	*err_str = "";
	guint32		byte_cnt, group_byte_cnt, group_word_cnt;
	guint32		packet_num;	/* num to uniquely identify different mbtcp
					 * packets in one packet */
	guint8		exception_code;
	gboolean	exception_returned;
	guint8		fc;

	mh.transaction_id = tvb_get_ntohs(tvb, 0);
	mh.protocol_id = tvb_get_ntohs(tvb, 2);
	mh.len = tvb_get_ntohs(tvb, 4);
	mh.mdbs_hdr.unit_id = tvb_get_guint8(tvb, 6);
	mh.mdbs_hdr.function_code = tvb_get_guint8(tvb, 7);


	/* check that it actually looks like Modbus/TCP */
	/* protocol id == 0 */
	if( mh.protocol_id != 0 ){
		return 0;
	}
	/* length is at least 2 (unit_id + function_code) */
	if( mh.len < 2 ){
		return 0;
	}
	/* function code is in the set 1-24, 40, 125-127.
	 * Note that function code is only 7 bits.
	 */
	fc=mh.mdbs_hdr.function_code&0x7f;
	if(!match_strval(fc, function_code_vals))
		return 0;


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

	col_clear(pinfo->cinfo, COL_INFO);


	/* Make entries in Info column on summary display */
	offset = 0;

	if ( mh.mdbs_hdr.function_code & 0x80 ) {
		exception_code = tvb_get_guint8(tvb, offset + sizeof(mbtcp_hdr));
		mh.mdbs_hdr.function_code ^= 0x80;
		exception_returned = TRUE;
	}
	else {
		exception_code = 0;
		exception_returned = FALSE;
	}
	func_string = val_to_str(mh.mdbs_hdr.function_code, function_code_vals,
	    "Unknown function (%u)");
	if (check_col(pinfo->cinfo, COL_INFO))
	{
		packet_type = classify_packet(pinfo);
		switch ( packet_type ) {
			case QUERY_PACKET : 		pkt_type_str="query";
												break;
			case RESPONSE_PACKET : 	pkt_type_str="response";
												break;
			case CANNOT_CLASSIFY :		err_str="Unable to classify as query or response.";
										pkt_type_str="unknown";
												break;
			default :
												break;
		}
		if ( exception_returned )
			err_str="Exception returned ";
		col_add_fstr(pinfo->cinfo, COL_INFO,
				"%8s [%2u pkt(s)]: trans: %5u; unit: %3u, func: %3u: %s. %s",
				pkt_type_str, 1, mh.transaction_id, (unsigned char) mh.mdbs_hdr.unit_id,
				(unsigned char) mh.mdbs_hdr.function_code, func_string, err_str);
	}

	/* build up protocol tree and iterate over multiple packets */
	packet_num = 0;
	while (1) {
		packet_type = classify_packet(pinfo);
		packet_len = sizeof(mbtcp_hdr) - sizeof(modbus_hdr) + mh.len;

		/* if a tree exists, perform operations to add fields to it */
		if (tree) {
			mi = proto_tree_add_protocol_format(tree, proto_mbtcp, tvb, offset,
					packet_len, "Modbus/TCP");
			mbtcp_tree = proto_item_add_subtree(mi, ett_mbtcp);

			/* Add items to protocol tree specific to Modbus/TCP */
			proto_tree_add_uint(mbtcp_tree, hf_mbtcp_transid, tvb, offset, 2,
					mh.transaction_id);
			proto_tree_add_uint(mbtcp_tree, hf_mbtcp_protid, tvb, offset + 2, 2,
					mh.protocol_id);
			proto_tree_add_uint(mbtcp_tree, hf_mbtcp_len, tvb, offset + 4, 2,
					mh.len);
					
			proto_tree_add_uint(mbtcp_tree, hf_mbtcp_unitid, tvb, offset + 6, 1,
					mh.mdbs_hdr.unit_id);


			/* Add items to protocol tree specific to Modbus generic */
			mf = proto_tree_add_text(mbtcp_tree, tvb, offset + 7, mh.len - 1,
					"Modbus");
	  		modbus_tree = proto_item_add_subtree(mf, ett_modbus_hdr);
			mi = proto_tree_add_uint(modbus_tree, hf_mbtcp_functioncode, tvb, offset + 7, 1,
					mh.mdbs_hdr.function_code);
					
			/** detail payload as a function of exception/function code */
			func_string = val_to_str(mh.mdbs_hdr.function_code,
			    function_code_vals, "Unknown function");
			payload_start = offset + 8;
			payload_len = mh.len - sizeof(modbus_hdr);
			if (exception_returned) {
				proto_item_set_text(mi, "function %u:  %s.  Exception: %s",
						mh.mdbs_hdr.function_code,
						func_string,
						val_to_str(exception_code,
						    exception_code_vals,
						    "Unknown exception code (%u)"));
				proto_tree_add_uint(modbus_tree, hf_modbus_exceptioncode, tvb, payload_start, 1,
						exception_code);
			}
			else {
				proto_item_set_text(mi, "function %u:  %s", mh.mdbs_hdr.function_code,
						func_string);
				switch (mh.mdbs_hdr.function_code) {
					
					case READ_COILS:			
					case READ_INPUT_DISCRETES:	
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE);
						}
						else if (packet_type == RESPONSE_PACKET) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data");
						}
						break;
						
					case READ_MULT_REGS:		
					case READ_INPUT_REGS:		
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
						}
						else if (packet_type == RESPONSE_PACKET) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data");
						}
						break;
						
					case WRITE_COIL:			
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 1, "Data");
							proto_tree_add_text(modbus_tree, tvb, payload_start + 3, 1, "Padding");
						}
						else if (packet_type == RESPONSE_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 1, "Data");
							proto_tree_add_text(modbus_tree, tvb, payload_start + 3, 1, "Padding");
						}
						break;
						
					case WRITE_SINGLE_REG:		
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 2, "Data");
						}
						else if (packet_type == RESPONSE_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 2, "Data");
						}
						break;
						
					case READ_EXCEPT_STAT:		
						if (packet_type == RESPONSE_PACKET)
							proto_tree_add_text(modbus_tree, tvb, payload_start, 1, "Data");
						break;
						
					case FORCE_MULT_COILS:		
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE);
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 4);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 4, 1,
									byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 5, byte_cnt, "Data");
						}
						else if (packet_type == RESPONSE_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE);
						}
						break;
						
					case WRITE_MULT_REGS:		
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 4);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 4, 1,
									byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 5, byte_cnt, "Data");
						}
						else if (packet_type == RESPONSE_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
						}
						break;
						
					case READ_GENL_REF:			
						if (packet_type == QUERY_PACKET) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
									byte_cnt);
									
							/* add subtrees to describe each group of packet */
							group_offset = payload_start + 1;
							for (i = 0; i < byte_cnt / 7; i++) {
								mi = proto_tree_add_text( modbus_tree, tvb, group_offset, 7,
										"Group %u", i);
						  		group_tree = proto_item_add_subtree(mi, ett_group_hdr);
								proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset, 1, FALSE);
								proto_tree_add_item(group_tree, hf_modbus_lreference, tvb, group_offset + 1, 4, FALSE);
								proto_tree_add_item(group_tree, hf_modbus_wordcnt, tvb, group_offset + 5, 2, FALSE);
								group_offset += 7;
							}
						}
						else if (packet_type == RESPONSE_PACKET) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
									byte_cnt);
									
							/* add subtrees to describe each group of packet */
							group_offset = payload_start + 1;
							i = 0;
							while (byte_cnt > 0) {
								group_byte_cnt = (guint32)tvb_get_guint8(tvb, group_offset);
								mi = proto_tree_add_text( modbus_tree, tvb, group_offset, group_byte_cnt + 1,
										"Group %u", i);
						  		group_tree = proto_item_add_subtree(mi, ett_group_hdr);
								proto_tree_add_uint(group_tree, hf_modbus_bytecnt, tvb, group_offset, 1,
										group_byte_cnt);
								proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset + 1, 1, FALSE);
								proto_tree_add_text(group_tree, tvb, group_offset + 2, group_byte_cnt - 1, "Data");
								group_offset += (group_byte_cnt + 1);
								byte_cnt -= (group_byte_cnt + 1);
								i++;
							}
						}
						break;
						
					case WRITE_GENL_REF:		
						if ((packet_type == QUERY_PACKET) || (packet_type == RESPONSE_PACKET)) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
									byte_cnt);
									
							/* add subtrees to describe each group of packet */
							group_offset = payload_start + 1;
							i = 0;
							while (byte_cnt > 0) {
								group_word_cnt = tvb_get_ntohs(tvb, group_offset + 5);
								group_byte_cnt = (2 * group_word_cnt) + 7;
								mi = proto_tree_add_text( modbus_tree, tvb, group_offset, 
										group_byte_cnt, "Group %u", i);
						  		group_tree = proto_item_add_subtree(mi, ett_group_hdr);
								proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset, 1, FALSE);
								proto_tree_add_item(group_tree, hf_modbus_lreference, tvb, group_offset + 1, 4, FALSE);
								proto_tree_add_uint(group_tree, hf_modbus_wordcnt, tvb, group_offset + 5, 2, 
										group_word_cnt);
								proto_tree_add_text(group_tree, tvb, group_offset + 7, group_byte_cnt - 7, "Data");
								group_offset += group_byte_cnt;
								byte_cnt -= group_byte_cnt;
								i++;
							}
						}
						break;
						
					case MASK_WRITE_REG:		
						if ((packet_type == QUERY_PACKET) || (packet_type == RESPONSE_PACKET)) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_andmask, tvb, payload_start + 2, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_ormask, tvb, payload_start + 4, 2, FALSE);
						}
						break;
						
					case READ_WRITE_REG:		
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_readref, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_readwordcnt, tvb, payload_start + 2, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_writeref, tvb, payload_start + 4, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_writewordcnt, tvb, payload_start + 6, 2, FALSE);
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 8);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 8, 1,
									byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 9, byte_cnt, "Data");
						}
						else if (packet_type == RESPONSE_PACKET) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
									byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data");
						}
						break;
						
					case READ_FIFO_QUEUE:		
						if (packet_type == QUERY_PACKET)
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
						else if (packet_type == RESPONSE_PACKET) {
							byte_cnt = (guint32)tvb_get_ntohs(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_lbytecnt, tvb, payload_start, 2,
									byte_cnt);
							proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 4, byte_cnt - 2, "Data");
						}
						break;
						
					case DIAGNOSTICS:			
					case PROGRAM_484:			
					case POLL_484:				
					case GET_COMM_EVENT_CTRS:	
					case GET_COMM_EVENT_LOG:	
					case PROGRAM_584_984:		
					case POLL_584_984:			
					case REPORT_SLAVE_ID:		
					case PROGRAM_884_U84:		
					case RESET_COMM_LINK:		
					case PROGRAM_CONCEPT:		
					case FIRMWARE_REPLACE:		
					case PROGRAM_584_984_2:		
					case REPORT_LOCAL_ADDR_MB:	
						/* these function codes are not part of the Modbus/TCP specification */
					default:					
						if (payload_len > 0)
							proto_tree_add_text(modbus_tree, tvb, payload_start, payload_len, "Data");
						break;
				}
			}
		}
		
		/* move onto next packet (if there) */
		offset += packet_len;
		packet_num++;
		if (tvb_reported_length_remaining(tvb, offset) > 0) {
			
			/* load header structure for next packet */
			mh.transaction_id = tvb_get_ntohs(tvb, offset+0);
			mh.protocol_id = tvb_get_ntohs(tvb, offset+2);
			mh.len = tvb_get_ntohs(tvb, offset+4);
			mh.mdbs_hdr.unit_id = tvb_get_guint8(tvb, offset+6);
			mh.mdbs_hdr.function_code = tvb_get_guint8(tvb, offset+7);

	
			if ( mh.mdbs_hdr.function_code & 0x80 ) {
				exception_code = tvb_get_guint8(tvb, offset + sizeof(mbtcp_hdr));
				mh.mdbs_hdr.function_code ^= 0x80;
				exception_returned = TRUE;
			} else
				exception_returned = FALSE;
		}
		else
			break;
	}

	return tvb_length(tvb);
}