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

    unsigned char  b0;

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

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

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

#define SZINFO_SIZE 256
    szInfo=(char *)wmem_alloc(wmem_packet_scope(), SZINFO_SIZE);

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

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

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

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

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

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

    case ABORT:
        cbHeader = 4;
        break;

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

    case ACK:
        cbHeader = 3;
        break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    proto_tree_add_text(wtp_tree, tvb, dataOffset, -1, "Payload");
                }
            } else {
                /* Not reassembled yet, or not reassembled at all */
                col_append_fstr(pinfo->cinfo, COL_INFO,
                                "%s (Unreassembled fragment %u)",
                                szInfo, psn);
                proto_tree_add_text(wtp_tree, tvb, dataOffset, -1, "Payload");
            }
            /* Now reset fragmentation information in pinfo */
            pinfo->fragmented = save_fragmented;
        }
        else if ( ((pdut == INVOKE) || (pdut == RESULT)) && (fTTR) )
        {
            /* Non-fragmented payload */
            wsp_tvb = tvb_new_subset_remaining(tvb, dataOffset);
            /* We can safely hand the tvb to the WSP dissector */
            call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
        }
        else
        {
            /* Nothing to hand to subdissector */
            col_append_str(pinfo->cinfo, COL_INFO, szInfo);
        }
    }
    else
    {
        /* Nothing to hand to subdissector */
        col_append_str(pinfo->cinfo, COL_INFO, szInfo);
    }
}
Example #2
0
static int
dissect_dtpt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*dtpt_tree = NULL;
	proto_item	*dtpt_item = NULL;
	guint8		version;
	guint8		message_type;
	guint32		flags;
	guint32		payload_size;

	version = tvb_get_guint8(tvb, 0);
	if (version != 1) return 0;
	message_type = tvb_get_guint8(tvb, 1);
	switch (message_type) {
		case LookupBeginRequest:
		case LookupBeginResponse:
		case LookupNextRequest:
		case LookupNextResponse:
		case LookupEndRequest:
			if (tvb_reported_length(tvb) != 20) return 0;
		break;
		case ConnectRequest:
		case ConnectResponseOK:
		case ConnectResponseERR:
			if (tvb_reported_length(tvb) != 36) return 0;
		break;
		default:
			return 0;
	}

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "DTPT");
	if (check_col(pinfo->cinfo, COL_INFO))
		col_add_str(pinfo->cinfo, COL_INFO, val_to_str(message_type, names_message_type, "Unknown (%d)"));

	if (message_type == LookupBeginRequest) {
		conversation_t *c;
		c = find_or_create_conversation(pinfo);
		conversation_set_dissector(c, dtpt_conversation_handle);
	}

	if (tree) {
		dtpt_item = proto_tree_add_item(tree, proto_dtpt,
				tvb, 0, -1, ENC_NA);
		if (dtpt_item)
			dtpt_tree = proto_item_add_subtree(dtpt_item, ett_dtpt);
	}

	if (dtpt_tree) {
		proto_tree_add_uint(dtpt_tree, hf_dtpt_version,
			tvb, 0, 1, version);
		proto_tree_add_uint(dtpt_tree, hf_dtpt_message_type,
			tvb, 1, 1, message_type);

		switch (message_type) {
			case LookupBeginRequest: {
				proto_item* flags_item = NULL;
				proto_tree*	flags_tree = NULL;

				flags = tvb_get_letohl(tvb, 12);

				flags_item = proto_tree_add_uint(dtpt_tree, hf_dtpt_flags,
					tvb, 12, 4, flags);
				if (flags_item) {
					flags_tree = proto_item_add_subtree(flags_item, ett_dtpt_flags);
				}
				if (flags_tree) {
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_res_service,   tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_flushprevious, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_flushcache,    tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_query_string, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_aliases, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_blob, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_addr, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_comment, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_version, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_type, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_name, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_nearest, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_nocontainers, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_containers, tvb, 12, 4, flags);
					proto_tree_add_boolean(flags_tree, hf_dtpt_flags_deep, tvb, 12, 4, flags);
				}
				payload_size = tvb_get_letohl(tvb, 16);
				proto_tree_add_uint(dtpt_tree, hf_dtpt_payload_size,
					tvb, 16, 4, payload_size);
			}
			break;
			case LookupBeginResponse: {
				proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle,
					tvb, 4, 8, tvb_get_letoh64(tvb, 4));
				proto_tree_add_uint(dtpt_tree, hf_dtpt_error,
					tvb, 12, 4, tvb_get_letohl(tvb, 12));
			}
			break;
			case LookupNextRequest: {
				proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle,
					tvb, 4, 8, tvb_get_letoh64(tvb, 4));
				proto_tree_add_uint(dtpt_tree, hf_dtpt_buffer_size,
					tvb, 16, 4, tvb_get_letohl(tvb, 16));
			}
			break;
			case LookupNextResponse: {
				proto_tree_add_uint(dtpt_tree, hf_dtpt_error,
					tvb, 12, 4, tvb_get_letohl(tvb, 12));
				proto_tree_add_uint(dtpt_tree, hf_dtpt_data_size,
					tvb, 16, 4, tvb_get_letohl(tvb, 16));
			}
			break;
			case LookupEndRequest: {
				proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle,
					tvb, 4, 8, tvb_get_letoh64(tvb, 4));
			}
			break;
			case ConnectRequest: {
				dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT);
				proto_tree_add_uint(dtpt_tree, hf_dtpt_error,
					tvb, 32, 4, tvb_get_letohl(tvb, 32));
			}
			break;
			case ConnectResponseOK: {
				dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT);
				proto_tree_add_uint(dtpt_tree, hf_dtpt_error,
					tvb, 32, 4, tvb_get_letohl(tvb, 32));
			}
			break;
			case ConnectResponseERR: {
				dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT);
				proto_tree_add_uint(dtpt_tree, hf_dtpt_error,
					tvb, 32, 4, tvb_get_letohl(tvb, 32));
			}
			break;
		}
	}

	return tvb_length(tvb);
}
Example #3
0
/* WiMax MAC Management DCD message (table 15) dissector */
void dissect_mac_mgmt_msg_dcd_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint offset = 0;
	guint tvb_len, payload_type, length;
	gint  tlv_type, tlv_len, tlv_offset, tlv_value_offset;
	guint dl_burst_diuc, dl_num_regions;
	proto_item *dcd_item = NULL;
	proto_tree *dcd_tree = NULL;
	proto_tree *tlv_tree = NULL;
	proto_tree *sub_tree = NULL;
	tlv_info_t tlv_info;

	/* Ensure the right payload type */
	payload_type = tvb_get_guint8(tvb, offset);
	if(payload_type != MAC_MGMT_MSG_DCD)
	{
		return;
	}

	if(tree)
	{	/* we are being asked for details */
		/* Get the tvb reported length */
		tvb_len =  tvb_reported_length(tvb);
		/* display MAC payload type DCD */
		dcd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tvb_len, "Downlink Channel Descriptor (DCD) (%u bytes)", tvb_len);
		/* add MAC DCD subtree */
		dcd_tree = proto_item_add_subtree(dcd_item, ett_mac_mgmt_msg_dcd_decoder);
		/* Decode and display the Downlink Channel Descriptor (DCD) */
		/* display the Message Type */
		proto_tree_add_item(dcd_tree, hf_dcd_message_type, tvb, offset, 1, ENC_BIG_ENDIAN);
		/* set the offset for the Downlink Channel ID */
		offset++;
		/* display the Downlink Channel ID */
		proto_tree_add_item(dcd_tree, hf_dcd_downlink_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN);
		/* set the offset for the Configuration Change Count */
		offset++;
		/* display the Configuration Change Count */
		proto_tree_add_item(dcd_tree, hf_dcd_config_change_count, tvb, offset, 1, ENC_BIG_ENDIAN);
		/* set the offset for the TLV Encoded info */
		offset++;
		/* process the DCD TLV Encoded information (table 358) */
		while(offset < tvb_len)
		{
			/* get the TLV information */
			init_tlv_info(&tlv_info, tvb, offset);
			/* get the TLV type */
			tlv_type = get_tlv_type(&tlv_info);
			/* get the TLV length */
			tlv_len = get_tlv_length(&tlv_info);
			if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1)
			{	/* invalid tlv info */
				col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DCD TLV error");
				proto_tree_add_item(dcd_tree, hf_dcd_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA);
				break;
			}
			/* get the TLV value offset */
			tlv_value_offset = get_tlv_value_offset(&tlv_info);
#ifdef DEBUG /* for debug only */
			proto_tree_add_protocol_format(dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, (tlv_len + tlv_value_offset), "DCD Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len, offset, tvb_len);
#endif
			/* update the offset */
			offset += tlv_value_offset;
			/* process DCD TLVs */
			switch (tlv_type)
			{
				case DCD_DOWNLINK_BURST_PROFILE:
				{	/* Downlink Burst Profile TLV (table 363)*/
					/* get the DIUC */
					dl_burst_diuc = (tvb_get_guint8(tvb, offset) & 0x0F);
					/* display TLV info */
					/* add TLV subtree */
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "Downlink_Burst_Profile (DIUC=%u) (%u bytes)", (dl_burst_diuc+1), tlv_len);
					/* detail display */
					proto_tree_add_item(tlv_tree, hf_dcd_dl_burst_profile_rsv, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_dcd_dl_burst_profile_diuc, tvb, offset, 1, ENC_BIG_ENDIAN);
					/* process subTLVs */
					for (tlv_offset = 1; tlv_offset < tlv_len;  )
					{	/* get the TLV information */
						init_tlv_info(&tlv_info, tvb, (offset+tlv_offset));
						/* get the TLV type */
						tlv_type = get_tlv_type(&tlv_info);
						/* get the TLV length */
						length = get_tlv_length(&tlv_info);
						if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1)
						{	/* invalid tlv info */
							col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DL Burst Profile TLV error");
							proto_tree_add_item(tlv_tree, hf_dcd_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA);
							break;
						}
						/* update the offset */
						tlv_offset += get_tlv_value_offset(&tlv_info);
						switch (tlv_type)
						{
							case DCD_BURST_FREQUENCY:
							{
								proto_item *tlv_item = NULL;

								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_burst_freq, tvb, (offset+tlv_offset), 1, FALSE);
								tlv_item = proto_tree_add_item(sub_tree, hf_dcd_burst_freq, tvb, (offset+tlv_offset), 1, ENC_BIG_ENDIAN);
								proto_item_append_text(tlv_item, " kHz");
								break;
							}
							case DCD_BURST_FEC_CODE_TYPE:
							{
								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_burst_fec, tvb, (offset+tlv_offset), 1, FALSE);
								proto_tree_add_item(sub_tree, hf_dcd_burst_fec, tvb, (offset+tlv_offset), 1, ENC_BIG_ENDIAN);
								break;
							}
							case DCD_BURST_DIUC_EXIT_THRESHOLD:
							{
								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_burst_diuc_exit_threshold, tvb, (offset+tlv_offset), length, FALSE);
								proto_tree_add_item(sub_tree, hf_dcd_burst_diuc_exit_threshold, tvb, (offset+tlv_offset), length, ENC_BIG_ENDIAN);
								break;
							}
							case DCD_BURST_DIUC_ENTRY_THRESHOLD:
							{
								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_burst_diuc_entry_threshold, tvb, (offset+tlv_offset), length, FALSE);
								proto_tree_add_item(sub_tree, hf_dcd_burst_diuc_entry_threshold, tvb, (offset+tlv_offset), length, ENC_BIG_ENDIAN);
								break;
							}
							case DCD_BURST_TCS_ENABLE:
							{
								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_burst_tcs, tvb, (offset+tlv_offset), length, FALSE);
								proto_tree_add_item(sub_tree, hf_dcd_burst_tcs, tvb, (offset+tlv_offset), 1, ENC_BIG_ENDIAN);
								break;
							}
							default:
								/* ??? */
								break;
						}
						tlv_offset += length;
					}
					break;
				}
				case DCD_BS_EIRP:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_bs_eirp, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_bs_eirp, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " dBm");
					break;
				}
				case DCD_FRAME_DURATION:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_frame_duration, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_frame_duration, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_PHY_TYPE:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_phy_type, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_phy_type, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_POWER_ADJUSTMENT:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_power_adjustment, tvb, offset, 1, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_power_adjustment, tvb, offset, 1, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_CHANNEL_NR:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_channel_nr, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_channel_nr, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TTG:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_ttg, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_ttg, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " PS");
					break;
				}
				case DCD_RTG:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_rtg, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_rtg, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " PS");
					break;
				}
#ifdef WIMAX_16D_2004
				case DCD_RSS:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_rss, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_rss, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " dBm");
					break;
				}
#else
				case DCD_EIRXP:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_eirxp, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_eirxp, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " dBm");
					break;
				}
#endif
				case DCD_CHANNEL_SWITCH_FRAME_NR:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_channel_switch_frame_nr, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_channel_switch_frame_nr, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_FREQUENCY:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_frequency, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_frequency, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " kHz");
					break;
				}
				case DCD_BS_ID:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_bs_id, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_bs_id, tvb, offset, tlv_len, ENC_NA);
					break;
				}
				case DCD_FRAME_DURATION_CODE:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_frame_duration_code, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_frame_duration_code, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_FRAME_NR:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_frame_nr, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_frame_nr, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
#ifdef WIMAX_16D_2004
				case DCD_SIZE_CQICH_ID:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_size_cqich_id, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_size_cqich_id, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
#endif
				case DCD_H_ARQ_ACK_DELAY:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_h_arq_ack_delay, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_h_arq_ack_delay, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " frame offset");
					break;
				}
				case DCD_MAC_VERSION:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_mac_version, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_mac_version, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TLV_T_19_PERMUTATION_TYPE_FOR_BROADCAST_REGION_IN_HARQ_ZONE:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_19_permutation_type_for_broadcast_regions_in_harq_zone, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_19_permutation_type_for_broadcast_regions_in_harq_zone, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TLV_T_20_MAXIMUM_RETRANSMISSION:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_20_maximum_retransmission, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_20_maximum_retransmission, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TLV_T_21_DEFAULT_RSSI_AND_CINR_AVERAGING_PARAMETER:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, 1, "Default RSSI and CINR averaging parameter (%u byte(s))", tlv_len);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter_physical_cinr_measurements, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter_rssi_measurements, tvb, offset, 1, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TLV_T_22_DL_AMC_ALLOCATED_PHYSICAL_BANDS_BITMAP:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_22_dl_amc_allocated_physical_bands_bitmap, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_22_dl_amc_allocated_physical_bands_bitmap, tvb, offset, tlv_len, ENC_NA);
					break;
				}
				case DCD_TLV_T_34_DL_REGION_DEFINITION:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "DL region definition (%u byte(s))", tlv_len);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition, tvb, offset, tlv_len, ENC_NA);
					dl_num_regions = tvb_get_guint8(tvb, offset);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_num_region, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
					tlv_offset = offset;
					for(length = 0; length < dl_num_regions; length++)
					{
						proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_symbol_offset, tvb, tlv_offset, 1, ENC_BIG_ENDIAN);
						proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_subchannel_offset, tvb, (tlv_offset+1), 1, ENC_BIG_ENDIAN);
						proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_num_symbols, tvb, (tlv_offset+2), 1, ENC_BIG_ENDIAN);
						proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_num_subchannels, tvb, (tlv_offset+3), 1, ENC_BIG_ENDIAN);
						tlv_offset += 4;
					}
					break;
				}
				case DCD_TLV_T_50_HO_TYPE_SUPPORT:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "HO type support (%u byte(s))", tlv_len);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_ho, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_mdho, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_fbss_ho, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TLV_T_31_H_ADD_THRESHOLD:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_31_h_add_threshold, tvb, offset, 1, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_31_h_add_threshold, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " dB");
					break;
				}
				case DCD_TLV_T_32_H_DELETE_THRESHOLD:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_32_h_delete_threshold, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_32_h_delete_threshold, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " dB");
					break;
				}
				case DCD_TLV_T_33_ASR:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "ASR Slot Length (M) and Switching Period (L) (%u byte(s))", tlv_len);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_33_asr, tvb, offset, 1, ENC_BIG_ENDIAN);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_33_asr_m, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " frames");
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_33_asr_l, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " frames");
					break;
				}
				case DCD_TLV_T_35_PAGING_GROUP_ID:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_35_paging_group_id, tvb, offset, 1, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_35_paging_group_id, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TLV_T_36_TUSC1_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_36_tusc1_permutation_active_subchannels_bitmap, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_36_tusc1_permutation_active_subchannels_bitmap, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TLV_T_37_TUSC2_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_37_tusc2_permutation_active_subchannels_bitmap, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_37_tusc2_permutation_active_subchannels_bitmap, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TLV_T_51_HYSTERSIS_MARGIN:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_51_hysteresis_margin, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_51_hysteresis_margin, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " dB");
					break;
				}
				case DCD_TLV_T_52_TIME_TO_TRIGGER_DURATION:
				{
					proto_item *tlv_item = NULL;

					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_52_time_to_trigger_duration, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_52_time_to_trigger_duration, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item, " ms");
					break;
				}
				case DCD_TLV_T_54_TRIGGER:
				{	/* Trigger TLV (table 358a & 358b) */
					/* add TLV subtree */
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "DCD Trigger (%u bytes)", tlv_len);
					for (tlv_offset = 0; tlv_offset < tlv_len;  )
					{
						/* get the TLV information */
						init_tlv_info(&tlv_info, tvb, (offset + tlv_offset));
						/* get the TLV type */
						tlv_type = get_tlv_type(&tlv_info);
						/* get the TLV length */
						length = get_tlv_length(&tlv_info);
						if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1)
						{	/* invalid tlv info */
							col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Trigger TLV error");
							proto_tree_add_item(tlv_tree, hf_dcd_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA);
							break;
						}
						/* update the offset */
						tlv_offset += get_tlv_value_offset(&tlv_info);
						/* table 358a */
						switch (tlv_type)
						{
							case DCD_TLV_T_541_TYPE_FUNCTION_ACTION:
							{	/* table 358b */
								sub_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, (offset + tlv_offset), length, "Trigger; Type/function/action description (%u byte(s))", tlv_len);
								proto_tree_add_item(sub_tree, hf_dcd_tlv_t_541_type, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN);
								proto_tree_add_item(sub_tree, hf_dcd_tlv_t_541_function, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN);
								proto_tree_add_item(sub_tree, hf_dcd_tlv_t_541_action, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN);
							}
							break;
							case DCD_TLV_T542_TRIGGER_VALUE:
								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_tlv_t_542_trigger_value, tvb, (offset + tlv_offset), length, FALSE);
								proto_tree_add_item(sub_tree, hf_dcd_tlv_t_542_trigger_value, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN);
							break;
							case DCD_TLV_T_543_TRIGGER_AVERAGING_DURATION:
								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_tlv_t_543_trigger_averaging_duration, tvb, (offset + tlv_offset), length, FALSE);
								proto_tree_add_item(sub_tree, hf_dcd_tlv_t_543_trigger_averaging_duration, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN);
							break;
						}
						tlv_offset += length;
					}
					break;
				}
				case DCD_TLV_T_60_NOISE_AND_INTERFERENCE:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_60_noise_interference, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_60_noise_interference, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TLV_T_153_DOWNLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_153_downlink_burst_profile_for_mutiple_fec_types, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_153_downlink_burst_profile_for_mutiple_fec_types, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_RESTART_COUNT:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_restart_count, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_restart_count, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					break;
				}
				case DCD_TLV_T_45_PAGING_INTERVAL_LENGTH:
				{
					if (include_cor2_changes) {
						tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "Reserved (%u byte(s))", tlv_len);
						proto_tree_add_text(tlv_tree, tvb, offset, tlv_len,  "Reserved");
					} else {
						tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_45_paging_interval_length, tvb, offset, tlv_len, FALSE);
						proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_45_paging_interval_length, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
					}
					break;
				}
				default:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_unknown_type, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_dcd_unknown_type, tvb, offset, tlv_len, ENC_NA);
					break;
				}
			}
			offset += tlv_len;
		}	/* end of TLV process while loop */
	}
}
Example #4
0
/* XXX - "packet comment" is passed into dissector as data, but currently doesn't have a use */
static int
dissect_file_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
{
	proto_item  *volatile ti = NULL;
	guint	     cap_len = 0, frame_len = 0;
	proto_tree  *volatile fh_tree = NULL;
	proto_tree  *volatile tree;
	proto_item  *item;
	const gchar *cap_plurality, *frame_plurality;
	const color_filter_t *color_filter;
	file_data_t *file_data = (file_data_t*)data;

	tree=parent_tree;

	pinfo->current_proto = "File";

	/* if FILE is not referenced from any filters we don't need to worry about
	   generating any tree items.  */
	if(!proto_field_is_referenced(tree, proto_file)) {
		tree=NULL;
	} else {
		gboolean old_visible;

		/* Put in frame header information. */
		cap_len = tvb_captured_length(tvb);
		frame_len = tvb_reported_length(tvb);

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

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

		fh_tree = proto_item_add_subtree(ti, ett_file);

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

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

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

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

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

		if(proto_field_is_referenced(tree, hf_file_protocols)) {
			/* we are going to be using proto_item_append_string() on
			 * hf_frame_protocols, and we must therefore disable the
			 * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by
			 * setting it as visible.
			 *
			 * See proto.h for details.
			 */
			old_visible = proto_tree_set_visible(fh_tree, TRUE);
			ti = proto_tree_add_string(fh_tree, hf_file_protocols, tvb, 0, 0, "");
			PROTO_ITEM_SET_GENERATED(ti);
			proto_tree_set_visible(fh_tree, old_visible);
		}

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

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

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

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

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

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

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

	/* XXX optimize this so it doesn't need to scan the second time */
	color_filter = color_filters_colorize_packet(file_data->color_edt);

	if (color_filter) {
		pinfo->fd->color_filter = color_filter;
		item = proto_tree_add_string(fh_tree, hf_file_color_filter_name, tvb,
					     0, 0, color_filter->filter_name);
		PROTO_ITEM_SET_GENERATED(item);
		item = proto_tree_add_string(fh_tree, hf_file_color_filter_text, tvb,
					     0, 0, color_filter->filter_text);
		PROTO_ITEM_SET_GENERATED(item);
	}

	tap_queue_packet(file_tap, pinfo, NULL);


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

	return tvb_captured_length(tvb);
}
Example #5
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_set_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 #6
0
/* Code to actually dissect the packets */
static void
dissect_brdwlk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

/* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti, *hidden_item;
    proto_tree *brdwlk_tree = NULL;
    tvbuff_t *next_tvb;
    guint8 error, eof, sof;
    int hdrlen = 2,
        offset = 0;
    gint len, reported_len, plen;
    guint16 pkt_cnt;
    gboolean dropped_packets;

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

    col_clear(pinfo->cinfo, COL_INFO);

    pinfo->vsan = (tvb_get_ntohs(tvb, offset) & 0xFFF);
    sof = (tvb_get_guint8(tvb, offset) & 0xF0) >> 4;

    if ((sof == FCM_DELIM_SOFI3) || (sof == FCM_DELIM_SOFI2) || (sof == FCM_DELIM_SOFI1)
        || (sof == FCM_DELIM_SOFI4)) {
        pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
    }
    else if (sof == FCM_DELIM_SOFF) {
        pinfo->sof_eof = PINFO_SOF_SOFF;
    }

    if (tree) {
        ti = proto_tree_add_protocol_format(tree, proto_brdwlk, tvb, 0,
                                            hdrlen, "Boardwalk");

        brdwlk_tree = proto_item_add_subtree(ti, ett_brdwlk);

        proto_tree_add_item(brdwlk_tree, hf_brdwlk_sof, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(brdwlk_tree, hf_brdwlk_vsan, tvb, offset, 2, ENC_BIG_ENDIAN);

    }

    /* Locate EOF which is the last 4 bytes of the frame */
    len = tvb_length_remaining(tvb, hdrlen);
    reported_len = tvb_reported_length_remaining(tvb, hdrlen);
    if (reported_len < 4) {
        /*
         * This packet is claimed not to even have enough data for
         * a 4-byte EOF.
         * Don't try to process the EOF.
         */
        ;
    }
    else if (len < reported_len) {
        /*
         * This packet is claimed to have enough data for a 4-byte EOF,
         * but we didn't capture all of the packet.
         * Slice off the 4-byte EOF from the reported length, and trim
         * the captured length so it's no more than the reported length;
         * that will slice off what of the EOF, if any, is in the
         * captured length.
         */
        reported_len -= 4;
        if (len > reported_len)
            len = reported_len;
    }
    else {
        /*
         * We have the entire packet, and it includes a 4-byte EOF.
         * Slice it off, and put it into the tree if we're building
         * a tree.
         */
        len -= 4;
        reported_len -= 4;
        offset = tvb_reported_length(tvb) - 4;
        pkt_cnt = tvb_get_ntohs(tvb, offset);
        if (tree) {
            proto_tree_add_uint(brdwlk_tree, hf_brdwlk_pktcnt, tvb, offset,
                                2, pkt_cnt);
        }
        dropped_packets = FALSE;
        if (pinfo->fd->flags.visited) {
            /*
             * This isn't the first pass, so we can't use the global
             * "packet_count" variable to determine whether there were
             * any dropped frames or not.
             * We therefore attach a non-null pointer as frame data to
             * any frame preceded by dropped packets.
             */
            if (p_get_proto_data(pinfo->fd, proto_brdwlk, 0) != NULL)
                dropped_packets = TRUE;
        } else {
            /*
             * This is the first pass, so we have to use the global
             * "packet_count" variable to determine whether there were
             * any dropped frames or not.
             *
             * XXX - can there be more than one stream of packets, so that
             * we can't just use a global variable?
             */
            if (pkt_cnt != packet_count + 1) {
                if (!first_pkt &&
                    (pkt_cnt != 0 || (packet_count != BRDWLK_MAX_PACKET_CNT))) {
                    dropped_packets = TRUE;

                    /*
                     * Mark this frame as having been preceded by dropped
                     * packets.  (The data we use as the frame data doesn't
                     * matter - it just matters that it's non-null.)
                     */
                    p_add_proto_data(pinfo->fd, proto_brdwlk, 0, &packet_count);
                }
            }
        }
        if (tree) {
            hidden_item = proto_tree_add_boolean(brdwlk_tree, hf_brdwlk_drop,
                                                     tvb, offset, 0, dropped_packets);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
        }

        packet_count = pkt_cnt;

        error=tvb_get_guint8(tvb, offset+2);
        dissect_brdwlk_err(brdwlk_tree, tvb, offset+2);

        eof = tvb_get_guint8(tvb, offset+3);
        if (eof != FCM_DELIM_EOFN) {
            pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
        }
        else if (eof != FCM_DELIM_EOFT) {
            pinfo->sof_eof |= PINFO_EOF_INVALID;
        }

        if (tree) {
            proto_tree_add_item(brdwlk_tree, hf_brdwlk_eof, tvb, offset+3,
                                1, ENC_BIG_ENDIAN);
        }

        if ((error & BRDWLK_HAS_PLEN) && tree) {
            /* In newer Boardwalks, if this bit is set, the actual frame length
             * is also provided. This length is the size between SOF & EOF
             * including FC CRC.
             */
            plen = tvb_get_ntohl(tvb, offset-4);
            plen *= 4;
            proto_tree_add_uint(brdwlk_tree, hf_brdwlk_plen, tvb, offset-4,
                                4, plen);

#if 0
            /* XXX - this would throw an exception if it would increase
             * the reported length.
             */
            if (error & BRDWLK_TRUNCATED_BIT) {
                tvb_set_reported_length(tvb, plen);
            }
#endif
        }
    }

    next_tvb = tvb_new_subset(tvb, 2, len, reported_len);
    if (fc_dissector_handle) {
        call_dissector(fc_dissector_handle, next_tvb, pinfo, tree);
    }
}
Example #7
0
dissect_prp_redundancy_control_trailer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
{
    proto_item *ti;
    proto_tree *prp_tree;
    guint       i;
    guint       length;
    guint       offset;
    guint16     lan_id;
    guint16     lsdu_size;
    guint16     prp1_suffix;
    guint       trailer_start;
    guint       trailer_length;

    trailer_start = 0;
    trailer_length = 0;
    length = tvb_reported_length(tvb);

    if(length < 14)
        return 0;

    /*
     * This is horribly broken.  It assumes the frame is an Ethernet
     * frame, with a type field at an offset of 12 bytes from the header.
     * That is not guaranteed to be true.
     *
     * Ideally, this should be a heuristic dissector registered in
     * the "eth.trailer" heuristic dissector table (and it can
     * be registered as "disabled by default" there); unfortunately,
     * it needs to know the length of the entire frame for the
     * PRP-0 heuristic, so it'd have to be passed that length
     * out of band.
/* Code to actually dissect the packets */
static void
dissect_manolito(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	unsigned int offset;

	/* Set up structures needed to add the protocol subtree and manage it */
	proto_item *ti;
	proto_tree *manolito_tree;
	const char* packet_type = 0;

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

	ti = proto_tree_add_item(tree, proto_manolito, tvb, 0, -1, ENC_NA);

	manolito_tree = proto_item_add_subtree(ti, ett_manolito);

	/* MANOLITO packet header (network byte order) */
	proto_tree_add_item(manolito_tree,
	    hf_manolito_checksum, tvb, 0, 4, ENC_BIG_ENDIAN);
	proto_tree_add_item(manolito_tree,
	    hf_manolito_seqno, tvb, 4, 4, ENC_BIG_ENDIAN);

	proto_tree_add_item(manolito_tree,
	    hf_manolito_src, tvb, 8, 4, ENC_BIG_ENDIAN);

	proto_tree_add_item(manolito_tree,
	    hf_manolito_dest, tvb, 12, 4, ENC_BIG_ENDIAN);

	if (tvb_reported_length(tvb) == 19) {
		packet_type = "Ping (truncated)";
		proto_tree_add_item(manolito_tree,
		    hf_manolito_options_short, tvb, 16, 3, ENC_BIG_ENDIAN);
	} else {
		proto_tree_add_item(manolito_tree,
		    hf_manolito_options, tvb, 16, 4, ENC_BIG_ENDIAN);
	}

	if (tvb_reported_length(tvb) <= 20)      /* no payload, just headers */
	{
		col_set_str(pinfo->cinfo, COL_INFO, "Ping");
	} else {
		offset = 20;            /* fields start here */

	 	/* fields format: 2-byte name, optional NULL, 1-byte lenlen, */
		/* that many bytes(len or data), for NI,CN,VL is len, more */
		/* (that many bytes) data follows; else is raw data. */
		do
		{
			guint16 field_name;      /* 16-bit field name */
			guint8 dtype;            /* data-type */
			guint8 length;           /* length */
			guint8* data;            /* payload */
			int start;               /* field starting location */
			char field_name_str[3];  /* printable name */
			const char* longname;    /* human-friendly field name */

			start = offset;

			/* 2-byte field name */
			field_name = tvb_get_ntohs(tvb, offset);
			offset += 2;

			/* Identify the packet based on existing fields */
			/* Maybe using the options fields is a better idea...*/
			if (field_name == 0x434b)    /* CK */
				packet_type = "Search Hit";
			if (field_name == 0x4e43)    /* NC */
				packet_type = "User Information";
			if (field_name == 0x464e)    /* FN - if only field */
				packet_type = "Search Query";
			if (field_name == 0x4944)    /* ID ?? search by CK? */
				packet_type = "Search Query (by hash)";
			if (field_name == 0x5054)    /* PT */
				packet_type = "Download Request";
			if (field_name == 0x4d45)    /* ME */
				packet_type = "Chat";

			if (tvb_reported_length(tvb) == 20)   /* no fields */
				packet_type = "Ping";

			/* Find the long name of the field */
			switch(field_name)
			{
			case 0x5346: longname = "Shared Files"; break;    /* SF */
			case 0x534b: longname = "Shared Kilobytes";break; /* SK */
			case 0x4e49: longname = "Network ID"; break;      /* NI */
			case 0x4e43: longname = "Num. Connections";break; /* NC */
			case 0x4356: longname = "Client Version"; break;  /* CV */
			case 0x564c: longname = "Velocity"; break;        /* VL */
			case 0x464e: longname = "Filename"; break;        /* FN */
			case 0x464c: longname = "File Length"; break;     /* FL */
			case 0x4252: longname = "Bit Rate"; break;        /* BR */
			case 0x4643: longname = "Frequency"; break;       /* FC */
			case 0x5354: longname = "???"; break;             /* ST */
			case 0x534c: longname = "Song Length (s)"; break; /* SL */
			case 0x434b: longname = "Checksum"; break;    /* CK */
			case 0x4e4e: longname = "Nickname"; break;        /* NN */
			case 0x434e: longname = "Client Name"; break;     /* CN */
			case 0x5054: longname = "Port"; break;            /* PT */
			case 0x484e: longname = "???"; break;             /* HN */
			case 0x4d45: longname = "Message"; break;         /* ME */
			case 0x4944: longname = "Identification"; break;  /* ID */
			case 0x4144: longname = "???"; break;             /* AD */
			default: longname = "unknown"; break;
			}

			/* 1-byte data type */
#define MANOLITO_STRING		1
#define MANOLITO_INTEGER	0
			dtype = tvb_get_guint8(tvb, offset);
			length = tvb_get_guint8(tvb, ++offset);

			/*
			 * Get the payload.
			 *
			 * XXX - is the cast necessary?  I think the
			 * "usual arithmetic conversions" should
			 * widen it past 8 bits, so there shouldn't
			 * be an overflow.
			 */
			data = ep_alloc((guint)length + 1);
			tvb_memcpy(tvb, data, ++offset, length);
			offset += length;

			/* convert the 16-bit integer field name to a string */
                        /* XXX: changed this to use g_htons */
			field_name_str[0] = g_htons(field_name) & 0x00ff;
			field_name_str[1] = (g_htons(field_name) & 0xff00) >> 8;
			field_name_str[2] = 0;

			if (dtype == MANOLITO_STRING)
			{
				data[length] = 0;
				proto_tree_add_text(manolito_tree, tvb, start,
					offset - start, "%s (%s): %s",
					(char*)field_name_str, longname, data);
			} else if (dtype == MANOLITO_INTEGER) {
			 	int n = 0;

				/* integers can be up to 5 bytes */
				switch(length)
				{
				case 5: n += data[4] << ((length - 5) * 8);
				case 4: n += data[3] << ((length - 4) * 8);
				case 3: n += data[2] << ((length - 3) * 8);
				case 2: n += data[1] << ((length - 2) * 8);
				case 1: n += data[0] << ((length - 1) * 8);
				}
				proto_tree_add_text(manolito_tree, tvb, start,
					offset - start, "%s (%s): %d",
					(char*)field_name_str, longname, n);
			} else {
				proto_tree_add_text(manolito_tree, tvb, start,
					offset - start, "unknown type %d", dtype);
			}

		} while(offset < tvb_reported_length(tvb));

	}

	if (packet_type)
	{
		col_set_str(pinfo->cinfo, COL_INFO, packet_type);
	}
}
Example #9
0
static void dissect_kdp(tvbuff_t *tvb,
                        packet_info *pinfo,
                        proto_tree *tree) {
  guint body_len;
  guint8 version = 0;
  guint8 header_len = 0;
  guint8 packet_flags = 0;
  guint8 packet_errors = 0;
  guint32 sequence_number = G_MAXUINT32;
  guint32 ack_number = G_MAXUINT32;
  guint32 src_flowid = G_MAXUINT32;
  int offset;

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "KDP");
  col_clear(pinfo->cinfo, COL_INFO);
  if (tree) {
    proto_item *ti;
    proto_tree *kdp_tree, *flags_tree;
    ti = NULL;
    kdp_tree = NULL;
    flags_tree = NULL;

    ti = proto_tree_add_item(tree, proto_kdp, tvb, 0, -1, ENC_NA);
    kdp_tree = proto_item_add_subtree(ti, ett_kdp);

    version = tvb_get_guint8(tvb, 0);
    if (version != 2) {
      /* Version other than 2 is really SDDP in UDP */
      proto_tree_add_item(kdp_tree, hf_kdp_version, tvb, 0, 1, ENC_BIG_ENDIAN);
      proto_tree_add_item(kdp_tree, hf_kdp_xml_body, tvb, 0, -1, ENC_ASCII|ENC_NA);
    } else {
      header_len = tvb_get_guint8(tvb, 1) * 4;
      body_len = tvb_reported_length(tvb);
      if (header_len > body_len) {
        body_len = 0;           /* malformed packet */
      } else {
        body_len = body_len - header_len;
      }
      packet_flags = tvb_get_guint8(tvb, 2);
      packet_errors = tvb_get_guint8(tvb, 3);
      proto_tree_add_item(kdp_tree, hf_kdp_version, tvb, 0, 1, ENC_BIG_ENDIAN);
      proto_tree_add_item(kdp_tree, hf_kdp_headerlen, tvb, 1, 1, ENC_BIG_ENDIAN);
      ti = proto_tree_add_item(kdp_tree, hf_kdp_flags, tvb, 2, 1, ENC_BIG_ENDIAN);
      flags_tree = proto_item_add_subtree(ti, ett_kdp_flags);

      proto_tree_add_item(flags_tree, hf_kdp_drop_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
      proto_tree_add_item(flags_tree, hf_kdp_syn_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
      proto_tree_add_item(flags_tree, hf_kdp_ack_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
      proto_tree_add_item(flags_tree, hf_kdp_rst_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
      proto_tree_add_item(flags_tree, hf_kdp_bcst_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
      proto_tree_add_item(flags_tree, hf_kdp_dup_flag, tvb, 2, 1, ENC_BIG_ENDIAN);

      proto_tree_add_item(kdp_tree, hf_kdp_errors, tvb, 3, 1, ENC_BIG_ENDIAN);

      if (header_len > 4) {
        offset = 4;
        if (packet_flags & KDP_ACK_FLAG) {
          proto_tree_add_item(kdp_tree, hf_kdp_destflowid, tvb, offset, 4, ENC_BIG_ENDIAN);
          offset = offset + 4;
        }

        if (packet_flags & (KDP_SYN_FLAG | KDP_BCST_FLAG)) {
          proto_tree_add_item(kdp_tree, hf_kdp_srcflowid, tvb, offset, 4, ENC_BIG_ENDIAN);
          src_flowid = tvb_get_ntohl(tvb, offset);
          offset = offset + 4;
        }

        proto_tree_add_item(kdp_tree, hf_kdp_sequence, tvb, offset, 4, ENC_BIG_ENDIAN);
        sequence_number = tvb_get_ntohl(tvb, offset);
        offset = offset + 4;

        if (packet_flags & KDP_ACK_FLAG) {
          proto_tree_add_item(kdp_tree, hf_kdp_ack, tvb, offset, 4, ENC_BIG_ENDIAN);
          ack_number = tvb_get_ntohl(tvb, offset);
          offset = offset + 4;
        }
        if (packet_flags & KDP_SYN_FLAG) {
          proto_tree_add_item(kdp_tree, hf_kdp_maxsegmentsize, tvb, offset, 4, ENC_BIG_ENDIAN);
          offset = offset + 4;
        }

        while (offset < ((body_len > 0) ? header_len - 4 : header_len)) {
          guint8 option_number;
          guint8 option_len = 0;

          option_number = tvb_get_guint8(tvb, offset);

          proto_tree_add_item(kdp_tree, hf_kdp_optionnumber, tvb, offset, 1, ENC_BIG_ENDIAN);
          offset = offset + 1;
          if (option_number > 0) {
            option_len = tvb_get_guint8(tvb, offset);
            proto_tree_add_item(kdp_tree, hf_kdp_optionlen, tvb, offset, 1, ENC_BIG_ENDIAN);
            offset = offset + 1;
          }

          switch (option_number) {
          case 0:
            break;
          case 1:
            proto_tree_add_item(kdp_tree, hf_kdp_option1, tvb, offset, 2, ENC_BIG_ENDIAN);
            offset = offset + 2;
            break;
          case 2:
            proto_tree_add_item(kdp_tree, hf_kdp_option2, tvb, offset, 2, ENC_BIG_ENDIAN);
            offset = offset + 2;
            break;
          case 3:
            proto_tree_add_item(kdp_tree, hf_kdp_option3, tvb, offset, 2, ENC_BIG_ENDIAN);
            offset = offset + 2;
            break;
          case 4:
            proto_tree_add_item(kdp_tree, hf_kdp_option4, tvb, offset, 0, ENC_NA);
            break;
          case 5:
            proto_tree_add_item(kdp_tree, hf_kdp_option5, tvb, offset, 0, ENC_NA);
            break;
          case 6:
            proto_tree_add_item(kdp_tree, hf_kdp_option6, tvb, offset, option_len - 2, ENC_NA);
            offset = offset + option_len - 2;
            break;
          case 7:
            proto_tree_add_item(kdp_tree, hf_kdp_option7, tvb, offset, 2, ENC_BIG_ENDIAN);
            offset = offset + 2;
            break;
          case 8:
            proto_tree_add_item(kdp_tree, hf_kdp_option8, tvb, offset, 2, ENC_BIG_ENDIAN);
            offset = offset + 2;
            break;
          case 9:
            proto_tree_add_item(kdp_tree, hf_kdp_option9, tvb, offset, 2, ENC_BIG_ENDIAN);
            offset = offset + 2;
            break;
          default:
            proto_tree_add_item(kdp_tree, hf_kdp_option_unknown, tvb, offset, option_len - 2, ENC_NA);
            offset = offset + option_len - 2;
            break;
          }
        }

        if (body_len > 0) {
          proto_tree_add_item(kdp_tree, hf_kdp_fragment, tvb, offset, 2, ENC_BIG_ENDIAN);
          offset = offset + 2;

          proto_tree_add_item(kdp_tree, hf_kdp_fragtotal, tvb, offset, 2, ENC_BIG_ENDIAN);
          offset = offset + 2;

          proto_tree_add_item(kdp_tree, hf_kdp_body, tvb, offset, -1, ENC_NA);
        }
      }
    }
  }
  /* Now that we know sequence number and optional ack number, we can
     print more detailed summary info */
  if (version != 2) {
      col_set_str(pinfo->cinfo, COL_INFO, "SDDP message");
  } else {
      char ack_string[BUFFER_SIZE];
      char seq_num_string[BUFFER_SIZE];
      char src_flowid_string[BUFFER_SIZE];

      if (packet_flags & KDP_ACK_FLAG) {
        g_snprintf(ack_string, sizeof(ack_string), "ACK=%x ", ack_number);
      } else {
        ack_string[0] = '\0';
      }
      if (header_len > 4) {
        g_snprintf(seq_num_string, sizeof(seq_num_string), "SEQ=%x ", sequence_number);
      } else {
        seq_num_string[0] = '\0';
      }
      if (packet_flags & (KDP_SYN_FLAG | KDP_BCST_FLAG)) {
        g_snprintf(src_flowid_string, sizeof(src_flowid_string), "SRC_FLOWID=%x ", src_flowid);
      } else {
        src_flowid_string[0] = '\0';
      }
      col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s%s%s%s%s%serrors=%d",
                   ((packet_flags & KDP_DROP_FLAG) ? "DROP " : ""),
                   ((packet_flags & KDP_SYN_FLAG) ? "SYN " : ""),
                   ((packet_flags & KDP_RST_FLAG) ? "RST " : ""),
                   ((packet_flags & KDP_BCST_FLAG) ? "BCST " : ""),
                   ((packet_flags & KDP_DUP_FLAG) ? "DUP " : ""),
                   ack_string,
                   seq_num_string,
                   src_flowid_string,
                   packet_errors);
  }
}
Example #10
0
/* Tests a tvbuff against the expected pattern/length.
 * Returns TRUE if all tests succeeed, FALSE if any test fails */
gboolean
test(tvbuff_t *tvb, gchar* name,
     guint8* expected_data, guint expected_length, guint expected_reported_length)
{
	guint			length;
	guint			reported_length;
	guint8			*ptr;
	volatile gboolean	ex_thrown;
	volatile guint32	val32;
	guint32			expected32;
	guint			incr, i;

	length = tvb_length(tvb);

	if (length != expected_length) {
		printf("01: Failed TVB=%s Length of tvb=%u while expected length=%u\n",
				name, length, expected_length);
		failed = TRUE;
		return FALSE;
	}

	reported_length = tvb_reported_length(tvb);

	if (reported_length != expected_reported_length) {
		printf("01: Failed TVB=%s Reported length of tvb=%u while expected reported length=%u\n",
				name, reported_length, expected_reported_length);
		failed = TRUE;
		return FALSE;
	}

	/* Test boundary case. A BoundsError exception should be thrown. */
	ex_thrown = FALSE;
	TRY {
		tvb_get_ptr(tvb, 0, length + 1);
	}
	CATCH(BoundsError) {
		ex_thrown = TRUE;
	}
	CATCH(FragmentBoundsError) {
		printf("02: Caught wrong exception: FragmentBoundsError\n");
	}
	CATCH(ReportedBoundsError) {
		printf("02: Caught wrong exception: ReportedBoundsError\n");
	}
	CATCH_ALL {
		printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n");
	}
	ENDTRY;

	if (!ex_thrown) {
		printf("02: Failed TVB=%s No BoundsError when retrieving %u bytes\n",
				name, length + 1);
		failed = TRUE;
		return FALSE;
	}

	/* Test boundary case with reported_length+1. A ReportedBoundsError
	   exception should be thrown. */
	ex_thrown = FALSE;
	TRY {
		tvb_get_ptr(tvb, 0, reported_length + 1);
	}
	CATCH(BoundsError) {
		printf("03: Caught wrong exception: BoundsError\n");
	}
	CATCH(FragmentBoundsError) {
		printf("03: Caught wrong exception: FragmentBoundsError\n");
	}
	CATCH(ReportedBoundsError) {
		ex_thrown = TRUE;
	}
	CATCH_ALL {
		printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n");
	}
	ENDTRY;

	if (!ex_thrown) {
		printf("03: Failed TVB=%s No ReportedBoundsError when retrieving %u bytes\n",
				name, reported_length + 1);
		failed = TRUE;
		return FALSE;
	}

	/* Test boundary case. A BoundsError exception should be thrown. */
	ex_thrown = FALSE;
	TRY {
		tvb_get_ptr(tvb, -1, 2);
	}
	CATCH(BoundsError) {
		ex_thrown = TRUE;
	}
	CATCH(FragmentBoundsError) {
		printf("04: Caught wrong exception: FragmentBoundsError\n");
	}
	CATCH(ReportedBoundsError) {
		printf("04: Caught wrong exception: ReportedBoundsError\n");
	}
	CATCH_ALL {
		printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n");
	}
	ENDTRY;

	if (!ex_thrown) {
		printf("04: Failed TVB=%s No BoundsError when retrieving 2 bytes from"
				" offset -1\n", name);
		failed = TRUE;
		return FALSE;
	}

	/* Test boundary case. A BoundsError exception should not be thrown. */
	ex_thrown = FALSE;
	TRY {
		tvb_get_ptr(tvb, 0, 1);
	}
	CATCH(BoundsError) {
		ex_thrown = TRUE;
	}
	CATCH(FragmentBoundsError) {
		printf("05: Caught wrong exception: FragmentBoundsError\n");
	}
	CATCH(ReportedBoundsError) {
		printf("05: Caught wrong exception: ReportedBoundsError\n");
	}
	CATCH_ALL {
		printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n");
	}
	ENDTRY;

	if (ex_thrown) {
		printf("05: Failed TVB=%s BoundsError when retrieving 1 bytes from"
				" offset 0\n", name);
		failed = TRUE;
		return FALSE;
	}

	/* Test boundary case. A BoundsError exception should not be thrown. */
	ex_thrown = FALSE;
	TRY {
		tvb_get_ptr(tvb, -1, 1);
	}
	CATCH(BoundsError) {
		ex_thrown = TRUE;
	}
	CATCH(FragmentBoundsError) {
		printf("06: Caught wrong exception: FragmentBoundsError\n");
	}
	CATCH(ReportedBoundsError) {
		printf("06: Caught wrong exception: ReportedBoundsError\n");
	}
	CATCH_ALL {
		printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n");
	}
	ENDTRY;

	if (ex_thrown) {
		printf("06: Failed TVB=%s BoundsError when retrieving 1 bytes from"
				" offset -1\n", name);
		failed = TRUE;
		return FALSE;
	}


	/* Check data at boundary. An exception should not be thrown. */
	if (length >= 4) {
		ex_thrown = FALSE;
		TRY {
			val32 = tvb_get_ntohl(tvb, 0);
		}
		CATCH_ALL {
			ex_thrown = TRUE;
		}
		ENDTRY;

		if (ex_thrown) {
			printf("07: Failed TVB=%s Exception when retrieving "
					"guint32 from offset 0\n", name);
			failed = TRUE;
			return FALSE;
		}

		expected32 = pntohl(expected_data);
		if (val32 != expected32) {
			printf("08: Failed TVB=%s  guint32 @ 0 %u != expected %u\n",
					name, val32, expected32);
			failed = TRUE;
			return FALSE;
		}
	}
Example #11
0
        return 10;
    else if ( (flagsValue & esl_port11_bitmask) != 0 )
        return 11;

    return -1;
}

/*esl*/
static void
dissect_esl_header(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree) {

    proto_item *ti = NULL;
    proto_tree *esl_header_tree;
    gint offset = 0;

    guint esl_length = tvb_reported_length(tvb);
    if ( esl_length >= SIZEOF_ESLHEADER )
    {
        if (tree)
        {
            guint16 flags;

            ti = proto_tree_add_item(tree, proto_esl, tvb, 0, SIZEOF_ESLHEADER, TRUE);
            esl_header_tree = proto_item_add_subtree(ti, ett_esl);
            offset+=6;

            flags =  tvb_get_letohs(tvb, offset);
            proto_tree_add_uint(esl_header_tree, hf_esl_port, tvb, offset, 2, flags_to_port(flags));

            proto_tree_add_item(esl_header_tree, hf_esl_crcerror, tvb, offset, 2, TRUE);
            proto_tree_add_item(esl_header_tree, hf_esl_alignerror, tvb, offset, 2, TRUE);
static void
dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
	proto_item  *volatile ti = NULL, *comment_item;
	guint	     cap_len = 0, frame_len = 0;
	proto_tree  *volatile tree;
	proto_tree  *comments_tree;
	proto_item  *item;
	const gchar *cap_plurality, *frame_plurality;

	tree=parent_tree;

	switch (pinfo->phdr->rec_type) {

	case REC_TYPE_PACKET:
		pinfo->current_proto = "Frame";
		if (pinfo->pseudo_header != NULL) {
			switch (pinfo->fd->lnk_t) {

			case WTAP_ENCAP_WFLEET_HDLC:
			case WTAP_ENCAP_CHDLC_WITH_PHDR:
			case WTAP_ENCAP_PPP_WITH_PHDR:
			case WTAP_ENCAP_SDLC:
			case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR:
				pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				break;

			case WTAP_ENCAP_BLUETOOTH_HCI:
				pinfo->p2p_dir = pinfo->pseudo_header->bthci.sent;
				break;

			case WTAP_ENCAP_LAPB:
			case WTAP_ENCAP_FRELAY_WITH_PHDR:
				pinfo->p2p_dir =
				    (pinfo->pseudo_header->x25.flags & FROM_DCE) ?
				    P2P_DIR_RECV : P2P_DIR_SENT;
				break;

			case WTAP_ENCAP_ISDN:
			case WTAP_ENCAP_V5_EF:
			case WTAP_ENCAP_DPNSS:
			case WTAP_ENCAP_BACNET_MS_TP_WITH_PHDR:
				pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				break;

			case WTAP_ENCAP_LINUX_LAPD:
				pinfo->p2p_dir = (pinfo->pseudo_header->lapd.pkttype == 3 ||
					pinfo->pseudo_header->lapd.pkttype == 4) ?
					P2P_DIR_SENT : P2P_DIR_RECV;
				break;

			case WTAP_ENCAP_MTP2_WITH_PHDR:
				pinfo->p2p_dir = pinfo->pseudo_header->mtp2.sent ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				pinfo->link_number  = pinfo->pseudo_header->mtp2.link_number;
				pinfo->annex_a_used = pinfo->pseudo_header->mtp2.annex_a_used;
				break;

			case WTAP_ENCAP_GSM_UM:
				pinfo->p2p_dir = pinfo->pseudo_header->gsm_um.uplink ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				break;
			}
		}
		break;

	case REC_TYPE_FT_SPECIFIC_EVENT:
		pinfo->current_proto = "Event";
		break;

	case REC_TYPE_FT_SPECIFIC_REPORT:
		pinfo->current_proto = "Report";
		break;

	default:
		g_assert_not_reached();
		break;
	}

	if(pinfo->pkt_comment){
		item = proto_tree_add_item(tree, proto_pkt_comment, tvb, 0, 0, ENC_NA);
		comments_tree = proto_item_add_subtree(item, ett_comments);
		comment_item = proto_tree_add_string_format(comments_tree, hf_comments_text, tvb, 0, 0,
							                   pinfo->pkt_comment, "%s",
							                   pinfo->pkt_comment);
		expert_add_info_format(pinfo, comment_item, &ei_comments_text,
					                       "%s",  pinfo->pkt_comment);


	}

	/* if FRAME is not referenced from any filters we don't need to worry about
	   generating any tree items.  */
	if(!proto_field_is_referenced(tree, proto_frame)) {
		tree=NULL;
		if(pinfo->fd->flags.has_ts) {
			if(pinfo->fd->abs_ts.nsecs < 0 || pinfo->fd->abs_ts.nsecs >= 1000000000)
				expert_add_info(pinfo, NULL, &ei_arrive_time_out_of_range);
		}
	} else {
		proto_tree *fh_tree;
		gboolean old_visible;

		/* Put in frame header information. */
		cap_len = tvb_length(tvb);
		frame_len = tvb_reported_length(tvb);

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

		ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_captured_length(tvb),
		    "Frame %u: %u byte%s on wire",
		    pinfo->fd->num, frame_len, frame_plurality);
		if (generate_bits_field)
			proto_item_append_text(ti, " (%u bits)", frame_len * 8);
		proto_item_append_text(ti, ", %u byte%s captured",
		    cap_len, cap_plurality);
		if (generate_bits_field) {
			proto_item_append_text(ti, " (%u bits)",
			    cap_len * 8);
		}
		if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) {
			proto_item_append_text(ti, " on interface %u",
			    pinfo->phdr->interface_id);
		}
		if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
			if (pinfo->phdr->pack_flags & 0x00000001) {
				proto_item_append_text(ti, " (inbound)");
				pinfo->p2p_dir = P2P_DIR_RECV;
			}
			if (pinfo->phdr->pack_flags & 0x00000002) {
				proto_item_append_text(ti, " (outbound)");
				pinfo->p2p_dir = P2P_DIR_SENT;
			}
		}

		fh_tree = proto_item_add_subtree(ti, ett_frame);

		if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID && proto_field_is_referenced(tree, hf_frame_interface_id)) {
			const char *interface_name = epan_get_interface_name(pinfo->epan, pinfo->phdr->interface_id);

			if (interface_name)
				proto_tree_add_uint_format_value(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id, "%u (%s)", pinfo->phdr->interface_id, interface_name);
			else
				proto_tree_add_uint(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id);
		}

		if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
			proto_tree *flags_tree;
			proto_item *flags_item;

			flags_item = proto_tree_add_uint(fh_tree, hf_frame_pack_flags, tvb, 0, 0, pinfo->phdr->pack_flags);
			flags_tree = proto_item_add_subtree(flags_item, ett_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_direction, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_reception_type, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_fcs_length, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_reserved, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_crc_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_long_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_short_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_inter_frame_gap_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_unaligned_frame_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_start_frame_delimiter_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_preamble_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_symbol_error, tvb, 0, 0, pinfo->phdr->pack_flags);
		}

		if (pinfo->phdr->rec_type == REC_TYPE_PACKET)
			proto_tree_add_int(fh_tree, hf_frame_wtap_encap, tvb, 0, 0, pinfo->fd->lnk_t);

		if (pinfo->fd->flags.has_ts) {
			proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb,
					    0, 0, &(pinfo->fd->abs_ts));
			if(pinfo->fd->abs_ts.nsecs < 0 || pinfo->fd->abs_ts.nsecs >= 1000000000) {
				expert_add_info_format(pinfo, ti, &ei_arrive_time_out_of_range,
								  "Arrival Time: Fractional second %09ld is invalid,"
								  " the valid range is 0-1000000000",
								  (long) pinfo->fd->abs_ts.nsecs);
			}
			item = proto_tree_add_time(fh_tree, hf_frame_shift_offset, tvb,
					    0, 0, &(pinfo->fd->shift_offset));
			PROTO_ITEM_SET_GENERATED(item);

			if(generate_epoch_time) {
				proto_tree_add_time(fh_tree, hf_frame_arrival_time_epoch, tvb,
						    0, 0, &(pinfo->fd->abs_ts));
			}

			if (proto_field_is_referenced(tree, hf_frame_time_delta)) {
				nstime_t     del_cap_ts;

				frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->fd->num - 1, &del_cap_ts);

				item = proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb,
							   0, 0, &(del_cap_ts));
				PROTO_ITEM_SET_GENERATED(item);
			}

			if (proto_field_is_referenced(tree, hf_frame_time_delta_displayed)) {
				nstime_t del_dis_ts;

				frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->fd->prev_dis_num, &del_dis_ts);

				item = proto_tree_add_time(fh_tree, hf_frame_time_delta_displayed, tvb,
							   0, 0, &(del_dis_ts));
				PROTO_ITEM_SET_GENERATED(item);
			}

			item = proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb,
						   0, 0, &(pinfo->rel_ts));
			PROTO_ITEM_SET_GENERATED(item);

			if(pinfo->fd->flags.ref_time){
				ti = proto_tree_add_item(fh_tree, hf_frame_time_reference, tvb, 0, 0, ENC_NA);
				PROTO_ITEM_SET_GENERATED(ti);
			}
		}

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

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

		proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb,
					   0, 0, cap_len, "Capture Length: %u byte%s (%u bits)",
					   cap_len, cap_plurality, cap_len * 8);

		if (generate_md5_hash) {
			const guint8 *cp;
			md5_state_t   md_ctx;
			md5_byte_t    digest[16];
			const gchar  *digest_string;

			cp = tvb_get_ptr(tvb, 0, cap_len);

			md5_init(&md_ctx);
			md5_append(&md_ctx, cp, cap_len);
			md5_finish(&md_ctx, digest);

			digest_string = bytestring_to_str(wmem_packet_scope(), digest, 16, '\0');
			ti = proto_tree_add_string(fh_tree, hf_frame_md5_hash, tvb, 0, 0, digest_string);
			PROTO_ITEM_SET_GENERATED(ti);
		}

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

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

		if(proto_field_is_referenced(tree, hf_frame_protocols)) {
			/* we are going to be using proto_item_append_string() on
			 * hf_frame_protocols, and we must therefore disable the
			 * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by
			 * setting it as visible.
			 *
			 * See proto.h for details.
			 */
			old_visible = proto_tree_set_visible(fh_tree, TRUE);
			ti = proto_tree_add_string(fh_tree, hf_frame_protocols, tvb, 0, 0, "");
			PROTO_ITEM_SET_GENERATED(ti);
			proto_tree_set_visible(fh_tree, old_visible);
		}

		/* Check for existences of P2P pseudo header */
		if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) {
			proto_tree_add_int(fh_tree, hf_frame_p2p_dir, tvb,
					   0, 0, pinfo->p2p_dir);
		}

		/* Check for existences of MTP2 link number */
		if ((pinfo->pseudo_header != NULL ) && (pinfo->fd->lnk_t == WTAP_ENCAP_MTP2_WITH_PHDR)) {
			proto_tree_add_uint(fh_tree, hf_link_number, tvb,
					    0, 0, pinfo->link_number);
		}

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

		if(pinfo->fd->color_filter != NULL) {
			const color_filter_t *color_filter = (const color_filter_t *)pinfo->fd->color_filter;
			item = proto_tree_add_string(fh_tree, hf_frame_color_filter_name, tvb,
						     0, 0, color_filter->filter_name);
			PROTO_ITEM_SET_GENERATED(item);
			item = proto_tree_add_string(fh_tree, hf_frame_color_filter_text, tvb,
						     0, 0, color_filter->filter_text);
			PROTO_ITEM_SET_GENERATED(item);
		}
	}

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

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

			case REC_TYPE_PACKET:
				if ((force_docsis_encap) && (docsis_handle)) {
					call_dissector(docsis_handle, tvb, pinfo, parent_tree);
				} else {
					if (!dissector_try_uint(wtap_encap_dissector_table, pinfo->fd->lnk_t,
								tvb, pinfo, parent_tree)) {

						col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
						col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %d",
							     pinfo->fd->lnk_t);
						call_dissector(data_handle,tvb, pinfo, parent_tree);
					}
				}
				break;

			case REC_TYPE_FT_SPECIFIC_EVENT:
			case REC_TYPE_FT_SPECIFIC_REPORT:
				if (!dissector_try_uint(wtap_fts_rec_dissector_table, pinfo->file_type_subtype,
							tvb, pinfo, parent_tree)) {

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

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

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

	tap_queue_packet(frame_tap, pinfo, NULL);


	if (pinfo->frame_end_routines) {
		g_slist_foreach(pinfo->frame_end_routines, &call_frame_end_routine, NULL);
		g_slist_free(pinfo->frame_end_routines);
		pinfo->frame_end_routines = NULL;
	}
}
static int
dissect_mpls_y1711(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    struct mplsinfo *mplsinfo;
    int              offset          = 0;
    proto_item      *ti;
    proto_tree      *mpls_y1711_tree;
    int              functype;
    tvbuff_t        *data_tvb;

    static const guint8 allone[]  = { 0xff, 0xff };
    static const guint8 allzero[] = { 0x00, 0x00, 0x00, 0x00, 0x00,
                                      0x00, 0x00, 0x00, 0x00, 0x00,
                                      0x00, 0x00, 0x00, 0x00, 0x00,
                                      0x00, 0x00, 0x00, 0x00, 0x00 };

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

    functype = tvb_get_guint8(tvb, offset);
    col_append_fstr(pinfo->cinfo, COL_INFO, " (Y.1711: %s)",
                    (functype == 0x01) ? "CV" :
                    (functype == 0x02) ? "FDI" :
                    (functype == 0x03) ? "BDI" :
                    (functype == 0x07) ? "FDD" :
                    "reserved/unknown");

    /* sanity checks */
    if (tvb_reported_length(tvb) < 44) {
        /*
         * ITU-T Y.1711, 5.3: PDUs must have a minimum payload length of
         * 44 bytes
         */
        proto_tree_add_expert(tree, pinfo, &ei_mpls_y1711_minimum_payload, tvb, offset, -1);
        data_tvb = tvb_new_subset_remaining(tvb, offset);
        call_dissector(data_handle, data_tvb, pinfo, tree);

        return tvb_reported_length(tvb);
    }

    ti = proto_tree_add_text(tree, tvb, offset, 44, "Y.1711 OAM");
    mpls_y1711_tree = proto_item_add_subtree(ti, ett_mpls_y1711);

    /* checks for exp, bos and ttl encoding */
    if (mplsinfo->label != MPLS_LABEL_OAM_ALERT)
        proto_tree_add_expert_format(mpls_y1711_tree, pinfo, &ei_mpls_y1711_no_OAM_alert_label, tvb, offset - 4, 3,
                                     "Warning: Y.1711 but no OAM alert label (%d) ?!", MPLS_LABEL_OAM_ALERT);

    if (mplsinfo->exp != 0)
        proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_exp_bits_not_zero, tvb, offset - 2, 1);

    if (mplsinfo->bos != 1)
        proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_s_bit_not_one, tvb, offset - 2, 1);

    if (mplsinfo->ttl != 1)
        proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_ttl_not_one, tvb, offset - 1, 1);

    /* starting dissection */
    functype = tvb_get_guint8(tvb, offset);
    proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_function_type, tvb,
                        offset, 1,
                        ENC_LITTLE_ENDIAN);
    offset++;

    switch (functype) {
    case 0x01: /* CV */
    {
        /* 3 octets reserved (all 0x00) */
        if (tvb_memeql(tvb, offset, allzero, 3) == -1) {
            proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_reserved_not_zero, tvb, offset, 3);
        }
        offset += 3;

        /* ttsi (ipv4 flavor as in RFC 2373) */
        if (tvb_memeql(tvb, offset, allzero, 10) == -1) {
            proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 10);
        }
        offset += 10;

        if (tvb_memeql(tvb, offset, allone, 2) == -1) {
            proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_ff, tvb, offset, 2);
        }
        offset += 2;

        proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsr_id, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        /* 18 octets of padding (all 0x00) */
        if (tvb_memeql(tvb, offset, allzero, 18) == -1) {
            proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 18);
        }
        offset += 18;
    }
    break;

    case 0x02: /* FDI */
    case 0x03: /* BDI */
    {
        /* 1 octets reserved (all 0x00) */
        if (tvb_memeql(tvb, offset, allzero, 1) == -1) {
            proto_tree_add_expert_format(mpls_y1711_tree, pinfo, &ei_mpls_y1711_reserved_not_zero, tvb, offset, 3,
                                         "Error: this byte is reserved and must be 0x00");
        }
        offset++;

        proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_defect_type, tvb,
                            offset, 2,
                            ENC_LITTLE_ENDIAN);
        offset += 2;

        /*
         * ttsi (ipv4 flavor as in RFC 2373) is optional if not used must
         * be set to all 0x00
         */
        if (tvb_memeql(tvb, offset, allzero, 20) == 0) {
            proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_ttsi_not_preset, tvb, offset, 20);
            offset += 20;
        } else {
            if (tvb_memeql(tvb, offset, allzero, 10) == -1) {
                proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 10);
            }
            offset += 10;

            if (tvb_memeql(tvb, offset, allone, 2) == -1) {
                proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_ff, tvb, offset, 2);
            }
            offset += 2;

            proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsr_id, tvb, offset, 4, ENC_BIG_ENDIAN);
            offset += 4;

            proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
            offset += 4;
        }

        /* defect location */
        proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_defect_location, tvb,
                            offset, 4,
                            ENC_LITTLE_ENDIAN);
        offset += 4;

        /* 14 octets of padding (all 0x00) */
        if (tvb_memeql(tvb, offset, allzero, 14) == -1) {
            proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 14);
        }
        offset += 14;
    }
    break;

    case 0x07: /* FDD */
    {
        /* 3 octets reserved (all 0x00) */
        if (tvb_memeql(tvb, offset, allzero, 3) == -1) {
            proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_reserved_not_zero, tvb, offset, 3);
        }
        offset += 3;

        /* ttsi (ipv4 flavor as in RFC 2373) */
        if (tvb_memeql(tvb, offset, allzero, 10) == -1) {
            proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 10);
        }
        offset += 10;

        if (tvb_memeql(tvb, offset, allone, 2) == -1) {
            proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_ff, tvb, offset, 2);
        }
        offset += 2;

        proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsr_id, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_frequency, tvb,
                            offset, 1,
                            ENC_LITTLE_ENDIAN);
        offset++;

        /* 17 octets of padding (all 0x00) */
        if (tvb_memeql(tvb, offset, allzero, 17) == -1) {
            proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 17);
        }
        offset += 17;
    }
    break;

    default:
        proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_unknown_pdu, tvb, offset - 1, -1);
        return offset;
    }

    /* BIP16 */
    proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_bip16, tvb, offset, 2,
                        ENC_LITTLE_ENDIAN);
    offset += 2;

    return offset;
}
Example #14
0
static int
dissect_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

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

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

	offset = 0;

	bvlc_type =  tvb_get_guint8(tvb, offset);

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

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

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

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

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

	}
/* Ok, no routing information BVLC packet. Dissect as
 * BACnet NPDU
 */
	npdu_length = packet_length - bvlc_length;
	next_tvb = tvb_new_subset(tvb,bvlc_length,-1,npdu_length);
	/* Code from Guy Harris */
	if (!dissector_try_uint(bvlc_dissector_table,
	    bvlc_function, next_tvb, pinfo, tree)) {
		/* Unknown function - dissect the paylod as data */
		call_dissector(data_handle,next_tvb, pinfo, tree);
	}
	return tvb_reported_length(tvb);
}
Example #15
0
static void
dissect_smb_direct(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
		   enum SMB_DIRECT_HDR_TYPE hdr_type)

{
	proto_tree *tree = NULL;
	proto_item *item = NULL;
	proto_tree *neg_req_tree = NULL;
	proto_tree *neg_rep_tree = NULL;
	proto_tree *data_tree = NULL;
	int offset = 0;
	guint32 status = 0;
	guint32 remaining_length = 0;
	guint32 data_offset = 0;
	guint32 data_length = 0;
	guint rlen = tvb_reported_length(tvb);
	gint len = 0;
	tvbuff_t *next_tvb = NULL;
	static const int * flags[] = {
		&hf_smb_direct_flags_response_requested,
		NULL
	};

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

	if (parent_tree != NULL) {
		item = proto_tree_add_item(parent_tree, proto_smb_direct, tvb, 0, -1, ENC_NA);
		tree = proto_item_add_subtree(item, ett_smb_direct);
	}

	switch (hdr_type) {
	case SMB_DIRECT_HDR_UNKNOWN:
		break;

	case SMB_DIRECT_HDR_NEG_REQ:
		col_append_str(pinfo->cinfo, COL_INFO, "NegotiateRequest");

		if (tree == NULL) {
			break;
		}

		item = proto_tree_add_item(tree, hf_smb_direct_negotiate_request, tvb, 0, -1, ENC_NA);
		neg_req_tree = proto_item_add_subtree(item, ett_smb_direct_hdr);

		proto_tree_add_item(neg_req_tree, hf_smb_direct_min_version,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_req_tree, hf_smb_direct_max_version,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		/* 2 bytes reserved */
		offset += 2;

		proto_tree_add_item(neg_req_tree, hf_smb_direct_credits_requested,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_req_tree, hf_smb_direct_preferred_send_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_req_tree, hf_smb_direct_max_receive_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_req_tree, hf_smb_direct_max_fragmented_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		/* offset += 4; */
		break;

	case SMB_DIRECT_HDR_NEG_REP:
		col_append_str(pinfo->cinfo, COL_INFO, "NegotiateResponse");

		status = tvb_get_letohl(tvb, 12);
		if (status != 0) {
			col_append_fstr(
				pinfo->cinfo, COL_INFO, ", Error: %s",
				val_to_str(status, NT_errors, "Unknown (0x%08X)"));
		}

		if (tree == NULL) {
			break;
		}

		item = proto_tree_add_item(tree, hf_smb_direct_negotiate_response, tvb, 0, -1, ENC_NA);
		neg_rep_tree = proto_item_add_subtree(item, ett_smb_direct_hdr);

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_min_version,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_version,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_negotiated_version,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		/* 2 bytes reserved */
		offset += 2;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_credits_requested,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_credits_granted,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_status,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_read_write_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_preferred_send_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_receive_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_fragmented_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		/* offset += 4; */
		break;

	case SMB_DIRECT_HDR_DATA:
		col_append_str(pinfo->cinfo, COL_INFO, "DataMessage");

		if (tree == NULL) {
			break;
		}

		rlen = MIN(rlen, 24);

		item = proto_tree_add_item(tree, hf_smb_direct_data_message, tvb, 0, rlen, ENC_NA);
		data_tree = proto_item_add_subtree(item, ett_smb_direct_hdr);

		proto_tree_add_item(data_tree, hf_smb_direct_credits_requested,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(data_tree, hf_smb_direct_credits_granted,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_bitmask(tree, tvb, offset, hf_smb_direct_flags,
			       ett_smb_direct_flags, flags, ENC_LITTLE_ENDIAN);
		offset += 2;

		/* 2 bytes reserved */
		offset += 2;

		remaining_length = tvb_get_letohl(tvb, offset);
		proto_tree_add_item(data_tree, hf_smb_direct_remaining_length,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		data_offset = tvb_get_letohl(tvb, offset);
		proto_tree_add_item(data_tree, hf_smb_direct_data_offset,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		data_length = tvb_get_letohl(tvb, offset);
		proto_tree_add_item(data_tree, hf_smb_direct_data_length,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		if (data_length > 0 && data_offset > (guint32)offset) {
			len = tvb_reported_length_remaining(tvb, data_offset);
		}

		if (data_length <= (guint32)len) {
			next_tvb = tvb_new_subset_length(tvb, data_offset,
						  data_length);
		}

		if (next_tvb != NULL) {
			dissect_smb_direct_payload(next_tvb, pinfo,
						   parent_tree, remaining_length);
		}

		/* offset = data_offset + data_length; */
		break;
	}

	return;
}
Example #16
0
/* ---------------------------------------------- */
static void
dissect_fix_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti;
    proto_tree *fix_tree;
    int pdu_len;
    int offset = 0;
    int field_offset, ctrla_offset;
    int tag_value;
    char *value;
    char *tag_str;
    fix_parameter *tag;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        field_offset =  tag->ctrla_offset + 1;

        tag_str = NULL;
    }
    return;
}
Example #17
0
        case 8:
            return tvb_get_guint64(tvb, offset, encoding);
    }

    return 0;
}

static int
dissect_uds(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void* data _U_)
{
    proto_tree *uds_tree, *subtree;
    proto_item *ti;
    guint8      sid, service;
    guint32     enum_val;
    const char *service_name;
    guint32 data_length = tvb_reported_length(tvb);

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

    sid = tvb_get_guint8(tvb, UDS_SID_OFFSET);
    service = sid & UDS_SID_MASK;
    service_name = val_to_str(service, uds_services, "Unknown (0x%02x)");

    col_add_fstr(pinfo->cinfo, COL_INFO, "%-7s   %-36s", (sid & UDS_REPLY_MASK)? "Reply": "Request", service_name);

    ti = proto_tree_add_item(tree, proto_uds, tvb, 0, -1, ENC_NA);
    uds_tree = proto_item_add_subtree(ti, ett_uds);
    proto_tree_add_item(uds_tree, hf_uds_service, tvb, UDS_SID_OFFSET, UDS_SID_LEN, ENC_BIG_ENDIAN);
    proto_tree_add_item(uds_tree, hf_uds_reply, tvb, UDS_SID_OFFSET, UDS_SID_LEN, ENC_BIG_ENDIAN);
Example #18
0
/*ams*/
static gint dissect_ams(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
   proto_item *ti, *anItem;
   proto_tree *ams_tree = NULL, *ams_adstree, *ams_statetree;
   gint offset = 0;
   guint ams_length = tvb_reported_length(tvb);
   guint16 stateflags = 0;
   guint16 cmdId = 0;

   char szText[200];
   int nMax = sizeof(szText)-1;

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

   col_clear(pinfo->cinfo, COL_INFO);

   if( pinfo->ethertype != 0x88a4 )
   {
      if( TcpAdsParserHDR_Len > ams_length )
         return offset;
      ams_length -= TcpAdsParserHDR_Len;

      offset = TcpAdsParserHDR_Len;
   }

   if( ams_length < AmsHead_Len )
      return offset;

  if (tree)
  {
     ti = proto_tree_add_item(tree, proto_ams, tvb, 0, -1, ENC_NA);
     ams_tree = proto_item_add_subtree(ti, ett_ams);

     NetIdFormater(tvb, offset, szText, nMax);
     proto_tree_add_string(ams_tree, hf_ams_targetnetid, tvb, offset, AmsNetId_Len, szText);
     offset += AmsNetId_Len;

     proto_tree_add_item(ams_tree, hf_ams_targetport, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     offset += sizeof(guint16);

     NetIdFormater(tvb, offset, szText, nMax);
     proto_tree_add_string(ams_tree, hf_ams_sendernetid, tvb, offset, AmsNetId_Len, szText);
     offset += AmsNetId_Len;

     proto_tree_add_item(ams_tree, hf_ams_senderport, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     offset += sizeof(guint16);

     proto_tree_add_item(ams_tree, hf_ams_cmdid, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     cmdId = tvb_get_letohs(tvb, offset);
     offset+=sizeof(guint16);

     anItem = proto_tree_add_item(ams_tree, hf_ams_stateflags, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     ams_statetree = proto_item_add_subtree(anItem, ett_ams_stateflags);
     proto_tree_add_item(ams_statetree, hf_ams_stateresponse,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     proto_tree_add_item(ams_statetree, hf_ams_statenoreturn,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     proto_tree_add_item(ams_statetree, hf_ams_stateadscmd,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     proto_tree_add_item(ams_statetree, hf_ams_statesyscmd,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     proto_tree_add_item(ams_statetree, hf_ams_statehighprio,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     proto_tree_add_item(ams_statetree, hf_ams_statetimestampadded,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     proto_tree_add_item(ams_statetree, hf_ams_stateudp,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     proto_tree_add_item(ams_statetree, hf_ams_stateinitcmd,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     proto_tree_add_item(ams_statetree, hf_ams_statebroadcast,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
     stateflags = tvb_get_letohs(tvb, offset);
     offset+=sizeof(guint16);

     proto_tree_add_item(ams_tree, hf_ams_cbdata, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
     offset+=sizeof(guint32);

     proto_tree_add_item(ams_tree, hf_ams_errorcode, tvb, offset, sizeof(guint32),ENC_LITTLE_ENDIAN);
     offset+=sizeof(guint32);

     proto_tree_add_item(ams_tree, hf_ams_invokeid, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
     offset+=sizeof(guint32);
  }
  else
  {
     offset+=AmsHead_Len;
  }

  if ( (stateflags & AMSCMDSF_ADSCMD) != 0 )
  {
     /* ADS */
     if ( (stateflags & AMSCMDSF_RESPONSE) == 0 )
     {
        /* Request */
        switch ( cmdId )
        {
        case ADSSRVID_READ:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Request");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadrequest, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsReadReq_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadrequest);
                    proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);
                 }
              }
           }
           break;
        case ADSSRVID_WRITE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Request");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adswriterequest, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsWriteReq_Len - sizeof(guint16) )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswriterequest);
                    proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA);
                 }
              }
           }
           break;
        case ADSSRVID_READWRITE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Write Request");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadwriterequest, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsReadWriteReq_Len - sizeof(guint16))
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadwriterequest);
                    proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adscbreadlength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adscbwritelength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset+16, ams_length-offset, ENC_NA);
                 }
              }
           }
           break;
        case ADSSRVID_READSTATE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Read State Request");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadstaterequest, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsReadStateReq_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadstaterequest);
                    proto_tree_add_item(ams_adstree, hf_ams_adsinvokeid, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                 }
              }
           }
           break;
        case ADSSRVID_WRITECTRL:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Control Request");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adswritectrlrequest, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsWriteControlReq_Len - sizeof(guint16) )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswritectrlrequest);
                    proto_tree_add_item(ams_adstree, hf_ams_adsstate, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint16);

                    proto_tree_add_item(ams_adstree, hf_ams_adsdevicestate, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint16);

                    proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA);
                 }
              }
           }
           break;
        case ADSSRVID_READDEVICEINFO:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Device Info Request");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsreaddinforequest, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsReadDeviceInfoReq_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreaddinforequest);
                    proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                 }
              }
           }
           break;
        case ADSSRVID_ADDDEVICENOTE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Add Device Notification Request");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsadddnrequest, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsAddDeviceNotificationReq_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsadddnrequest);
                    proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adstransmode, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsmaxdelay, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adscycletime, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);
                 }
              }
           }
           break;
        case ADSSRVID_DELDEVICENOTE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Delete Device Notification Request");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsdeldnrequest, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsDelDeviceNotificationReq_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsdeldnrequest);
                    proto_tree_add_item(ams_adstree, hf_ams_adsnotificationhandle, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                 }
              }
           }
           break;
        case ADSSRVID_DEVICENOTE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Device Notification Request");

              if( tree )
              {
                 /*guint32 cbLength;
                 guint32 nStamps;*/

                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsdnrequest, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsDeviceNotificationReq_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsdnrequest);
                    proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    /*cbLength = tvb_get_letohs(tvb, offset);*/
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsnoteblocksstamps, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    /*nStamps = tvb_get_letohs(tvb, offset);*/
                    offset+=sizeof(guint32);

                    /*ToDo: dissect noteblocks*/
                 }
              }
           }
           break;
        }
     }
     else
     {
        /* Response */
        switch ( cmdId )
        {
        case ADSSRVID_READ:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Response");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadresponse, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsReadRes_Len - sizeof(guint16) )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadresponse);
                    proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA);
                 }
              }
           }
           break;
        case ADSSRVID_WRITE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Response");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adswriteresponse, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsWriteRes_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswriteresponse);
                    proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                 }
              }
           }
           break;
        case ADSSRVID_READWRITE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Write Response");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadwriteresponse, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsReadWriteRes_Len - sizeof(guint16) )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadwriteresponse);
                    proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA);
                 }
              }
           }
           break;
        case ADSSRVID_READSTATE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Read State Response");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadstateresponse, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsReadStateRes_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadstateresponse);
                    proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsstate, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsdevicestate, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
                 }
              }
           }
           break;
        case ADSSRVID_WRITECTRL:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Control Response");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adswritectrlresponse, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsWriteControlRes_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswritectrlresponse);
                    proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                 }
              }
           }
           break;
        case ADSSRVID_READDEVICEINFO:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Device Info Response");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsreaddinforesponse, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsReadDeviceInfoRes_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreaddinforesponse);
                    proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsversionversion, tvb, offset++, sizeof(guint8), ENC_LITTLE_ENDIAN);
                    proto_tree_add_item(ams_adstree, hf_ams_adsversionrevision, tvb, offset++, sizeof(guint8), ENC_LITTLE_ENDIAN);
                    proto_tree_add_item(ams_adstree, hf_ams_adsversionbuild, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint16);

                    proto_tree_add_item(ams_adstree, hf_ams_adsdevicename, tvb, offset, ams_length-offset, ENC_ASCII|ENC_NA);
                 }
              }
           }
           break;
        case ADSSRVID_ADDDEVICENOTE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Device Notification Response");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsadddnresponse, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsAddDeviceNotificationRes_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsadddnresponse);
                    proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                    offset+=sizeof(guint32);

                    proto_tree_add_item(ams_adstree, hf_ams_adsnotificationhandle, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                 }
              }
           }
           break;
        case ADSSRVID_DELDEVICENOTE:
           {
              col_append_str(pinfo->cinfo, COL_INFO, "ADS Delete Device Notification Response");

              if( tree )
              {
                 anItem = proto_tree_add_item(ams_tree, hf_ams_adsdeldnresponse, tvb, offset, ams_length-offset, ENC_NA);
                 if( ams_length-offset >= TAdsDelDeviceNotificationRes_Len )
                 {
                    ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsdeldnresponse);
                    proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN);
                 }
              }
           }
           break;
        }
     }
  }
  else
  {
    if ( (stateflags & AMSCMDSF_RESPONSE) == 0 )
       col_append_str(pinfo->cinfo, COL_INFO, "AMS Request");
    else
       col_append_str(pinfo->cinfo, COL_INFO, "AMS Response");
    if( tree && ams_length-offset > 0 )
        proto_tree_add_item(ams_tree, hf_ams_data, tvb, offset, ams_length-offset, ENC_NA);
  }
return offset;
}
Example #19
0
/* Code to actually dissect the packets */
static void
dissect_gvrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item   *ti;
    proto_tree   *gvrp_tree;
    guint16       protocol_id;
    guint8        octet;
    int           msg_index, attr_index, offset = 0, length = tvb_reported_length(tvb);

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

    col_set_str(pinfo->cinfo, COL_INFO, "GVRP");

    if (tree)
    {
	ti = proto_tree_add_item(tree, proto_gvrp, tvb, 0, length, FALSE);

	gvrp_tree = proto_item_add_subtree(ti, ett_gvrp);

	/* Read in GARP protocol ID */
	protocol_id = tvb_get_ntohs(tvb, GARP_PROTOCOL_ID);

	proto_tree_add_uint_format(gvrp_tree, hf_gvrp_proto_id, tvb,
				   GARP_PROTOCOL_ID, sizeof(guint16),
				   protocol_id,
				   "Protocol Identifier: 0x%04x (%s)",
				   protocol_id,
				   protocol_id == GARP_DEFAULT_PROTOCOL_ID ?
				     "GARP VLAN Registration Protocol" :
				     "Unknown Protocol");

	/* Currently only one protocol ID is supported */
	if (protocol_id != GARP_DEFAULT_PROTOCOL_ID)
	{
	    proto_tree_add_text(gvrp_tree, tvb, GARP_PROTOCOL_ID, sizeof(guint16),
 "   (Warning: this version of Wireshark only knows about protocol id = 1)");
	    call_dissector(data_handle,
	        tvb_new_subset(tvb, GARP_PROTOCOL_ID + sizeof(guint16), -1, -1),
	        pinfo, tree);
	    return;
	}

	offset += sizeof(guint16);
	length -= sizeof(guint16);

	msg_index = 0;

	/* Begin to parse GARP messages */
	while (length)
	{
	    proto_item   *msg_item;
	    int           msg_start = offset;

	    /* Read in attribute type. */
	    octet = tvb_get_guint8(tvb, offset);

	    /* Check for end of mark */
	    if (octet == GARP_END_OF_MARK)
	    {
		/* End of GARP PDU */
		if (msg_index)
		{
		    proto_tree_add_text(gvrp_tree, tvb, offset, sizeof(guint8),
					"End of mark");
		    break;
		}
		else
		{
		    call_dissector(data_handle,
		        tvb_new_subset_remaining(tvb, offset), pinfo, tree);
		    return;
		}
	    }

	    offset += sizeof(guint8);
	    length -= sizeof(guint8);

	    msg_item = proto_tree_add_text(gvrp_tree, tvb, msg_start, -1,
					   "Message %d", msg_index + 1);

	    proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_type, tvb,
				msg_start, sizeof(guint8), octet);

	    /* GVRP only supports one attribute type. */
	    if (octet != GVRP_ATTRIBUTE_TYPE)
	    {
		call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset),
		    pinfo, tree);
		return;
	    }

	    attr_index = 0;

	    while (length)
	    {
		int          attr_start = offset;
		proto_item   *attr_item;

		/* Read in attribute length. */
		octet = tvb_get_guint8(tvb, offset);

		/* Check for end of mark */
		if (octet == GARP_END_OF_MARK)
		{
		    /* If at least one message has been already read,
		     * check for another end of mark.
		     */
		    if (attr_index)
		    {
			proto_tree_add_text(gvrp_tree, tvb, offset,
					    sizeof(guint8), "  End of mark");

			offset += sizeof(guint8);
			length -= sizeof(guint8);

			proto_item_set_len(msg_item, offset - msg_start);
			break;
		    }
		    else
		    {
			call_dissector(data_handle,
			    tvb_new_subset_remaining(tvb, offset), pinfo, tree);
			return;
		    }
		}
		else
		{
		    guint8   event;

		    offset += sizeof(guint8);
		    length -= sizeof(guint8);

		    attr_item = proto_tree_add_text(gvrp_tree, tvb,
			 attr_start, -1, "  Attribute %d", attr_index + 1);

		    proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_length,
			 tvb, attr_start, sizeof(guint8), octet);

		    /* Read in attribute event */
		    event = tvb_get_guint8(tvb, offset);

		    proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_event,
			 tvb, offset, sizeof(guint8), event);

		    offset += sizeof(guint8);
		    length -= sizeof(guint8);

		    switch (event) {

		    case GVRP_EVENT_LEAVEALL:
			if (octet != GVRP_LENGTH_LEAVEALL)
			{
			    call_dissector(data_handle,
			        tvb_new_subset_remaining(tvb, offset), pinfo,
			        tree);
			    return;
			}
			break;

		     case GVRP_EVENT_JOINEMPTY:
		     case GVRP_EVENT_JOININ:
		     case GVRP_EVENT_LEAVEEMPTY:
		     case GVRP_EVENT_LEAVEIN:
		     case GVRP_EVENT_EMPTY:
			if (octet != GVRP_LENGTH_NON_LEAVEALL)
			{
			    call_dissector(data_handle,
			        tvb_new_subset_remaining(tvb, offset),pinfo,
			        tree);
			    return;
			}

			/* Show attribute value */
			proto_tree_add_item(gvrp_tree, hf_gvrp_attribute_value,
			    tvb, offset, sizeof(guint16), FALSE);

			offset += sizeof(guint16);
			length -= sizeof(guint16);
			break;

		     default:
			call_dissector(data_handle,
			    tvb_new_subset_remaining(tvb, offset), pinfo, tree);
			return;
		    }
		}

		proto_item_set_len(attr_item, offset - attr_start);

		attr_index++;
	    }

	    msg_index++;
	}
    }
}
Example #20
0
/* UCD dissector */
static void dissect_mac_mgmt_msg_ucd_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint offset = 0;
	guint tvb_len, length;
	gint  tlv_type, tlv_len, tlv_offset, tlv_value_offset;
	tlv_info_t tlv_info;
	gchar* proto_str;

	{	/* we are being asked for details */
		proto_item *ucd_item;
		proto_tree *ucd_tree;
		guint ucd_ranging_backoff_start;
		guint ucd_ranging_backoff_end;
		guint ucd_request_backoff_start;
		guint ucd_request_backoff_end;

		tvb_len =  tvb_reported_length(tvb);
		/* display MAC payload type UCD */
		ucd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, -1, "Uplink Channel Descriptor (UCD)");
		ucd_tree = proto_item_add_subtree(ucd_item, ett_mac_mgmt_msg_ucd_decoder);

		/* Decode and display the Uplink Channel Descriptor (UCD) */
		/* display the Configuration Change Count */
		proto_tree_add_item(ucd_tree, hf_ucd_config_change_count, tvb, offset, 1, ENC_NA);
		offset++;

		/* get the ranging backoff start */
		ucd_ranging_backoff_start = tvb_get_guint8(tvb, offset);
		proto_tree_add_uint_format_value(ucd_tree, hf_ucd_ranging_backoff_start, tvb, offset, 1, (1 << ucd_ranging_backoff_start), "2^%u = %u", ucd_ranging_backoff_start, (1 << ucd_ranging_backoff_start));
		offset++;

		/* get the ranging backoff end */
		ucd_ranging_backoff_end = tvb_get_guint8(tvb, offset);
		proto_tree_add_uint_format_value(ucd_tree, hf_ucd_ranging_backoff_end, tvb, offset, 1, (1 << ucd_ranging_backoff_end), "2^%u = %u", ucd_ranging_backoff_end, (1 << ucd_ranging_backoff_end));
		offset++;

		/* get the request backoff start */
		ucd_request_backoff_start = tvb_get_guint8(tvb, offset);
		proto_tree_add_uint_format_value(ucd_tree, hf_ucd_request_backoff_start, tvb, offset, 1, (1 << ucd_request_backoff_start), "2^%u = %u", ucd_request_backoff_start, (1 << ucd_request_backoff_start));
		offset++;

		/* get the request backoff end */
		ucd_request_backoff_end = tvb_get_guint8(tvb, offset);
		proto_tree_add_uint_format_value(ucd_tree, hf_ucd_request_backoff_end, tvb, offset, 1, (1 << ucd_request_backoff_end), "2^%u = %u", ucd_request_backoff_end, (1 << ucd_request_backoff_end));
		offset++;

		while(offset < tvb_len)
		{
			/* get the TLV information */
			init_tlv_info(&tlv_info, tvb, offset);
			/* get the TLV type */
			tlv_type = get_tlv_type(&tlv_info);
			/* get the TLV length */
			tlv_len = get_tlv_length(&tlv_info);
			if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1)
			{	/* invalid tlv info */
				col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "UCD TLV error");
				proto_tree_add_item(ucd_tree,hf_ucd_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA);
				break;
			}
			/* get the TLV value offset */
			tlv_value_offset = get_tlv_value_offset(&tlv_info);
#ifdef DEBUG /* for debug only */
			proto_tree_add_protocol_format(ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, (tlv_len + tlv_value_offset), "UCD Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len, offset, tvb_len);
#endif
			/* update the offset */
			offset += tlv_value_offset;
			/* process UCD TLV Encoded information */
			if (include_cor2_changes)
			{
				switch (tlv_type)
				{
					case UCD_TLV_T_203_UL_PUSC_SUBCHANNEL_ROTATION:
					{
						add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_203_ul_pusc_subchannel_rotation, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
						break;
					}
					case UCD_TLV_T_205_RELATIVE_POWER_OFFSET_UL_HARQ_BURST:
					{
						add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_205_relative_power_offset_ul_harq_burst, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
						break;
					}
					case UCD_TLV_T_206_RELATIVE_POWER_OFFSET_UL_BURST_CONTAINING_MAC_MGMT_MSG:
					{
						add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_206_relative_power_offset_ul_burst_containing_mac_mgmt_msg, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
						break;
					}
					case UCD_TLV_T_207_UL_INITIAL_TRANSMIT_TIMING:
					{
						add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_207_ul_initial_transmit_timing, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
						break;
					}
					case UCD_TLV_T_210_FAST_FEEDBACK_REGION:
					{
						add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_210_fast_feedback_region, tvb, offset-tlv_value_offset, ENC_NA);
						break;
					}
					case UCD_TLV_T_211_HARQ_ACK_REGION:
					{
						add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_211_harq_ack_region, tvb, offset-tlv_value_offset, ENC_NA);
						break;
					}
					case UCD_TLV_T_212_RANGING_REGION:
					{
						add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_212_ranging_region, tvb, offset-tlv_value_offset, ENC_NA);
						break;
					}
					case UCD_TLV_T_213_SOUNDING_REGION:
					{
						add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_213_sounding_region, tvb, offset-tlv_value_offset, ENC_NA);
						break;
					}
				}
			}
			switch (tlv_type)
			{
				proto_tree *tlv_tree;
				proto_item *tlv_item1;
				guint ul_burst_uiuc;
				guint utemp;

				case UCD_UPLINK_BURST_PROFILE:
				{
					/* get the UIUC */
					ul_burst_uiuc = tvb_get_guint8(tvb, offset) & 0x0F;
					/* add TLV subtree */
					proto_str = wmem_strdup_printf(wmem_packet_scope(), "Uplink Burst Profile (UIUC = %u)", ul_burst_uiuc);
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset-tlv_value_offset, tlv_len, proto_str);
					proto_tree_add_item(tlv_tree, hf_ucd_ul_burst_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_ucd_ul_burst_uiuc, tvb, offset, 1, ENC_BIG_ENDIAN);
					for (tlv_offset = 1; tlv_offset < tlv_len;)
					{	/* get the TLV information */
						init_tlv_info(&tlv_info, tvb, (offset+tlv_offset));
						/* get the TLV type */
						tlv_type = get_tlv_type(&tlv_info);
						if(tlv_type == -1)
						{	/* invalid tlv info */
							col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "UL Burst Profile error");
							proto_tree_add_item(tlv_tree, hf_ucd_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA);
							break;
						}
						/* get the TLV length */
						length = get_tlv_length(&tlv_info);

						switch (tlv_type)
						{
							proto_item *tlv_item2;
							case UCD_BURST_FEC:
							{
								add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_fec, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN);
								break;
							}
							case UCD_BURST_RANGING_DATA_RATIO:
							{
								tlv_item2 = add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_ranging_data_ratio, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN);
								proto_item_append_text(tlv_item2, " dB");
								break;
							}
#if 0 /* for OFDM */
							case UCD_BURST_POWER_BOOST:
							{
								tlv_item2 = add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_power_boost, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN);
								proto_item_append_text(tlv_item2, " dB");
								break;
							}
							case UCD_BURST_TCS_ENABLE:
							{
								add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_tcs_enable, tvb, (offset+tlv_offset), 1, ENC_BIG_ENDIAN);
								break;
							}
#endif
							default:
								/* ??? */
								break;
						}
						tlv_offset += (length+get_tlv_value_offset(&tlv_info));
					}
					break;
				}
				case UCD_RESERVATION_TIMEOUT:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_res_timeout, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_BW_REQ_SIZE:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_bw_req_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " PS");
					break;
				}
				case UCD_RANGING_REQ_SIZE:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_ranging_req_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " PS");
					break;
				}
				case UCD_FREQUENCY:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_freq, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " kHz");
					break;
				}
				case UCD_TLV_T_7_HO_RANGING_START:
				{
					tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_ho_ranging_start, tvb, offset-tlv_value_offset);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_uint_format_value(tlv_tree, hf_ucd_ho_ranging_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_8_RANGING_HO_END:
				{
					tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_ho_ranging_end, tvb, offset-tlv_value_offset);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_uint_format_value(tlv_tree, hf_ucd_ho_ranging_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_158_OPTIONAL_PERMUTATION_UL_ALLOCATED_SUBCHANNELS_BITMAP:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_158_optional_permutation_ul_allocated_subchannels_bitmap, tvb, offset-tlv_value_offset, ENC_NA);
					break;
				}
				case UCD_TLV_T_159_BAND_AMC_ALLOCATION_THRESHHOLD:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_159_band_amc_allocation_threshold, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " dB");
					break;
				}
				case UCD_TLV_T_160_BAND_AMC_RELEASE_THRESHOLD:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_160_band_amc_release_threshold, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " dB");
					break;
				}
				case UCD_TLV_T_161_BAND_AMC_ALLOCATION_TIMER:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_161_band_amc_allocation_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " frames");
					break;
				}
				case UCD_TLV_T_162_BAND_AMC_RELEASE_TIMER:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_161_band_amc_allocation_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " frames");
					break;
				}
				case UCD_TLV_T_163_BAND_STATUS_REPORT_MAX_PERIOD:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_163_band_status_report_max_period, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " frames");
					break;
				}
				case UCD_TLV_T_164_BAND_AMC_RETRY_TIMER:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_164_band_amc_retry_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " frames");
					break;
				}
				case UCD_TLV_T_170_SAFETY_CHANNEL_RETRY_TIMER:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_170_safety_channel_retry_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " frames");
					break;
				}
				case UCD_TLV_T_171_HARQ_ACK_DELAY_FOR_DL_BURST:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_171_harq_ack_delay_dl_burst, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " frames offset");
					break;
				}
				case UCD_TLV_T_172_CQICH_BAND_AMC_TRANSITION_DELAY:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_172_cqich_band_amc_transition_delay, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					proto_item_append_text(tlv_item1, " frames");
					break;
				}
				case UCD_TLV_T_174_MAXIMUM_RETRANSMISSION:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_174_maximum_retransmission, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_176_SIZE_OF_CQICH_ID_FIELD:
				{
					utemp = tvb_get_guint8(tvb, offset);
					cqich_id_size = 0;	/* Default is 0 */
					if (utemp && utemp < 8) {
					    /* Set for CQICH_Alloc_IE */
					    cqich_id_size = utemp + 2;
					}
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_176_size_of_cqich_id_field, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_177_NORMALIZED_CN_OVERRIDE_2:
				{
					/* add TLV subtree */
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_177_normalized_cn_override2, tvb, offset-tlv_value_offset, ENC_NA|ENC_ASCII);
					tlv_tree = proto_item_add_subtree(tlv_item1, ett_mac_mgmt_msg_ucd_decoder);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_177_normalized_cn_override2_first_line, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_177_normalized_cn_override2_list, tvb, offset + 3, 7, ENC_ASCII|ENC_NA);
					break;
				}
				case UCD_TLV_T_186_UPPER_BOUND__AAS_PREAMBLE:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_186_upper_bound_aas_preamble, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_187_LOWER_BOUND_AAS_PREAMBLE:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_187_lower_bound_aas_preamble, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_188_ALLOW_AAS_BEAM_SELECT_MESSAGE:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_188_allow_aas_beam_select_message, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_189_USE_CQICH_INDICATION_FLAG:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_189_use_cqich_indication_flag, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_190_MS_SPECIFIC_UP_POWER_OFFSET_ADJUSTMENT_STEP:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_190_ms_specific_up_power_addjustment_step, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_191_MS_SPECIFIC_DOWN_POWER_OFSET_ADJUSTMENT_STEP:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_191_ms_specific_down_power_addjustment_step, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_192_MIN_LEVEL_POWER_OFFSET_ADJUSTMENT:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_192_min_level_power_offset_adjustment, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_193_MAX_LEVEL_POWER_OFFSETR_ADJUSTMENT:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_193_max_level_power_offset_adjustment, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_194_HANDOVER_RANGING_CODES:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_194_handover_ranging_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_195_INITIAL_RANGING_INTERVAL:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_195_initial_ranging_interval, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_196_TX_POWER_REPORT:
				{
					tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_196_tx_power_report, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					tlv_tree = proto_item_add_subtree(tlv_item1, ett_mac_mgmt_msg_ucd_decoder);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_threshold, tvb, offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_interval, tvb , offset, 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_a_p_avg, tvb, (offset + 1), 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_threshold_icqch, tvb, (offset + 1), 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_interval_icqch, tvb, (offset + 2), 1, ENC_BIG_ENDIAN);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_a_p_avg_icqch, tvb, (offset + 2), 1, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_197_NORMALIZED_CN_FOR_CHANNEL_SOUNDING:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_195_initial_ranging_interval, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_TLV_T_198_INTIAL_RANGING_BACKOFF_START:
				{
					tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_initial_range_backoff_start, tvb, offset-tlv_value_offset);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_uint_format_value(tlv_tree, hf_ucd_initial_range_backoff_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_199_INITIAL_RANGING_BACKOFF_END:
				{
					tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_initial_range_backoff_end, tvb, offset-tlv_value_offset);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_uint_format_value(tlv_tree, hf_ucd_initial_range_backoff_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_200_BANDWIDTH_REQUESET_BACKOFF_START:
				{
					tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_bandwidth_backoff_start, tvb, offset-tlv_value_offset);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_uint_format_value(tlv_tree, hf_ucd_bandwidth_backoff_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_201_BANDWIDTH_REQUEST_BACKOFF_END:
				{
					tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_bandwidth_backoff_end, tvb, offset-tlv_value_offset);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_uint_format_value(tlv_tree, hf_ucd_bandwidth_backoff_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_202_UPLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_202_uplink_burst_profile_for_multiple_fec_types, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_INITIAL_RANGING_CODES:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_150_initial_ranging_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_PERIODIC_RANGING_CODES:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_151_periodic_ranging_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_BANDWIDTH_REQUEST_CODES:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_152_bandwidth_request_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_PERIODIC_RANGING_BACKOFF_START:
				{
					tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_periodic_ranging_backoff_start, tvb, offset-tlv_value_offset);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_uint_format_value(tlv_tree, hf_ucd_periodic_ranging_backoff_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp));
					break;

				}
				case UCD_PERIODIC_RANGING_BACKOFF_END:
				{
					tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_periodic_ranging_backoff_end, tvb, offset-tlv_value_offset);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_uint_format_value(tlv_tree, hf_ucd_periodic_ranging_backoff_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_START_OF_RANGING_CODES_GROUP:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_155_start_of_ranging_codes_group, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;

				}
				case UCD_PERMUTATION_BASE:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_156_permutation_base, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN);
					break;
				}
				case UCD_UL_ALLOCATED_SUBCHANNELS_BITMAP:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_ul_allocated_subchannles_bitmap, tvb, offset-tlv_value_offset, ENC_NA);
					break;
				}
				case UCD_TLV_T_203_UL_PUSC_SUBCHANNEL_ROTATION:
				case UCD_TLV_T_205_RELATIVE_POWER_OFFSET_UL_HARQ_BURST:
				case UCD_TLV_T_206_RELATIVE_POWER_OFFSET_UL_BURST_CONTAINING_MAC_MGMT_MSG:
				case UCD_TLV_T_207_UL_INITIAL_TRANSMIT_TIMING:
				case UCD_TLV_T_210_FAST_FEEDBACK_REGION:
				case UCD_TLV_T_211_HARQ_ACK_REGION:
				case UCD_TLV_T_212_RANGING_REGION:
				case UCD_TLV_T_213_SOUNDING_REGION:
				{
					/* Unknown TLV type if cor2 not enabled. */
					if (!include_cor2_changes)
					{
						add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_invalid_tlv, tvb, offset-tlv_value_offset, ENC_NA);
					}
					break;
				}
				default:
				{
					add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_invalid_tlv, tvb, offset-tlv_value_offset, ENC_NA);
				}
			}	/* end of switch(tlv_type) */
			offset += tlv_len;
		}	/* end of TLV process while loop */
	}
}
Example #21
0
/*
 * dissect_pgm - The dissector for Pragmatic General Multicast
 */
static void
dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint16 pgmhdr_sport;
	guint16 pgmhdr_dport;
	guint8  pgmhdr_type;
	guint8  pgmhdr_opts;
	guint16 pgmhdr_cksum;
	guint16 pgmhdr_tsdulen;
	guint32 sqn;
	guint16 afi;

	guint       plen   = 0;
	proto_item *ti;
	const char *pktname;
	const char *pollstname;
	char       *gsi;
	gboolean    isdata = FALSE;
	guint       pgmlen, reportedlen;

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

	col_clear(pinfo->cinfo, COL_INFO);
	if (tvb_reported_length_remaining(tvb, 0) < 18) {
		col_set_str(pinfo->cinfo, COL_INFO,
				"Packet too small");
		return;
	}

	pinfo->srcport = pgmhdr_sport = tvb_get_ntohs(tvb, 0);
	pinfo->destport = pgmhdr_dport = tvb_get_ntohs(tvb, 2);

	pgmhdr_type = tvb_get_guint8(tvb, 4);
	pktname = val_to_str(pgmhdr_type, type_vals, "Unknown (0x%02x)");

	pgmhdr_opts = tvb_get_guint8(tvb, 5);
	pgmhdr_cksum = tvb_get_ntohs(tvb, 6);
	gsi = tvb_bytes_to_str(wmem_packet_scope(), tvb, 8, 6);
	pgmhdr_tsdulen = tvb_get_ntohs(tvb, 14);
	sqn = tvb_get_ntohl(tvb, 16);

	switch(pgmhdr_type) {
	case PGM_SPM_PCKT:
	case PGM_NAK_PCKT:
	case PGM_NNAK_PCKT:
	case PGM_NCF_PCKT:
	case PGM_POLR_PCKT:
	case PGM_ACK_PCKT:
		col_add_fstr(pinfo->cinfo, COL_INFO,
				"%-5s sqn 0x%x gsi %s", pktname, sqn, gsi);
		break;
	case PGM_RDATA_PCKT:
	case PGM_ODATA_PCKT:
		col_add_fstr(pinfo->cinfo, COL_INFO,
			    "%-5s sqn 0x%x gsi %s tsdulen %d", pktname, sqn, gsi,
			    pgmhdr_tsdulen);

		isdata = TRUE;
		break;
	case PGM_POLL_PCKT: {
		guint16 poll_stype = tvb_get_ntohs(tvb, 22);
		pollstname = val_to_str(poll_stype, poll_subtype_vals, "Unknown (0x%02x)");

		col_add_fstr(pinfo->cinfo, COL_INFO,
				"%-5s sqn 0x%x gsi %s subtype %s",
					pktname, sqn, gsi, pollstname);
		}
		break;
	default:
		return;
	}

	{
		proto_tree *pgm_tree = NULL;
		proto_tree *opt_tree = NULL;
		proto_tree *type_tree = NULL;
		proto_item *tf, *hidden_item;
		ptvcursor_t* cursor;

		ti = proto_tree_add_protocol_format(tree, proto_pgm,
			tvb, 0, -1,
			"Pragmatic General Multicast: Type %s"
			    " Src Port %u, Dst Port %u, GSI %s", pktname,
			pgmhdr_sport, pgmhdr_dport, gsi);

		pgm_tree = proto_item_add_subtree(ti, ett_pgm);

		cursor = ptvcursor_new(pgm_tree, tvb, 0);

		hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 0, 2, ENC_BIG_ENDIAN);
		PROTO_ITEM_SET_HIDDEN(hidden_item);
		hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 2, 2, ENC_BIG_ENDIAN);
		PROTO_ITEM_SET_HIDDEN(hidden_item);
		ptvcursor_add(cursor, hf_pgm_main_sport, 2, ENC_BIG_ENDIAN);
		ptvcursor_add(cursor, hf_pgm_main_dport, 2, ENC_BIG_ENDIAN);
		ptvcursor_add(cursor, hf_pgm_main_type, 1, ENC_BIG_ENDIAN);

		tf = proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_opts, tvb,
			ptvcursor_current_offset(cursor), 1, pgmhdr_opts, "%s (0x%x)",
			optsstr(pgmhdr_opts), pgmhdr_opts);
		opt_tree = proto_item_add_subtree(tf, ett_pgm_optbits);
		ptvcursor_set_tree(cursor, opt_tree);

		ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_opt, 1, ENC_BIG_ENDIAN);
		ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_netsig, 1, ENC_BIG_ENDIAN);
		ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_varlen, 1, ENC_BIG_ENDIAN);
		ptvcursor_add(cursor, hf_pgm_main_opts_parity, 1, ENC_BIG_ENDIAN);
		ptvcursor_set_tree(cursor, pgm_tree);

		/* Checksum may be 0 (not available), but not for DATA packets */
		if ((pgmhdr_type != PGM_RDATA_PCKT) && (pgmhdr_type != PGM_ODATA_PCKT) &&
		    (pgmhdr_cksum == 0))
		{
			proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb,
				ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "not available");
		} else {
			reportedlen = tvb_reported_length(tvb);
			pgmlen = tvb_captured_length(tvb);
			if (pgm_check_checksum && pgmlen >= reportedlen) {
				vec_t cksum_vec[1];
				guint16 computed_cksum;

				SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, 0, pgmlen);
				computed_cksum = in_cksum(&cksum_vec[0], 1);
				if (computed_cksum == 0) {
					proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb,
						ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "0x%04x [correct]", pgmhdr_cksum);
				} else {
					hidden_item = proto_tree_add_boolean(pgm_tree, hf_pgm_main_cksum_bad, tvb,
					    ptvcursor_current_offset(cursor), 2, TRUE);
					PROTO_ITEM_SET_HIDDEN(hidden_item);
					proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb,
					    ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "0x%04x [incorrect, should be 0x%04x]",
						pgmhdr_cksum, in_cksum_shouldbe(pgmhdr_cksum, computed_cksum));
				}
			} else {
				ptvcursor_add_no_advance(cursor, hf_pgm_main_cksum, 2, ENC_BIG_ENDIAN);
			}
		}
		ptvcursor_advance(cursor, 2);

		ptvcursor_add(cursor, hf_pgm_main_gsi, 6, ENC_NA);
		ptvcursor_add(cursor, hf_pgm_main_tsdulen, 2, ENC_BIG_ENDIAN);

		switch(pgmhdr_type) {
		case PGM_SPM_PCKT:
			type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen,
												ett_pgm_spm, NULL, "%s Packet", pktname);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_lead, 4, ENC_BIG_ENDIAN);
			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_spm_pathafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_res, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_spm_path, 4, ENC_BIG_ENDIAN);
				break;

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

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				ptvcursor_free(cursor);
				return;
			}
			break;
		case PGM_RDATA_PCKT:
		case PGM_ODATA_PCKT:
			type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen,
												ett_pgm_data, NULL, "%s Packet", pktname);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN);
			break;
		case PGM_NAK_PCKT:
		case PGM_NNAK_PCKT:
		case PGM_NCF_PCKT:
			type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen,
												ett_pgm_nak, NULL, "%s Packet", pktname);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_nak_sqn, 4, ENC_BIG_ENDIAN);
			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_nak_srcafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_nak_srcres, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_nak_src, 4, ENC_BIG_ENDIAN);
				break;

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

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				break;
			}

			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_nak_grpafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_nak_grpres, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_nak_grp, 4, ENC_BIG_ENDIAN);
				break;

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

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				ptvcursor_free(cursor);
				return;
			}
			break;
		case PGM_POLL_PCKT:
			type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen,
												ett_pgm_poll, NULL, "%s Packet", pktname);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_poll_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_round, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_subtype, 2, ENC_BIG_ENDIAN);
			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_poll_pathafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_res, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_poll_path, 4, ENC_BIG_ENDIAN);
				break;

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

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				break;
			}

			ptvcursor_add(cursor, hf_pgm_poll_backoff_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_rand_str, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_matching_bmask, 4, ENC_BIG_ENDIAN);
			break;
		case PGM_POLR_PCKT:
			type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen,
												ett_pgm_polr, NULL, "%s Packet", pktname);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_polr_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_polr_round, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_polr_res, 2, ENC_BIG_ENDIAN);
			break;
		case PGM_ACK_PCKT:
			type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen,
												ett_pgm_ack, NULL, "%s Packet", pktname);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_ack_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_ack_bitmap, 4, ENC_BIG_ENDIAN);
			break;
		}

		if (pgmhdr_opts & PGM_OPT)
			dissect_pgmopts(cursor, pinfo, pktname);

		if (isdata)
			decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport);

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

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

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

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

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

	if (tree) {
		proto_item *direction_ti;

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

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

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

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

	if (tree)
		proto_item_set_len(v5dl_ti, v5dl_header_len);

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

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

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

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

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

	if (XDLC_IS_INFORMATION(control)) {
		/* call V5.2 dissector */
	        call_dissector(v52_handle, next_tvb, pinfo, tree);
	}
}
Example #23
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) {
                guint  length = 0;
                offset += dissect_multiple_certificate(tvb, offset, data_tree);
                offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by ASUE");
                length  = tvb_get_ntohs(tvb, offset+1);
                if (length + 3 + offset + 1 < lenx)
                    offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by AE");
            }

            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;
            guint8  optional_field;

            optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3;

            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 ");
            if (optional_field) {
                dissect_identity_list(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");
            if (offset < lenx)
                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 #24
0
static void
dissect_evrc_aux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, evrc_variant_t evrc_variant)
{
    guint8                      oct;
    guint8                      frame_count;
    guint8                      i;
    guint32                     offset, saved_offset;
    gboolean                    further_entries;
    guint32                     len;
    proto_item                  *item = NULL;
    proto_tree                  *evrc_tree = NULL;
    proto_tree                  *toc_tree = NULL;
    int                         hf_mode_request;
    int                         hf_toc_frame_type_high;
    int                         hf_toc_frame_type_low;

    /*
     * assumed max number of speech frames based on
     * frame count being 5 bits + 1
     */
    guint8                      speech_data_len[0x20];


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

    if (!tree) return;

    offset = 0;
    memset(speech_data_len, 0, sizeof(speech_data_len));

    len = tvb_reported_length(tvb);

    item = proto_tree_add_item(tree, proto_evrc, tvb, 0, len, ENC_NA);

    evrc_tree = proto_item_add_subtree(item, ett_evrc);

    if (evrc_variant == EVRC_VARIANT_EVRC_LEGACY)
    {
        /* legacy 'payload type 60' draft-ietf-avt-evrc-07.txt header format */

        proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(evrc_tree, hf_evrc_interleave_length, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(evrc_tree, hf_evrc_interleave_index, tvb, offset, 1, ENC_BIG_ENDIAN);

        offset++;

        frame_count = 0;
        further_entries = TRUE;
        while (further_entries && (frame_count < sizeof(speech_data_len)) &&
            ((len - offset) > 0))
        {
            item =
                proto_tree_add_text(evrc_tree, tvb, offset, 1, "ToC [%u]", frame_count+1);

            toc_tree = proto_item_add_subtree(item, ett_toc);

            proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_fe_ind, tvb, offset, 1, ENC_BIG_ENDIAN);
            proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_reduc_rate, tvb, offset, 1, ENC_BIG_ENDIAN);
            proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_frame_type, tvb, offset, 1, ENC_BIG_ENDIAN);

            oct = tvb_get_guint8(tvb, offset);
            further_entries = (oct & 0x80) ? TRUE : FALSE;

            speech_data_len[frame_count] = evrc_frame_type_to_octs((guint8)(oct & 0x7f));

            frame_count++;
            offset++;
        }
    }
    else
    {
        /* RFC 3558 header format */

        switch (evrc_variant)
        {
        default:
            proto_tree_add_expert(evrc_tree, pinfo, &ei_evrc_unknown_variant, tvb, offset, len);
            return;

        case EVRC_VARIANT_EVRC:
            hf_mode_request = hf_evrc_mode_request;
            hf_toc_frame_type_high = hf_evrc_toc_frame_type_high;
            hf_toc_frame_type_low = hf_evrc_toc_frame_type_low;

            proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
            break;

        case EVRC_VARIANT_EVRC_B:
            hf_mode_request = hf_evrc_b_mode_request;
            hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high;
            hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low;

            proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
            break;

        case EVRC_VARIANT_EVRC_WB:
            hf_mode_request = hf_evrc_wb_mode_request;
            hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high;
            hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low;

            proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
            break;

        case EVRC_VARIANT_EVRC_NW:
            hf_mode_request = hf_evrc_nw_mode_request;
            hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high;
            hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low;

            proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
            break;

        case EVRC_VARIANT_EVRC_NW2k:
            hf_mode_request = hf_evrc_nw2k_mode_request;
            hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high;
            hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low;

            proto_tree_add_item(evrc_tree, hf_evrc_reserved_2k, tvb, offset, 1, ENC_BIG_ENDIAN);
            proto_tree_add_item(evrc_tree, hf_evrc_enc_capability_2k, tvb, offset, 1, ENC_BIG_ENDIAN);
            break;
        }

        proto_tree_add_item(evrc_tree, hf_evrc_interleave_length, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(evrc_tree, hf_evrc_interleave_index, tvb, offset, 1, ENC_BIG_ENDIAN);

        offset++;

        proto_tree_add_item(evrc_tree, hf_mode_request, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(evrc_tree, hf_evrc_frame_count, tvb, offset, 1, ENC_BIG_ENDIAN);

        /*
         * number of frames in PACKET is frame_count + 1
         */
        frame_count = (tvb_get_guint8(tvb, offset) & 0x1f) + 1;

        offset++;
        saved_offset = offset;

        item =
            proto_tree_add_text(evrc_tree, tvb, offset, -1, "ToC - %u frame%s",
                frame_count, plurality(frame_count, "", "s"));

        toc_tree = proto_item_add_subtree(item, ett_toc);

        i = 0;
        while ((i < frame_count) &&
            ((len - offset) > 0))
        {
            oct = tvb_get_guint8(tvb, offset);

            proto_tree_add_item(toc_tree, hf_toc_frame_type_high, tvb, offset, 1, ENC_BIG_ENDIAN);

            speech_data_len[i] = evrc_frame_type_to_octs((guint8)((oct & 0xf0) >> 4));

            i++;

            if (i < frame_count)
            {
                /* even number of frames */
                proto_tree_add_item(toc_tree, hf_toc_frame_type_low, tvb, offset, 1, ENC_BIG_ENDIAN);

                speech_data_len[i] = evrc_frame_type_to_octs((guint8)(oct & 0x0f));

                i++;
            }

            offset++;
        }

        if (frame_count & 0x01)
        {
            /* odd number of frames */
            proto_tree_add_item(toc_tree, hf_evrc_padding, tvb, offset-1, 1, ENC_BIG_ENDIAN);
        }

        proto_item_set_len(item, offset - saved_offset);
    }

    i = 0;
    while ((i < frame_count) &&
        ((len - offset) >= speech_data_len[i]))
    {
        proto_tree_add_text(evrc_tree, tvb, offset, speech_data_len[i], "Speech Data [%u]", i+1);

        offset += speech_data_len[i];
        i++;
    }
}
Example #25
0
/* Decode REG-RSP messages. */
static void dissect_mac_mgmt_msg_reg_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint offset = 0;
	guint tlv_offset;
	guint tvb_len;
	proto_item *reg_rsp_item;
	proto_tree *reg_rsp_tree;
	proto_item *tlv_item = NULL;
	proto_tree *tlv_tree = NULL;
	proto_tree *sub_tree = NULL;
	gboolean hmac_found = FALSE;
	tlv_info_t tlv_info;
	gint tlv_type;
	guint tlv_len;
	guint this_offset = 0;
	tlv_info_t sub_tlv_info;
	gint sub_tlv_type;
	gint sub_tlv_len;
	guint sub_tlv_offset;

	{	/* we are being asked for details */

		/* Get the tvb reported length */
		tvb_len =  tvb_reported_length(tvb);
		/* display MAC payload type REG-RSP */
		reg_rsp_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tvb_len, "MAC Management Message, REG-RSP");
		/* add MAC REG-RSP subtree */
		reg_rsp_tree = proto_item_add_subtree(reg_rsp_item, ett_mac_mgmt_msg_reg_rsp_decoder);
		proto_tree_add_item(reg_rsp_tree, hf_reg_rsp_status, tvb, offset, 1, ENC_BIG_ENDIAN);
		offset += 1;

		while (offset < tvb_len)
		{
			/* Get the TLV data. */
			init_tlv_info(&tlv_info, tvb, offset);
			/* get the TLV type */
			tlv_type = get_tlv_type(&tlv_info);
			/* get the TLV length */
			tlv_len = get_tlv_length(&tlv_info);
			if (tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1)
			{	/* invalid tlv info */
				col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REG-RSP TLV error");
				proto_tree_add_item(reg_rsp_tree, hf_reg_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA);
				break;
			}
			/* get the offset to the TLV data */
			tlv_offset = offset + get_tlv_value_offset(&tlv_info);

			switch (tlv_type) {
				case REG_ARQ_PARAMETERS:
				case REG_SS_MGMT_SUPPORT:
				case REG_IP_MGMT_MODE:
				case REG_IP_VERSION:
				case REG_UL_TRANSPORT_CIDS_SUPPORTED:
				case REG_IP_PHS_SDU_ENCAP:
				case REG_MAX_CLASSIFIERS_SUPPORTED:
				case REG_PHS_SUPPORT:
				case REG_ARQ_SUPPORT:
				case REG_DSX_FLOW_CONTROL:
				case REG_MCA_FLOW_CONTROL:
				case REG_MCAST_POLLING_CIDS:
				case REG_NUM_DL_TRANS_CID:
				case REG_MAC_ADDRESS:
#ifdef WIMAX_16E_2005
				case REG_TLV_T_20_MAX_MAC_DATA_PER_FRAME_SUPPORT:
				case REG_TLV_T_21_PACKING_SUPPORT:
				case REG_TLV_T_22_MAC_EXTENDED_RTPS_SUPPORT:
				case REG_TLV_T_23_MAX_NUM_BURSTS_TRANSMITTED_CONCURRENTLY_TO_THE_MS:
				case REG_TLV_T_26_METHOD_FOR_ALLOCATING_IP_ADDR_SECONDARY_MGMNT_CONNECTION:
				case REG_TLV_T_27_HANDOVER_SUPPORTED:
				case REG_TLV_T_29_HO_PROCESS_OPTIMIZATION_MS_TIMER:
				case REG_TLV_T_31_MOBILITY_FEATURES_SUPPORTED:
				case REG_TLV_T_40_ARQ_ACK_TYPE:
				case REG_TLV_T_41_MS_HO_CONNECTIONS_PARAM_PROCESSING_TIME:
				case REG_TLV_T_42_MS_HO_TEK_PROCESSING_TIME:
				case REG_TLV_T_43_MAC_HEADER_AND_EXTENDED_SUBHEADER_SUPPORT:
				case REG_POWER_SAVING_CLASS_CAPABILITY:
#endif
					dissect_extended_tlv(reg_rsp_tree, tlv_type, tvb, tlv_offset, tlv_len, pinfo, offset, proto_mac_mgmt_msg_reg_rsp_decoder);
					break;
				case REG_RSP_SECONDARY_MGMT_CID:
					add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_reg_rsp_secondary_mgmt_cid, tvb, offset, ENC_BIG_ENDIAN);
					break;

				case REG_RSP_TLV_T_36_TOTAL_PROVISIONED_SERVICE_FLOW_DSAs:
					add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_reg_total_provisioned_sf, tvb, offset, ENC_BIG_ENDIAN);
					break;

				case REG_RSP_TLV_T_24_CID_UPDATE_ENCODINGS:
					/* Display CID update encodings */
					/* add subtree */
					sub_tree = add_protocol_subtree(&tlv_info, ett_reg_rsp_message_tree, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "CID update encodings");
					/* Use a local copy of tlv_offset */
					this_offset = tlv_offset;
					while(this_offset < tlv_len) {
						/* Get the sub TLV data. */
						init_tlv_info(&sub_tlv_info, tvb, this_offset);
						/* get the sub TLV type */
						sub_tlv_type = get_tlv_type(&sub_tlv_info);
						/* get the TLV length */
						sub_tlv_len = get_tlv_length(&sub_tlv_info);
						if (tlv_type == -1 || sub_tlv_len > MAX_TLV_LEN || sub_tlv_len < 1)
						{	/* invalid tlv info */
							col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REG-RSP TLV error");
							proto_tree_add_item(reg_rsp_tree, hf_reg_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA);
							break;
						}
						/* get the offset to the sub TLV data */
						sub_tlv_offset = this_offset + get_tlv_value_offset(&sub_tlv_info);
						switch (sub_tlv_type) {
							case REG_RSP_TLV_T_24_1_CID_UPDATE_ENCODINGS_NEW_CID:
								add_tlv_subtree(&sub_tlv_info, sub_tree, hf_reg_rsp_new_cid_after_ho, tvb, this_offset, ENC_BIG_ENDIAN);
								break;
							case REG_RSP_TLV_T_24_2_CID_UPDATE_ENCODINGS_SFID:
								add_tlv_subtree(&sub_tlv_info, sub_tree, hf_reg_rsp_service_flow_id, tvb, this_offset, ENC_BIG_ENDIAN);
								break;
							case REG_RSP_TLV_T_24_3_CID_UPDATE_ENCODINGS_CONNECTION_INFO:
								tlv_tree = add_protocol_subtree(&sub_tlv_info, ett_reg_rsp_message_tree, sub_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, this_offset, sub_tlv_len, "CID Update Encodings Connection Info");
								/* Decode the DSC_RSP subTLV's */
								call_dissector(dsc_rsp_handle, tvb_new_subset_length(tvb, sub_tlv_offset, sub_tlv_len), pinfo, tlv_tree);
								break;
							default:
								add_tlv_subtree(&sub_tlv_info, sub_tree, hf_tlv_type, tvb, this_offset, ENC_NA);
								break;
						}
						this_offset = sub_tlv_len + sub_tlv_offset;
					}
					break;
				case REG_RSP_TLV_T_28_HO_SYSTEM_RESOURCE_RETAIN_TIME:
					tlv_item = add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_reg_rsp_system_resource_retain_time, tvb, offset, ENC_BIG_ENDIAN);
					if (include_cor2_changes) {
						proto_item_append_text(tlv_item, " (in units of 100 milliseconds)");
					} else {
						proto_item_append_text(tlv_item, " (multiple of 100 milliseconds)");
					}
					break;
				case DSx_UPLINK_FLOW:
					/* display Uplink Service Flow Encodings info */
					/* add subtree */
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "Uplink Service Flow Encodings");
					/* decode and display the DL Service Flow Encodings */
					wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, tlv_tree);
					break;
				case DSx_DOWNLINK_FLOW:
					/* display Downlink Service Flow Encodings info */
					/* add subtree */
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "Downlink Service Flow Encodings");
					/* decode and display the DL Service Flow Encodings */
					wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, tlv_tree);
					break;
				case HMAC_TUPLE:	/* Table 348d */
					/* decode and display the HMAC Tuple */
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "HMAC Tuple");
					wimax_hmac_tuple_decoder(tlv_tree, tvb, offset+2, tlv_len);
					hmac_found = TRUE;
					break;
				case CMAC_TUPLE:	/* Table 348b */
					/* decode and display the CMAC Tuple */
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "CMAC Tuple");
					wimax_cmac_tuple_decoder(tlv_tree, tvb, offset+2, tlv_len);
					break;
				case SHORT_HMAC_TUPLE:
				case SHORT_HMAC_TUPLE_COR2:
					if ((!include_cor2_changes && (tlv_type == SHORT_HMAC_TUPLE)) ||
						(include_cor2_changes && (tlv_type == SHORT_HMAC_TUPLE_COR2))) {
						/* decode and display the Short HMAC Tuple */
						tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "Short HMAC Tuple");
						wimax_short_hmac_tuple_decoder(tlv_tree, tvb, tlv_offset, tlv_len);
					} else {
						/* Unknown TLV Type */
						add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_tlv_type, tvb, offset, ENC_NA);
					}
					break;
				case VENDOR_SPECIFIC_INFO:
				case VENDOR_ID_ENCODING:
				case MAC_VERSION_ENCODING:
					wimax_common_tlv_encoding_decoder(tvb_new_subset_length(tvb, offset, (tvb_len - offset)), pinfo, reg_rsp_tree);
					break;
				default:
					add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_tlv_type, tvb, offset, ENC_NA);
					break;
			}

			offset = tlv_len + tlv_offset;
		}	/* end of TLV process while loop */
		if (!hmac_found)
			proto_item_append_text(reg_rsp_tree, " (HMAC Tuple is missing !)");
	}
}
Example #26
0
/*
 * Add an Ethernet trailer - which, for some captures, might be the FCS
 * rather than a pad-to-60-bytes trailer.
 *
 * If fcs_len is 0, we assume the frame has no FCS; if it's 4, we assume
 * it has an FCS; if it's anything else (such as -1, which means "maybe
 * it does, maybe it doesn't"), we try to infer whether it has an FCS.
 */
void
add_ethernet_trailer(packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
    int trailer_id, tvbuff_t *tvb, tvbuff_t *trailer_tvb, int fcs_len)
{
  /* If there're some bytes left over, it could be a combination of:
     - padding to meet the minimum 64 byte frame length
     - an FCS, if present (if fcs_len is 0, we know it's not present;
       if fcs_len is 4, we know it's present; if fcs_len is -1, we
       need some heuristics to determine whether it's present)
     - information inserted by TAPs or other network monitoring equipment.

     If we don't know whether the FCS is present, then, if we don't have a
     network monitoring trailer, and if the Ethernet frame was claimed to
     have had 64 or more bytes - i.e., it was at least an FCS worth of data
     longer than the minimum payload size - we could assume the last 4 bytes
     of the trailer are an FCS. */
  proto_item *item;
  proto_tree *checksum_tree;
  heur_dtbl_entry_t *hdtbl_entry;

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

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

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

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

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

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

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

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

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

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

    if (has_fcs) {
      guint32 sent_fcs = tvb_get_ntohl(trailer_tvb, padding_length+trailer_length);
      if(eth_check_fcs){
        guint32 fcs = crc32_802_tvb(tvb, tvb_captured_length(tvb) - 4);
        if (fcs == sent_fcs) {
          item = proto_tree_add_uint_format_value(fh_tree, hf_eth_fcs, trailer_tvb,
                                            padding_length+trailer_length, 4, sent_fcs,
                                            "0x%08x [correct]", sent_fcs);
          checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                        padding_length+trailer_length, 4, TRUE);
          PROTO_ITEM_SET_GENERATED(item);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                        padding_length+trailer_length, 4, FALSE);
          PROTO_ITEM_SET_GENERATED(item);
        } else {
          item = proto_tree_add_uint_format_value(fh_tree, hf_eth_fcs, trailer_tvb,
                                            padding_length+trailer_length, 4, sent_fcs,
                                            "0x%08x [incorrect, should be 0x%08x]",
                                            sent_fcs, fcs);
          checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                        padding_length+trailer_length, 4, FALSE);
          PROTO_ITEM_SET_GENERATED(item);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                        padding_length+trailer_length, 4, TRUE);
          PROTO_ITEM_SET_GENERATED(item);
          expert_add_info(pinfo, item, &ei_eth_fcs_bad);
          col_append_str(pinfo->cinfo, COL_INFO, " [ETHERNET FRAME CHECK SEQUENCE INCORRECT]");
        }
      }else{
        item = proto_tree_add_uint_format_value(fh_tree, hf_eth_fcs, trailer_tvb,
                                          padding_length+trailer_length, 4, sent_fcs,
                                          "0x%08x [validiation disabled]", sent_fcs);
        checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
        item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                      padding_length+trailer_length, 4, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
        item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                      padding_length+trailer_length, 4, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
      }
      trailer_length += 4;
    }
    proto_tree_set_appendix(fh_tree, tvb, tvb_captured_length(tvb) - padding_length - trailer_length, padding_length + trailer_length);
  }
}
Example #27
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;

            case 0x24: /* National Language Single Shift */
                if (len == 1) {
                    subtree = proto_item_add_subtree(subtree, ett_udh_ie);
                    proto_tree_add_item(subtree,
                            hf_gsm_sms_udh_national_single_shift,
                            tvb, i++, 1, ENC_BIG_ENDIAN);
                } else {
                    proto_item_append_text(subtree, " - Invalid format!");
                    i += len;
                }
                break;

            case 0x25: /* National Language Locking Shift */
                if (len == 1) {
                    subtree = proto_item_add_subtree(subtree, ett_udh_ie);
                    proto_tree_add_item(subtree,
                            hf_gsm_sms_udh_national_locking_shift,
                            tvb, i++, 1, ENC_BIG_ENDIAN);
                } 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->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;
}
Example #28
0
						   parent_tree, remaining_length);
		}

		/* offset = data_offset + data_length; */
		break;
	}

	return;
}

static enum SMB_DIRECT_HDR_TYPE
is_smb_direct(tvbuff_t *tvb, packet_info *pinfo _U_)
{
	gboolean maybe_neg_req = FALSE;
	gboolean maybe_data = FALSE;
	guint len = tvb_reported_length(tvb);

	if (len < 20) {
		return SMB_DIRECT_HDR_UNKNOWN;
	}

	if (len == 32 &&
	    tvb_get_letohs(tvb, 0) == 0x0100 && /* min version */
	    tvb_get_letohs(tvb, 2) == 0x0100 && /* max version */
	    tvb_get_letohs(tvb, 4) == 0x0100 && /* negotiated version */
	    tvb_get_letohs(tvb, 6) == 0x0000)   /* reserved */
	{
		/* Negotiate Response */
		return SMB_DIRECT_HDR_NEG_REP;
	}
Example #29
0
static int dissect_pbb_addressblock(tvbuff_t *tvb, packet_info *pinfo, 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_expert_format(tree, pinfo, &ei_packetbb_error, 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_expert_format(tree, pinfo, &ei_packetbb_error, 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_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
          "address head length is too long");
      return tvb_reported_length(tvb);
    }
    if (maxoffset - offset < head_length) {
      proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, 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_expert_format(tree, pinfo, &ei_packetbb_error, 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_expert_format(tree, pinfo, &ei_packetbb_error, 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_expert_format(tree, pinfo, &ei_packetbb_error, 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_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
          "address tail length is too long");
      return tvb_reported_length(tvb);
    }

    if (maxoffset - offset < tail_length) {
      proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, 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_expert_format(tree, pinfo, &ei_packetbb_error, 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, ENC_NA);
  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, ENC_BIG_ENDIAN);

  /* add flags */
  addrFlags_item = proto_tree_add_item(addr_tree, hf_packetbb_addr_flags, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
  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, ENC_BIG_ENDIAN);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasfulltail, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_haszerotail, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hassingleprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasmultiprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN);

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

  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, ENC_NA);
  }
  else if ((address_flags & ADDR_HASZEROTAIL) != 0) {
    /* add zero tail */
    proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, 1, ENC_NA);
  }
  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, (struct e_in6_addr *)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;
      case 3:
        addrValue_item = proto_tree_add_bytes(addr_tree, hf_packetbb_addr_value[addressType],
            tvb, mid_index, block_index + block_length - mid_index, addr);
        break;
      default:
        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, ENC_NA);

    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, ENC_BIG_ENDIAN);
    }
    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, ENC_BIG_ENDIAN);
    }
    proto_item_append_text(addrValue_item, "/%d", prefix);
  }

  offset = dissect_pbb_tlvblock(tvb, pinfo, addr_tree, block_index + block_length, maxoffset, numAddr);
  return offset;
}
Example #30
0
static void
dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto)
{
  proto_tree *udp_tree = NULL;
  proto_item *ti, *hidden_item, *port_item;
  guint      len;
  guint      reported_len;
  vec_t      cksum_vec[4];
  guint32    phdr[2];
  guint16    computed_cksum;
  int        offset = 0;
  e_udphdr *udph;
  proto_tree *checksum_tree;
  proto_item *item;
  conversation_t *conv = NULL;
  struct udp_analysis *udpd = NULL;
  proto_tree *process_tree;

  udph=ep_new(e_udphdr);
  SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
  SET_ADDRESS(&udph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);

  col_set_str(pinfo->cinfo, COL_PROTOCOL, (ip_proto == IP_PROTO_UDP) ? "UDP" : "UDPlite");
  col_clear(pinfo->cinfo, COL_INFO);

  udph->uh_sport=tvb_get_ntohs(tvb, offset);
  udph->uh_dport=tvb_get_ntohs(tvb, offset+2);

  col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s  Destination port: %s",
    get_udp_port(udph->uh_sport), get_udp_port(udph->uh_dport));

  if (tree) {
    if (udp_summary_in_tree) {
      if (ip_proto == IP_PROTO_UDP) {
        ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8,
        "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
        get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport);
      } else {
        ti = proto_tree_add_protocol_format(tree, proto_udplite, tvb, offset, 8,
        "Lightweight User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
        get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport);
      }
    } else {
      ti = proto_tree_add_item(tree, (ip_proto == IP_PROTO_UDP) ? proto_udp : proto_udplite, tvb, offset, 8, ENC_NA);
    }
    udp_tree = proto_item_add_subtree(ti, ett_udp);

    port_item = proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, udph->uh_sport,
	"Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport);
    /* The beginning port number, 32768 + 666 (33434), is from LBL's traceroute.c source code and this code
     * further assumes that 3 attempts are made per hop */
    if(udph->uh_sport > 32768 + 666 && udph->uh_sport <= 32768 + 666 + 30)
	    expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u",
				   ((udph->uh_sport - 32768 - 666 - 1) / 3) + 1,
				   ((udph->uh_sport - 32768 - 666 - 1) % 3) + 1
				   );

    port_item = proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport,
	"Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport);
    if(udph->uh_dport > 32768 + 666 && udph->uh_dport <= 32768 + 666 + 30)
	    expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u",
				   ((udph->uh_dport - 32768 - 666 - 1) / 3) + 1,
				   ((udph->uh_dport - 32768 - 666 - 1) % 3) + 1
				   );

    hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
    hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
  }

  if (ip_proto == IP_PROTO_UDP) {
    udph->uh_ulen = udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4);
    if (udph->uh_ulen < 8) {
      /* Bogus length - it includes the header, so it must be >= 8. */
      /* XXX - should handle IPv6 UDP jumbograms (RFC 2675), where the length is zero */
      item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2,
          udph->uh_ulen, "Length: %u (bogus, must be >= 8)", udph->uh_ulen);
      expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u < 8", udph->uh_ulen);
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u < 8]", udph->uh_ulen);
      return;
    }
    if ((udph->uh_ulen > tvb_reported_length(tvb)) && ! pinfo->fragmented && ! pinfo->flags.in_error_pkt) {
      /* Bogus length - it goes past the end of the IP payload */
      item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2,
          udph->uh_ulen, "Length: %u (bogus, payload length %u)", udph->uh_ulen, tvb_reported_length(tvb));
      expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u > IP payload length", udph->uh_ulen);
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u > IP PAYLOAD LENGTH]", udph->uh_ulen);
    } else {
      if (tree) {
        proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen);
        /* XXX - why is this here, given that this is UDP, not Lightweight UDP? */
        hidden_item = proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4,
                                          0, udph->uh_sum_cov);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
      }
    }
  } else {
    udph->uh_ulen = pinfo->iplen - pinfo->iphdrlen;
    udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4);
    if (((udph->uh_sum_cov > 0) && (udph->uh_sum_cov < 8)) || (udph->uh_sum_cov > udph->uh_ulen)) {
      /* Bogus length - it includes the header, so it must be >= 8, and no larger then the IP payload size. */
      if (tree) {
        hidden_item = proto_tree_add_boolean(udp_tree, hf_udplite_checksum_coverage_bad, tvb, offset + 4, 2, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
      }
      item = proto_tree_add_uint_format(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2,
          udph->uh_sum_cov, "Checksum coverage: %u (bogus, must be >= 8 and <= %u (ip.len-ip.hdr_len))",
          udph->uh_sum_cov, udph->uh_ulen);
      expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad checksum coverage length value %u < 8 or > %u",
                             udph->uh_sum_cov, udph->uh_ulen);
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD LIGHTWEIGHT UDP CHECKSUM COVERAGE LENGTH %u < 8 or > %u]",
                        udph->uh_sum_cov, udph->uh_ulen);
      if (!udplite_ignore_checksum_coverage)
        return;
    } else {
      if (tree) {
        hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov);
      }
    }
  }

  udph->uh_sum_cov = (udph->uh_sum_cov) ? udph->uh_sum_cov : udph->uh_ulen;
  udph->uh_sum = tvb_get_ntohs(tvb, offset+6);
  reported_len = tvb_reported_length(tvb);
  len = tvb_length(tvb);
  if (udph->uh_sum == 0) {
    /* No checksum supplied in the packet. */
    if ((ip_proto == IP_PROTO_UDP) && (pinfo->src.type == AT_IPv4)) {
      item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0,
        "Checksum: 0x%04x (none)", 0);

      checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
    } else {
      item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0,
        "Checksum: 0x%04x (Illegal)", 0);
      expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Illegal Checksum value (0)");
      col_append_fstr(pinfo->cinfo, COL_INFO, " [ILLEGAL CHECKSUM (0)]");

      checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, TRUE);
      PROTO_ITEM_SET_GENERATED(item);
    }
  } else if (!pinfo->fragmented && len >= reported_len &&
             len >= udph->uh_sum_cov && reported_len >= udph->uh_sum_cov &&
             udph->uh_sum_cov >=8) {
    /* The packet isn't part of a fragmented datagram and isn't
       truncated, so we can checksum it.
       XXX - make a bigger scatter-gather list once we do fragment
       reassembly? */

    if (((ip_proto == IP_PROTO_UDP) && (udp_check_checksum)) ||
        ((ip_proto == IP_PROTO_UDPLITE) && (udplite_check_checksum))) {
      /* Set up the fields of the pseudo-header. */
      cksum_vec[0].ptr = (const guint8 *)pinfo->src.data;
      cksum_vec[0].len = pinfo->src.len;
      cksum_vec[1].ptr = (const guint8 *)pinfo->dst.data;
      cksum_vec[1].len = pinfo->dst.len;
      cksum_vec[2].ptr = (const guint8 *)&phdr;
      switch (pinfo->src.type) {

      case AT_IPv4:
        if (ip_proto == IP_PROTO_UDP)
          phdr[0] = g_htonl((ip_proto<<16) | udph->uh_ulen);
	else
          phdr[0] = g_htonl((ip_proto<<16) | reported_len);
        cksum_vec[2].len = 4;
        break;

      case AT_IPv6:
        if (ip_proto == IP_PROTO_UDP)
          phdr[0] = g_htonl(udph->uh_ulen);
	else
          phdr[0] = g_htonl(reported_len);
        phdr[1] = g_htonl(ip_proto);
        cksum_vec[2].len = 8;
        break;

      default:
        /* UDP runs only atop IPv4 and IPv6.... */
        DISSECTOR_ASSERT_NOT_REACHED();
        break;
      }
      cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, udph->uh_sum_cov);
      cksum_vec[3].len = udph->uh_sum_cov;
      computed_cksum = in_cksum(&cksum_vec[0], 4);
      if (computed_cksum == 0) {
        item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
          offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [correct]", udph->uh_sum);

        checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                                      offset + 6, 2, TRUE);
        PROTO_ITEM_SET_GENERATED(item);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                                      offset + 6, 2, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
      } else {
        item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
                                          offset + 6, 2, udph->uh_sum,
          "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"UDP checksum offload\"?)]", udph->uh_sum,
          in_cksum_shouldbe(udph->uh_sum, computed_cksum));

        checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                                      offset + 6, 2, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                                      offset + 6, 2, TRUE);
        PROTO_ITEM_SET_GENERATED(item);
        expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");

        col_append_fstr(pinfo->cinfo, COL_INFO, " [UDP CHECKSUM INCORRECT]");
      }
    } else {
      item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
        offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [validation disabled]", udph->uh_sum);
      checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
    }
  } else {
    item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
      offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [unchecked, not all data available]", udph->uh_sum);

    checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
    item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
    PROTO_ITEM_SET_GENERATED(item);
    item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, FALSE);
    PROTO_ITEM_SET_GENERATED(item);
  }

  /* Skip over header */
  offset += 8;

  pinfo->ptype = PT_UDP;
  pinfo->srcport = udph->uh_sport;
  pinfo->destport = udph->uh_dport;

  tap_queue_packet(udp_tap, pinfo, udph);

  /* find(or create if needed) the conversation for this udp session */
  if (udp_process_info) {
    conv=find_or_create_conversation(pinfo);
    udpd=get_udp_conversation_data(conv,pinfo);
  }

  if (udpd && ((udpd->fwd && udpd->fwd->command) || (udpd->rev && udpd->rev->command))) {
    ti = proto_tree_add_text(udp_tree, tvb, offset, 0, "Process Information");
	PROTO_ITEM_SET_GENERATED(ti);
    process_tree = proto_item_add_subtree(ti, ett_udp_process_info);
	if (udpd->fwd && udpd->fwd->command) {
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_uid, tvb, 0, 0,
              udpd->fwd->process_uid, "%u", udpd->fwd->process_uid);
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_pid, tvb, 0, 0,
              udpd->fwd->process_pid, "%u", udpd->fwd->process_pid);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_uname, tvb, 0, 0,
              udpd->fwd->username, "%s", udpd->fwd->username);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_cmd, tvb, 0, 0,
              udpd->fwd->command, "%s", udpd->fwd->command);
    }
    if (udpd->rev->command) {
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_uid, tvb, 0, 0,
              udpd->rev->process_uid, "%u", udpd->rev->process_uid);
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_pid, tvb, 0, 0,
              udpd->rev->process_pid, "%u", udpd->rev->process_pid);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_uname, tvb, 0, 0,
              udpd->rev->username, "%s", udpd->rev->username);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_cmd, tvb, 0, 0,
              udpd->rev->command, "%s", udpd->rev->command);
    }
  }

  /*
   * Call sub-dissectors.
   *
   * XXX - should we do this if this is included in an error packet?
   * It might be nice to see the details of the packet that caused the
   * ICMP error, but it might not be nice to have the dissector update
   * state based on it.
   * Also, we probably don't want to run UDP taps on those packets.
   *
   * We definitely don't want to do it for an error packet if there's
   * nothing left in the packet.
   */
  if (!pinfo->flags.in_error_pkt || tvb_length_remaining(tvb, offset) > 0)
    decode_udp_ports(tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport,
                     udph->uh_ulen);
}