Esempio n. 1
0
/* 
 * This function dissects an "Ice facet", adds hf(s) to "tree" and returns consumed 
 * bytes in "*consumed", if errors "*consumed" is -1.
 */
static void dissect_ice_facet(proto_tree *tree, int hf_icep, 
			      tvbuff_t *tvb, guint32 offset, gint32 *consumed)
{
	/*  p. 588, chapter 23.2.6:
	 *  "facet" is a StringSeq, a StringSeq is a:                
	 *  sequence<string>
	 *
	 *
	 * sequence == Size + SizeElements 
	 * sequence = 1byte (0..254) + SizeElements 
	 * or                                                      
	 * sequence = 1byte (255) + 1int (255..2^32-1) + SizeElements 
	 *
	 *
	 * p.613. chapter 23.3.2
	 * "facet has either zero elements (empty) or one element"
	 *
	 *	 
	 */
	
	guint32 Size = 0; /* number of elements in the sequence */
	char *s = NULL;
	
	(*consumed) = 0;
	
	/* check first byte */
	if ( !tvb_bytes_exist(tvb, offset, 1) ) {
		
		if (tree)
			proto_tree_add_text(tree, tvb, offset, -1, "facet field missing");
		
		if ( check_col(mypinfo->cinfo, COL_INFO) ) {
			col_append_str(mypinfo->cinfo, COL_INFO, 
				       " (facet field missing)");
		}
		
		(*consumed) = -1;
		return;
	}
	
	/* get first byte of Size */
	Size = tvb_get_guint8(tvb, offset);
	offset++;
	(*consumed)++;
	
	if ( Size == 0 ) {
		
		if (tree) {
			s = ep_strdup( "(empty)" );
			/* display the 0x00 Size byte when click on a empty ice_string */
			proto_tree_add_string(tree, hf_icep, tvb, offset - 1, 1, s);
		}
		return;
	}
	
	if ( Size == 1 ) {
		
		gint32 consumed_facet = 0;
		
		dissect_ice_string(tree, hf_icep, tvb, offset, &consumed_facet, NULL, TRUE);
		
		if ( consumed_facet == -1 ) {
			(*consumed) = -1;
			return;
		}
		
		offset += consumed_facet;
		(*consumed) += consumed_facet;
		return;
	}
	
	/* if here => Size > 1 => not possible */
	
	if (tree)
		/* display the XX Size byte when click here */
		proto_tree_add_text(tree, tvb, offset - 1, 1, 
				    "facet can be max one element");
	
	if ( check_col(mypinfo->cinfo, COL_INFO) ) {
		col_append_str(mypinfo->cinfo, COL_INFO, 
			       " (facet can be max one element)");
	}
	
	(*consumed) = -1;
	return;
}
Esempio n. 2
0
static gboolean
dissect_dcc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree      *dcc_tree, *dcc_optree, *dcc_opnumtree, *ti;
	proto_tree *dcc_tracetree;
	proto_item *hidden_item;
	int offset = 0;
	int client_is_le = 0;
	int op = 0;
	int i, is_response;

	if (pinfo->srcport != DCC_PORT && pinfo->destport != DCC_PORT) {
		/* Not the right port - not a DCC packet. */
		return FALSE;
	}

	/* get at least a full packet structure */
	if ( tvb_length(tvb) < sizeof(DCC_HDR) ) {
		/* Doesn't have enough bytes to contain packet header. */
		return FALSE;
	}

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

	offset = 0;
	is_response = pinfo->srcport == DCC_PORT;

	if (check_col(pinfo->cinfo, COL_INFO)) {
		col_add_fstr(pinfo->cinfo, COL_INFO,
			"%s: %s",
			is_response ? "Response" : "Request",
			val_to_str(tvb_get_guint8(tvb, offset+3),
				 dcc_op_vals, "Unknown Op: %u")
		);
	}

	if (tree) {
		ti = proto_tree_add_item(tree, proto_dcc, tvb, offset, -1,
			FALSE);
		dcc_tree = proto_item_add_subtree(ti, ett_dcc);

		proto_tree_add_item(dcc_tree, hf_dcc_len, tvb,
			offset, 2, FALSE);

		if ( tvb_length(tvb) < tvb_get_ntohs(tvb, offset)) {
			/* Doesn't have number of bytes that header claims. */
			proto_tree_add_text(dcc_tree, tvb, offset, 2, "Error - packet is shorter than header claims!");
		}
		offset += 2;

		proto_tree_add_item(dcc_tree, hf_dcc_pkt_vers, tvb,
			offset, 1, FALSE);
		offset += 1;

		op = tvb_get_guint8(tvb, offset);
		proto_tree_add_item(dcc_tree, hf_dcc_op, tvb,
			offset, 1, FALSE);
		offset += 1;

		proto_tree_add_item(dcc_tree, hf_dcc_clientid, tvb,
			offset, 4, FALSE);
		offset += 4;

		ti = proto_tree_add_text(dcc_tree, tvb, offset, -1, "Operation Numbers (Opaque to Server)");
		dcc_opnumtree = proto_item_add_subtree(ti, ett_dcc_opnums);

		/* Note - these are indeterminate - they are sortof considered opaque to the client */
		/* Make some attempt to figure out if this data is little endian, not guaranteed to be
		correct if connection went through a firewall or similar. */

		/* Very hokey check - if all three of pid/report/retrans look like little-endian
			numbers, host is probably little endian. Probably innacurate on super-heavily-used
			DCC clients though. This should be good enough for now. */
		client_is_le = ( (tvb_get_guint8(tvb, offset+4) | tvb_get_guint8(tvb, offset+4)) &&
						 (tvb_get_guint8(tvb, offset+8) | tvb_get_guint8(tvb, offset+9)) &&
						 (tvb_get_guint8(tvb, offset+12) | tvb_get_guint8(tvb, offset+13)) );

		proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_host, tvb,
			offset, 4, client_is_le);
		offset += 4;

		proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_pid, tvb,
			offset, 4, client_is_le);
		offset += 4;

		proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_report, tvb,
			offset, 4, client_is_le);
		offset += 4;

		proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_retrans, tvb,
			offset, 4, client_is_le);
		offset += 4;

		ti = proto_tree_add_text(dcc_tree, tvb, offset, -1, "Operation: %s",
			val_to_str(op, dcc_op_vals, "Unknown Op: %u"));
		dcc_optree = proto_item_add_subtree(ti, ett_dcc_op);

		switch(op) {
			case DCC_OP_NOP:
				D_SIGNATURE();
				break;

			case DCC_OP_REPORT:
				D_TARGET();
				for (i=0; i<=DCC_QUERY_MAX &&
					tvb_bytes_exist(tvb, offset+sizeof(DCC_SIGNATURE),1); i++)
				{
					D_CHECKSUM();
				}
				D_SIGNATURE();
				break;

			case DCC_OP_QUERY_RESP:
				for (i=0; i<=DCC_QUERY_MAX &&
					tvb_bytes_exist(tvb, offset+sizeof(DCC_SIGNATURE),1); i++)
				{
					D_TARGET();
				}
				D_SIGNATURE();
				break;

			case DCC_OP_ADMN:
				if ( is_response )
				{
					int left_local = tvb_length_remaining(tvb, offset) -
						sizeof(DCC_SIGNATURE);
					if ( left_local == sizeof(DCC_ADMN_RESP_CLIENTS) )
					{
						D_LABEL("Addr", 16);
						D_LABEL("Id", sizeof(DCC_CLNT_ID));
						D_LABEL("Last Used", 4);
						D_LABEL("Requests", 4);
					}
					else
					{
						D_TEXT("Response Text", sizeof(DCC_SIGNATURE));
					}
					D_SIGNATURE();
				}
				else
				{
					int aop;

					D_DATE();

					aop = tvb_get_guint8(tvb, offset+4);
					proto_tree_add_item(dcc_optree, hf_dcc_adminop, tvb, offset+4,
						1, FALSE);
					if (check_col(pinfo->cinfo, COL_INFO)) {
						col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
							val_to_str(tvb_get_guint8(tvb,offset+4),
							dcc_adminop_vals, "Unknown (%u)"));
					}

					if (aop == DCC_AOP_TRACE_ON || aop == DCC_AOP_TRACE_OFF )
					{
						ti = proto_tree_add_item(dcc_optree, hf_dcc_trace, tvb, offset,
							4, FALSE);
						dcc_tracetree = proto_item_add_subtree(ti, ett_dcc_trace);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_admin, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_anon, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_client, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_rlim, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_query, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_ridc, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_flood, tvb, offset, 4, FALSE);
					}
					else if ( aop == DCC_AOP_FLOD )
					{
						proto_tree_add_item(dcc_optree, hf_dcc_floodop,
							tvb, offset, 4, FALSE);
						if (check_col(pinfo->cinfo, COL_INFO)) {
							col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
								val_to_str(tvb_get_ntohl(tvb,offset),
								dcc_floodop_vals, "Unknown (%u)"));
						}
					}
					else
					{
						proto_tree_add_item(dcc_optree, hf_dcc_adminval,
							tvb, offset, 4, FALSE);
					}
					offset += 4;

					offset += 1; /* admin op we did in reverse order */
					D_LABEL("Pad", 3);
					D_SIGNATURE();
				}
				break;

			case DCC_OP_OK:
				proto_tree_add_item(dcc_optree, hf_dcc_max_pkt_vers, tvb,
					offset, 1, FALSE);
				offset += 1;

				D_LABEL("Unused", 1);

				proto_tree_add_item(dcc_optree, hf_dcc_qdelay_ms, tvb,
					offset, 2, FALSE);
				offset += 2;

				proto_tree_add_item(dcc_optree, hf_dcc_brand, tvb,
					offset, sizeof(DCC_BRAND), FALSE);
				offset += sizeof(DCC_BRAND);

				D_SIGNATURE();
				break;

			default:
				/* do nothing */
				break;
		}
	}

	return TRUE;
}
Esempio n. 3
0
/****************************************************************
 * Main dissection function
 ****************************************************************/
static int
dissect_rlogin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
	struct tcpinfo *tcpinfo = (struct tcpinfo *)data;
	conversation_t *conversation;
	rlogin_hash_entry_t *hash_info;
	guint length;
	gint ti_offset;

	/* Get or create conversation */
	conversation = find_or_create_conversation(pinfo);

	/* Get or create data associated with this conversation */
	hash_info = (rlogin_hash_entry_t *)conversation_get_proto_data(conversation, proto_rlogin);
	if (!hash_info)
	{
		/* Populate new data struct... */
		hash_info = wmem_new(wmem_file_scope(), rlogin_hash_entry_t);
		hash_info->state = NONE;
		hash_info->info_framenum = 0;  /* no frame has the number 0 */
		hash_info->user_name[0] = '\0';

		/* ... and store in conversation */
		conversation_add_proto_data(conversation, proto_rlogin, hash_info);
	}

	/* Set protocol column text */
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "Rlogin");

	/* Set info column */
	/* Show user-name if available */
	if (hash_info->user_name[0])
	{
		col_add_fstr(pinfo->cinfo, COL_INFO,
		              "User name: %s, ", hash_info->user_name);
	}
	else
	{
		col_clear(pinfo->cinfo, COL_INFO);
	}

	/* Work out packet content summary for display */
	length = tvb_reported_length(tvb);
	if (length != 0)
	{
		/* Initial NULL byte represents part of connection handshake */
		if (tvb_get_guint8(tvb, 0) == '\0')
		{
			col_append_str(pinfo->cinfo, COL_INFO,
				               (pinfo->destport == RLOGIN_PORT) ?
				                   "Start Handshake" :
				                   "Startup info received");
		}
		else
		if (tcpinfo && IS_TH_URG(tcpinfo->flags) && length >= tcpinfo->urgent_pointer)
		{
			/* Urgent pointer inside current data represents a control message */
			col_append_str(pinfo->cinfo, COL_INFO, "Control Message");
		}
		else
		{
			/* Search for 2 consecutive ff bytes
			  (signifies window change control message) */
			ti_offset = tvb_find_guint8(tvb, 0, -1, 0xff);
			if (ti_offset != -1 &&
			    tvb_bytes_exist(tvb, ti_offset + 1, 1) &&
			    tvb_get_guint8(tvb, ti_offset + 1) == 0xff)
			{
				col_append_str(pinfo->cinfo, COL_INFO, "Terminal Info");
			}
			else
			{
				/* Show any text data in the frame */
				int bytes_to_copy = tvb_captured_length(tvb);
				if (bytes_to_copy > 128)
				{
					/* Truncate to 128 bytes for display */
					bytes_to_copy = 128;
				}

				/* Add data into info column */
				col_append_fstr(pinfo->cinfo, COL_INFO,
				                "Data: %s",
				                 tvb_format_text(tvb, 0, bytes_to_copy));
			}
		}
	}

	/* See if conversation state needs to be updated */
	rlogin_state_machine(hash_info, tvb, pinfo);

	/* Dissect in detail */
	rlogin_display(hash_info, tvb, pinfo, tree, tcpinfo);

	return tvb_captured_length(tvb);
}
Esempio n. 4
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);
    }
}
Esempio n. 5
0
/*
 * Optionally do reassembly of the request/response line, headers, and body.
 */
gboolean
req_resp_hdrs_do_reassembly(tvbuff_t *tvb, const int offset, packet_info *pinfo,
    const gboolean desegment_headers, const gboolean desegment_body)
{
	gint		next_offset;
	gint		next_offset_sav;
	gint		length_remaining, reported_length_remaining;
	int			linelen;
	gchar		*header_val;
	long int	content_length;
	gboolean	content_length_found = FALSE;
	gboolean	content_type_found = FALSE;
	gboolean	chunked_encoding = FALSE;
	gboolean	keepalive_found = FALSE;
	gchar		*line;
	gchar		*content_type = NULL;

	/*
	 * Do header desegmentation if we've been told to.
	 *
	 * RFC 2616 defines HTTP messages as being either of the
	 * Request or the Response type
	 * (HTTP-message = Request | Response).
	 * Request and Response are defined as:
	 *     Request = Request-Line
	 *         *(( general-header
	 *         | request-header
	 *         | entity-header ) CRLF)
	 *         CRLF
	 *         [ message-body ]
	 *     Response = Status-Line
	 *         *(( general-header
	 *         | response-header
	 *         | entity-header ) CRLF)
	 *         CRLF
	 *         [ message-body ]
	 * that's why we can always assume two consecutive line
	 * endings (we allow CR, LF, or CRLF, as some clients
	 * or servers might not use a full CRLF) to mark the end
	 * of the headers.  The worst thing that would happen
	 * otherwise would be the packet not being desegmented
	 * or being interpreted as only headers.
	 *
	 * RFC 2326 says RTSP works the same way; RFC 3261 says SIP
	 * works the same way.
	 */

	/*
	 * If header desegmentation is activated, check that all
	 * headers are in this tvbuff (search for an empty line
	 * marking end of headers) or request one more byte (we
	 * don't know how many bytes we'll need, so we just ask
	 * for one).
	 */
	if (desegment_headers && pinfo->can_desegment) {
		next_offset = offset;
		for (;;) {
			next_offset_sav = next_offset;

			reported_length_remaining =
			    tvb_reported_length_remaining(tvb, next_offset);

			/*
			 * Request one more byte if there're no
			 * bytes left in the reported data (if there're
			 * bytes left in the reported data, but not in
			 * the available data, requesting more bytes
			 * won't help, as those bytes weren't captured).
			 */
			if (reported_length_remaining < 1) {
				pinfo->desegment_offset = offset;
				pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
				return FALSE;
			}

			length_remaining = tvb_length_remaining(tvb,
			    next_offset);

			/*
			 * Request one more byte if we cannot find a
			 * header (i.e. a line end).
			 */
			linelen = tvb_find_line_end(tvb, next_offset,
			    -1, &next_offset, TRUE);
			if (linelen == -1 &&
			    length_remaining >= reported_length_remaining) {
				/*
				 * Not enough data; ask for one more
				 * byte.
				 */
				pinfo->desegment_offset = offset;
				pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
				return FALSE;
			}

                        if (linelen == 0) {
				/*
				 * We found the end of the headers.
				 */
				break;
			}

			/*
			 * Is this a Content-Length or Transfer-Encoding
			 * header?  If not, it either means that we are in
			 * a different header line, or that we are
			 * at the end of the headers, or that there
			 * isn't enough data; the two latter cases
			 * have already been handled above.
			 */
			if (desegment_body) {
				/*
				 * Check if we've found Content-Length.
				 */
				line = tvb_get_ephemeral_string(tvb, next_offset_sav, linelen);
				if (g_ascii_strncasecmp(line, "Content-Length:", 15) == 0) {
					if (sscanf(line+15,"%li", &content_length) == 1)
						content_length_found = TRUE;
				} else if (g_ascii_strncasecmp(line, "Content-Type:", 13) == 0) {
					content_type_found = TRUE;
					content_type = line+13;
					while (*content_type == ' ') {
						content_type++;
					}
				} else if (g_ascii_strncasecmp(line, "Connection:", 11) == 0) {
					/* Check for keep-alive */
					header_val = line+11;
					if(header_val){
						while(*header_val==' '){
							header_val++;
						}
						if(!g_ascii_strncasecmp(header_val, "Keep-Alive", 10)){
							keepalive_found = TRUE;
						}
					}
				} else if (g_ascii_strncasecmp( line, "Transfer-Encoding:", 18) == 0) {
					/*
					 * Find out if this Transfer-Encoding is
					 * chunked.  It should be, since there
					 * really aren't any other types, but
					 * RFC 2616 allows for them.
					 */
					gchar *p;
					guint len;

					header_val = line+18;
					p = header_val;
					len = (guint) strlen(header_val);
					/* Skip white space */
					while (p < header_val + len &&
					    (*p == ' ' || *p == '\t'))
						p++;
					if (p <= header_val + len) {
						if (g_ascii_strncasecmp(p, "chunked", 7)
						    == 0) {
							/*
							 * Don't bother looking
							 * for extensions;
							 * since we don't
							 * understand them,
							 * they should be
							 * ignored.
							 */
							chunked_encoding = TRUE;
						}
					}
				}
			}
		}
	}

	/*
	 * The above loop ends when we reached the end of the headers, so
	 * there should be content_length bytes after the 4 terminating bytes
	 * and next_offset points to after the end of the headers.
	 */
	if (desegment_body) {
		if (content_length_found) {
			if (content_length >= 128*1024) { /* MS-RPCH stipulate that the content-length must be between 128K and 2G */
				gchar *tmp;
				if (content_type_found &&
				strncmp(content_type, "application/rpc", 15) == 0) {
					/* It looks like a RPC_IN_DATA request or a RPC_OUT_DATA response
					 * in which the content-length is meaningless
					 */
					return TRUE;
				}
				/* Following sizeof will return the length of the string + \0 we need to not count it*/
				tmp = tvb_get_ephemeral_string(tvb, 0, sizeof("RPC_OUT_DATA") - 1);
				if ((strncmp(tmp, "RPC_IN_DATA", sizeof("RPC_IN_DATA") - 1) == 0) ||
				    (strncmp(tmp, "RPC_OUT_DATA", sizeof("RPC_OUT_DATA") - 1) == 0)) {
					return TRUE;
				}
			}
			/* next_offset has been set to the end of the headers */
			if (!tvb_bytes_exist(tvb, next_offset, content_length)) {
				length_remaining = tvb_length_remaining(tvb,
				    next_offset);
				reported_length_remaining =
				    tvb_reported_length_remaining(tvb, next_offset);
				if (length_remaining < reported_length_remaining) {
					/*
					 * It's a waste of time asking for more
					 * data, because that data wasn't captured.
					 */
					return TRUE;
				}
				if (length_remaining == -1)
					length_remaining = 0;
				pinfo->desegment_offset = offset;
				pinfo->desegment_len =
				    content_length - length_remaining;
				return FALSE;
			}
		} else if (chunked_encoding) {
			/*
			 * This data is chunked, so we need to keep pulling
			 * data until we reach the end of the stream, or a
			 * zero sized chunk.
			 *
			 * XXX
			 * This doesn't bother with trailing headers; I don't
			 * think they are really used, and we'd have to use
			 * is_http_request_or_reply() to determine if it was
			 * a trailing header, or the start of a new response.
			 */
			gboolean done_chunking = FALSE;

			while (!done_chunking) {
				guint chunk_size = 0;
				gint  chunk_offset = 0;
				gchar *chunk_string = NULL;
				gchar *c = NULL;

				reported_length_remaining =
				    tvb_reported_length_remaining(tvb,
				    next_offset);

				if (reported_length_remaining < 1) {
					pinfo->desegment_offset = offset;
					pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
					return FALSE;
				}

				length_remaining = tvb_length_remaining(tvb,
				    next_offset);

				linelen = tvb_find_line_end(tvb, next_offset,
						-1, &chunk_offset, TRUE);

				if (linelen == -1 &&
				    length_remaining >=
				    reported_length_remaining) {
					 pinfo->desegment_offset = offset;
					 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
					 return FALSE;
				}

				/* We have a line with the chunk size in it.*/
				chunk_string = tvb_get_ephemeral_string(tvb, next_offset,
				    linelen);
				c = chunk_string;

				/*
				 * We don't care about the extensions.
				 */
				if ((c = strchr(c, ';'))) {
					*c = '\0';
				}

				if (sscanf(chunk_string, "%x", &chunk_size) < 1) {
					/* We couldn't get the chunk size,
					 * so stop trying.
					 */
					return TRUE;
				}
				if (chunk_size > (guint)1<<31) {
					/* Chunk size is unreasonable. */
					/* XXX What /is/ reasonable? */
					return TRUE;
				}

				if (chunk_size == 0) {
					/*
					 * This is the last chunk.  Let's pull in the
					 * trailing CRLF.
					 */
					linelen = tvb_find_line_end(tvb,
					    chunk_offset, -1, &chunk_offset, TRUE);

					if (linelen == -1 &&
					    length_remaining >=
					    reported_length_remaining) {
						pinfo->desegment_offset = offset;
						pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
						return FALSE;
					}

					pinfo->desegment_offset = chunk_offset;
					pinfo->desegment_len = 0;
					done_chunking = TRUE;
				} else {
					/*
					 * Skip to the next chunk if we
					 * already have it
					 */
					if (reported_length_remaining >
					        (gint) chunk_size) {

						next_offset = chunk_offset
						    + chunk_size + 2;
					} else {
						/*
						 * Fetch this chunk, plus the
						 * trailing CRLF.
						 */
						pinfo->desegment_offset = offset;
						pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
						return FALSE;
					}
				}

			}
		} else if (content_type_found && pinfo->can_desegment) {
			/* We found a content-type but no content-length.
			 * This is probably a HTTP header for a session with
			 * only one HTTP PDU and where the content spans
			 * until the end of the tcp session, unless there
			 * is a keepalive header present in which case we
			 * assume there is no message body at all and thus
			 * we wont do any reassembly.
			 * Set up tcp reassembly until the end of this session.
			 */
			length_remaining = tvb_length_remaining(tvb, next_offset);
			reported_length_remaining = tvb_reported_length_remaining(tvb, next_offset);
			if (length_remaining < reported_length_remaining) {
				/*
				 * It's a waste of time asking for more
				 * data, because that data wasn't captured.
				 */
				return TRUE;
			}

			if (keepalive_found) {
				/* We have a keep-alive but no content-length.
				 * Assume there is no message body and dont
				 * do any reassembly.
				 */
				return TRUE;
			}

			pinfo->desegment_offset = offset;
			pinfo->desegment_len = DESEGMENT_UNTIL_FIN;

			return FALSE;
		}

	}

	/*
	 * No further desegmentation needed.
	 */
	return TRUE;
}
void dissect_nhrp_hdr(tvbuff_t *tvb,
					  packet_info *pinfo,
					  proto_tree *tree,
					  gint *pOffset,
					  gint *pMandLen,
					  gint *pExtLen,
					  oui_info_t **pOuiInfo,
					  e_nhrp_hdr *hdr)
{
	gint	offset = *pOffset;
	const gchar *pro_type_str;
	guint   total_len = tvb_reported_length(tvb);
	guint16	ipcsum, rx_chksum;

	proto_item *nhrp_tree_item = NULL;
	proto_tree *nhrp_tree = NULL;
	proto_item *shtl_tree_item = NULL;
	proto_tree *shtl_tree = NULL;
	proto_item *sstl_tree_item = NULL;
	proto_tree *sstl_tree = NULL;
	proto_item *ti;

	nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, 20, "NHRP Fixed Header");
	nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_hdr);

	hdr->ar_pktsz = tvb_get_ntohs(tvb, 10);
	if (total_len > hdr->ar_pktsz) {
		total_len = hdr->ar_pktsz;
	}

	hdr->ar_afn = tvb_get_ntohs(tvb, offset);
	proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_afn, tvb, offset, 2, FALSE);
	offset += 2;

	hdr->ar_pro_type = tvb_get_ntohs(tvb, offset);
	if (hdr->ar_pro_type <= 0xFF) {
		/* It's an NLPID */
		pro_type_str = val_to_str(hdr->ar_pro_type, nlpid_vals,
		    "Unknown NLPID");
	} else if (hdr->ar_pro_type <= 0x3FF) {
		/* Reserved for future use by the IETF */
		pro_type_str = "Reserved for future use by the IETF";
	} else if (hdr->ar_pro_type <= 0x04FF) {
		/* Allocated for use by the ATM Forum */
		pro_type_str = "Allocated for use by the ATM Forum";
	} else if (hdr->ar_pro_type <= 0x05FF) {
		/* Experimental/Local use */
		pro_type_str = "Experimental/Local use";
	} else {
		pro_type_str = val_to_str(hdr->ar_pro_type, etype_vals,
		    "Unknown Ethertype");
	}
	proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_pro_type, tvb, offset, 2,
	    hdr->ar_pro_type, "Protocol Type (short form): %s (0x%04x)",
	    pro_type_str, hdr->ar_pro_type);
	offset += 2;

	if (hdr->ar_pro_type == NLPID_SNAP) {
		/*
		 * The long form protocol type is a SNAP OUI and PID.
		 */
		hdr->ar_pro_type_oui = tvb_get_ntoh24(tvb, offset);
		proto_tree_add_uint(nhrp_tree, hf_nhrp_hdr_pro_snap_oui,
		    tvb, offset, 3, hdr->ar_pro_type_oui);
		offset += 3;

		hdr->ar_pro_type_pid = tvb_get_ntohs(tvb, offset);
		*pOuiInfo = get_snap_oui_info(hdr->ar_pro_type_oui);
		if (*pOuiInfo != NULL) {
			proto_tree_add_uint(nhrp_tree,
			    *(*pOuiInfo)->field_info->p_id,
			    tvb, offset, 2, hdr->ar_pro_type_pid);
		} else {
			proto_tree_add_uint(nhrp_tree, hf_nhrp_hdr_pro_snap_pid,
			    tvb, offset, 2, hdr->ar_pro_type_pid);
		}
	} else {
		/*
		 * XXX - we should check that this is zero, as RFC 2332
		 * says it should be zero.
		 */
		proto_tree_add_text(nhrp_tree, tvb, offset, 5,
						"Protocol Type (long form): %s",
						tvb_bytes_to_str(tvb, offset, 5));
		offset += 5;
	}

	proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_hopcnt, tvb, offset, 1, FALSE);
	offset += 1;

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

	rx_chksum = tvb_get_ntohs(tvb, offset);
	if (tvb_bytes_exist(tvb, 0, total_len)) {
		ipcsum = nhrp_checksum(tvb_get_ptr(tvb, 0, total_len),
		    total_len);
		if (ipcsum == 0) {
			proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_chksum, tvb, offset, 2, rx_chksum,
			    "NHRP Packet checksum: 0x%04x [correct]", rx_chksum);
		} else {
			proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_chksum, tvb, offset, 2, rx_chksum,
			    "NHRP Packet checksum: 0x%04x [incorrect, should be 0x%04x]", rx_chksum,
			    in_cksum_shouldbe(rx_chksum, ipcsum));
		}
	} else {
		proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_chksum, tvb, offset, 2, rx_chksum,
		    "NHRP Packet checksum: 0x%04x [not all data available]", rx_chksum);
	}
	offset += 2;

	hdr->ar_extoff = tvb_get_ntohs(tvb, offset);
	ti = proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_extoff, tvb, offset, 2, FALSE);
	if (hdr->ar_extoff != 0 && hdr->ar_extoff < 20) {
		expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
		    "Extension offset is less than the fixed header length");
	}
	offset += 2;

	hdr->ar_op_version = tvb_get_guint8(tvb, offset);
	proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_version, tvb, offset, 1,
		hdr->ar_op_version, "Version : %u (%s)", hdr->ar_op_version,
		(hdr->ar_op_version == 1) ? "NHRP - rfc2332" : "Unknown");
	offset += 1;
	proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_op_type, tvb, offset, 1, FALSE);
	offset += 1;

	hdr->ar_shtl = tvb_get_guint8(tvb, offset);
	shtl_tree_item = proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_shtl,
		tvb, offset, 1, hdr->ar_shtl, "Source Address Type/Len: %s/%u",
		val_to_str(NHRP_SHTL_TYPE(hdr->ar_shtl), nhrp_shtl_type_vals, "Unknown Type"),
		NHRP_SHTL_LEN(hdr->ar_shtl));
	shtl_tree = proto_item_add_subtree(shtl_tree_item, ett_nhrp_hdr_shtl);
	proto_tree_add_item(shtl_tree, hf_nhrp_hdr_shtl_type, tvb, offset, 1, FALSE);
	proto_tree_add_item(shtl_tree, hf_nhrp_hdr_shtl_len, tvb, offset, 1, FALSE);
	offset += 1;

	hdr->ar_sstl = tvb_get_guint8(tvb, offset);
	sstl_tree_item = proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_sstl,
		tvb, offset, 1, hdr->ar_sstl, "Source SubAddress Type/Len: %s/%u",
		val_to_str(NHRP_SHTL_TYPE(hdr->ar_sstl), nhrp_shtl_type_vals, "Unknown Type"),
		NHRP_SHTL_LEN(hdr->ar_sstl));
	sstl_tree = proto_item_add_subtree(sstl_tree_item, ett_nhrp_hdr_sstl);
	proto_tree_add_item(sstl_tree, hf_nhrp_hdr_sstl_type, tvb, offset, 1, FALSE);
	proto_tree_add_item(sstl_tree, hf_nhrp_hdr_sstl_len, tvb, offset, 1, FALSE);
	offset += 1;

	*pOffset = offset;
	if (hdr->ar_extoff != 0) {
		if (hdr->ar_extoff >= 20) {
			*pMandLen = hdr->ar_extoff - 20;
			*pExtLen = total_len - hdr->ar_extoff;
		} else {
			/* Error */
			*pMandLen = 0;
			*pExtLen = 0;
		}
	}
	else {
		if (total_len >= 20)
			*pMandLen = total_len - 20;
		else {
			/* "Can't happen" - we would have thrown an exception */
			*pMandLen = 0;
		}
		*pExtLen = 0;
	}
}
Esempio n. 7
0
static void
client_display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo,
	proto_tree *tree, socks_hash_entry_t *hash_info, sock_state_t* state_info) {

/* Display the protocol tree for the version. This routine uses the	*/
/* stored conversation information to decide what to do with the row.	*/
/* Per packet information would have been better to do this, but we	*/
/* didn't have that when I wrote this. And I didn't expect this to get	*/
/* so messy.								*/

	unsigned int i;
	const char *AuthMethodStr;
	sock_state_t new_state_info;

	/* Either there is an error, or we're done with the state machine
	  (so there's nothing to display) */
	if (state_info == NULL)
		return;

	proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, ENC_BIG_ENDIAN);
	++offset;

	if (state_info->client == clientStart)
	{
		proto_tree      *AuthTree;
		proto_item      *ti;
		guint8 num_auth_methods, auth;

		ti = proto_tree_add_text( tree, tvb, offset, -1, "Client Authentication Methods");
		AuthTree = proto_item_add_subtree(ti, ett_socks_auth);

		num_auth_methods = tvb_get_guint8(tvb, offset);
		proto_item_set_len(ti, num_auth_methods+1);

		proto_tree_add_item( AuthTree, hf_client_auth_method_count, tvb, offset, 1, ENC_NA);
		++offset;

		for( i = 0; i  < num_auth_methods; ++i) {
			auth = tvb_get_guint8( tvb, offset);
			AuthMethodStr = get_auth_method_name(auth);

			proto_tree_add_uint_format(AuthTree, hf_client_auth_method, tvb, offset, 1, auth,
										"Method[%u]: %u (%s)", i, auth, AuthMethodStr);
			++offset;
		}

		if ((num_auth_methods == 1) &&
			(tvb_bytes_exist(tvb, offset + 2, 1)) &&
			(tvb_get_guint8(tvb, offset + 2) == 0) &&
			(tvb_reported_length_remaining(tvb, offset + 2 + num_auth_methods) > 0)) {
				new_state_info.client = clientV5Command;
				client_display_socks_v5(tvb, offset, pinfo, tree, hash_info, &new_state_info);
		}
	}
	else if (state_info->client == clientV5Command) {

		proto_tree_add_item( tree, hf_socks_cmd, tvb, offset, 1, ENC_NA);
		++offset;

		proto_tree_add_item( tree, hf_socks_reserved, tvb, offset, 1, ENC_NA);
		++offset;

		offset = display_address(tvb, offset, tree);
		proto_tree_add_item( tree, hf_client_port, tvb, offset, 2, ENC_BIG_ENDIAN);
	}
	else if ((state_info->client == clientWaitForAuthReply) &&
			 (state_info->server == serverInitReply)) {
		guint16 len;
		gchar* str;

		switch(hash_info->authentication_method)
		{
		case NO_AUTHENTICATION:
			break;
		case USER_NAME_AUTHENTICATION:
			/* process user name */
			len = tvb_get_guint8(tvb, offset);
			str = tvb_get_string(wmem_packet_scope(), tvb, offset+1, len);
			proto_tree_add_string(tree, hf_socks_username, tvb, offset, len+1, str);
			offset += (len+1);

			len = tvb_get_guint8(tvb, offset);
			str = tvb_get_string(wmem_packet_scope(), tvb, offset+1, len);
			proto_tree_add_string(tree, hf_socks_password, tvb, offset, len+1, str);
			/* offset += (len+1); */
			break;
		case GSS_API_AUTHENTICATION:
			proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, ENC_BIG_ENDIAN);
			proto_tree_add_item( tree, hf_gssapi_length, tvb, offset+1, 2, ENC_BIG_ENDIAN);
			len = tvb_get_ntohs(tvb, offset+1);
			if (len > 0)
				proto_tree_add_item( tree, hf_gssapi_payload, tvb, offset+3, len, ENC_NA);
			break;
		default:
			break;
		}
	}
}
Esempio n. 8
0
static int
dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    const char		*opcode_str;
    proto_tree		*slimp3_tree = NULL;
    proto_item		*ti = NULL, *hidden_item;
    gint		i1;
    gint		offset = 0;
    guint16		opcode;
    guchar		lcd_char;
    char		lcd_str[MAX_LCD_STR_LEN + 1];
    int			to_server = FALSE;
    int			old_protocol = FALSE;
    address		tmp_addr;
    gboolean		in_str;
    int			lcd_strlen;

    /*
     * If it doesn't begin with a known opcode, reject it, so that
     * traffic that happens to be do or from one of our ports
     * doesn't get misidentified as SliMP3 traffic.
     */
    if (!tvb_bytes_exist(tvb, offset, 1))
        return 0;	/* not even an opcode */
    opcode = tvb_get_guint8(tvb, offset);
    opcode_str = match_strval(opcode, slimp3_opcode_vals);
    if (opcode_str == NULL)
        return 0;

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

    if (check_col(pinfo->cinfo, COL_INFO)) {

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

    }

    if (tree) {

        ti = proto_tree_add_item(tree, proto_slimp3, tvb, offset, -1, ENC_NA);
        slimp3_tree = proto_item_add_subtree(ti, ett_slimp3);

        proto_tree_add_uint(slimp3_tree, hf_slimp3_opcode, tvb,
                            offset, 1, opcode);
    }

    /* The new protocol (v1.3 and later) uses an IANA-assigned port number.
    * It usually uses the same number for both sizes of the conversation, so
    * the port numbers can't always be used to determine client and server.
    * The new protocol places the clients MAC address in the packet, so that
    * is used to identify packets originating at the client.
    */
    if ((pinfo->destport == UDP_PORT_SLIMP3_V2) && (pinfo->srcport == UDP_PORT_SLIMP3_V2)) {
        SET_ADDRESS(&tmp_addr, AT_ETHER, 6, tvb_get_ptr(tvb, offset+12, 6));
        to_server = ADDRESSES_EQUAL(&tmp_addr, &pinfo->dl_src);
    }
    else if (pinfo->destport == UDP_PORT_SLIMP3_V2) {
        to_server = TRUE;
    }
    else if (pinfo->srcport == UDP_PORT_SLIMP3_V2) {
        to_server = FALSE;
    }
    if (pinfo->destport == UDP_PORT_SLIMP3_V1) {
        to_server = TRUE;
        old_protocol = TRUE;
    }
    else if (pinfo->srcport == UDP_PORT_SLIMP3_V1) {
        to_server = FALSE;
        old_protocol = TRUE;
    }

    switch (opcode) {

    case SLIMP3_IR:
        /* IR code
        *
        * [0]        'i' as in "IR"
        * [1]	     0x00
        * [2..5]     player's time since startup in ticks @625 KHz
        * [6]        IR code id, ff=JVC, 02=SLIMP3
        * [7]        number of meaningful bits - 16 for JVC, 32 for SLIMP3
        * [8..11]    the 32-bit IR code
        * [12..17]   reserved
        */
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_ir, tvb, offset+8, 4, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);

            i1 = tvb_get_ntohl(tvb, offset+2);
            proto_tree_add_text(slimp3_tree, tvb, offset+2, 4, "Uptime: %u sec (%u ticks)",
                                i1/625000, i1);
            i1 = tvb_get_guint8(tvb, offset+6);
            proto_tree_add_text(slimp3_tree, tvb, offset+6, 1, "Code identifier: 0x%0x: %s",
                                i1, val_to_str(i1, slimp3_ir_types, "Unknown"));
            proto_tree_add_text(slimp3_tree, tvb, offset+7, 1, "Code bits: %d",
                                tvb_get_guint8(tvb, offset+7));

            i1 = tvb_get_ntohl(tvb, offset+8);
            /* Check the code to figure out which remote is being used. */
            if (tvb_get_guint8(tvb, offset+6) == 0x02 &&
                    tvb_get_guint8(tvb, offset+7) == 32) {
                /* This is the custom SLIMP3 remote. */
                proto_tree_add_text(slimp3_tree, tvb, offset+8, 4,
                                    "Infrared Code: %s: 0x%0x",
                                    val_to_str(i1, slimp3_ir_codes_slimp3, "Unknown"), i1);
            }
            else if (tvb_get_guint8(tvb, offset+6) == 0xff &&
                     tvb_get_guint8(tvb, offset+7) == 16) {
                /* This is a JVC DVD player remote */
                proto_tree_add_text(slimp3_tree, tvb, offset+8, 4,
                                    "Infrared Code: %s: 0x%0x",
                                    val_to_str(i1, slimp3_ir_codes_jvc, "Unknown"), i1);
            } else {
                /* Unknown code; just write it */
                proto_tree_add_text(slimp3_tree, tvb, offset+8, 4, "Infrared Code: 0x%0x", i1);
            }
        }
        if (check_col(pinfo->cinfo, COL_INFO)) {
            i1 = tvb_get_ntohl(tvb, offset+8);
            if (tvb_get_guint8(tvb, offset+6) == 0x02 &&
                    tvb_get_guint8(tvb, offset+7) == 32) {
                col_append_fstr(pinfo->cinfo, COL_INFO, ", SLIMP3: %s",
                                val_to_str(i1, slimp3_ir_codes_slimp3, "Unknown (0x%0x)"));
            }
            else if (tvb_get_guint8(tvb, offset+6) == 0xff &&
                     tvb_get_guint8(tvb, offset+7) == 16) {
                col_append_fstr(pinfo->cinfo, COL_INFO, ", JVC: %s",
                                val_to_str(i1, slimp3_ir_codes_jvc, "Unknown (0x%0x)"));
            } else {
                /* Unknown code; just write it */
                col_append_fstr(pinfo->cinfo, COL_INFO, ", 0x%0x", i1);
            }
        }
        break;

    case SLIMP3_DISPLAY:
        if (tree) {

            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_display,
                                              tvb, offset, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);

            /* Loop through the commands */
            i1 = 18;
            in_str = FALSE;
            lcd_strlen = 0;
            while (i1 < tvb_reported_length_remaining(tvb, offset)) {
                switch(tvb_get_guint8(tvb, offset + i1)) {
                case 0:
                    in_str = FALSE;
                    lcd_strlen = 0;
                    proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
                                        "Delay (%d ms)", tvb_get_guint8(tvb, offset + i1 + 1));
                    i1 += 2;
                    break;
                case 3:
                    lcd_char = tvb_get_guint8(tvb, offset + i1 + 1);
                    if (!isprint(lcd_char)) lcd_char = '.';
                    if (ti && in_str) {
                        lcd_strlen += 2;
                        proto_item_append_text(ti, "%c", lcd_char);
                        proto_item_set_len(ti, lcd_strlen);
                    } else {
                        ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
                                                 "String: %c", lcd_char);
                        in_str = TRUE;
                        lcd_strlen = 2;
                    }
                    i1 += 2;
                    break;

                case 2:
                    in_str = FALSE;
                    lcd_strlen = 0;
                    ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
                                             "Command: %s",
                                             val_to_str(tvb_get_guint8(tvb, offset + i1 + 1),
                                                        slimp3_display_commands,
                                                        "Unknown (0x%0x)"));
                    if ((tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30) {
                        proto_item_append_text(ti, ": %s",
                                               val_to_str(tvb_get_guint8(tvb, offset + i1 + 2),
                                                          slimp3_display_fset8,
                                                          "Unknown (0x%0x)"));
                        i1 += 2;
                    }
                    i1 += 2;
                    break;

                default:
                    proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
                                        "Unknown 0x%0x, 0x%0x",
                                        tvb_get_guint8(tvb, offset + i1),
                                        tvb_get_guint8(tvb, offset + i1 + 1));
                    i1 += 2;
                    break;
                }
            }
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            i1 = 18;
            lcd_strlen = 0;
            while (tvb_offset_exists(tvb, offset + i1) &&
                    lcd_strlen < MAX_LCD_STR_LEN) {
                switch (tvb_get_guint8(tvb, offset + i1)) {

                case 0:
                    lcd_str[lcd_strlen++] = '.';
                    break;

                case 2:
                    lcd_str[lcd_strlen++] = '|';
                    if (tvb_offset_exists(tvb, offset + i1 + 1) &&
                            (tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30)
                        i1 += 2;
                    break;

                case 3:
                    if (tvb_offset_exists(tvb, offset + i1 + 1)) {
                        if (lcd_strlen < 1 ||
                                lcd_str[lcd_strlen-1] != ' ' ||
                                tvb_get_guint8(tvb, offset + i1 + 1) != ' ') {
                            lcd_char = tvb_get_guint8(tvb, offset + i1 + 1);
                            lcd_str[lcd_strlen++] = isprint(lcd_char) ? lcd_char : '.';
                        }
                    }
                }
                i1 += 2;
            }
            lcd_str[lcd_strlen] = '\0';
            if (lcd_strlen > 0)
                col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", lcd_str);
        }

        break;

    case SLIMP3_CONTROL:
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_control,
                                              tvb, offset+1, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s",
                                val_to_str(tvb_get_guint8(tvb, offset+1),
                                           slimp3_stream_control, "Unknown (0x%0x)"));
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
                            val_to_str(tvb_get_guint8(tvb, offset+1),
                                       slimp3_stream_control, "Unknown (0x%0x)"));
        }
        break;

    case SLIMP3_HELLO:
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_hello,
                                              tvb, offset+1, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            if (to_server) {
                guint8 fw_ver = 0;
                /* Hello response; client->server */
                proto_tree_add_text(slimp3_tree, tvb, offset, 1, "Hello Response (Client --> Server)");
                proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Device ID: %d",
                                    tvb_get_guint8(tvb, offset+1));
                fw_ver = tvb_get_guint8(tvb, offset+2);
                proto_tree_add_text(slimp3_tree, tvb, offset+2, 1, "Firmware Revision: %d.%d (0x%0x)",
                                    fw_ver>>4, fw_ver & 0xf, fw_ver);
            } else {
                /* Hello request; server->client */
                proto_tree_add_text(slimp3_tree, tvb, offset, 1, "Hello Request (Server --> Client)");
            }
        }
        break;

    case SLIMP3_I2C:
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_i2c,
                                              tvb, offset, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            if (to_server) {
                /* Hello response; client->server */
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
                                    "I2C Response (Client --> Server)");
            } else {
                /* Hello request; server->client */
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
                                    "I2C Request (Server --> Client)");
            }
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            if (to_server) {
                col_append_str(pinfo->cinfo, COL_INFO, ", Response");
            } else {
                col_append_str(pinfo->cinfo, COL_INFO, ", Request");
            }
        }
        break;

    case SLIMP3_DATA_REQ:
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data_request,
                                              tvb, offset, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+2, 2,
                                "Requested offset: %d bytes.",
                                tvb_get_ntohs(tvb, offset+2)*2);
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Offset: %d bytes",
                            tvb_get_ntohs(tvb, offset+2)*2);
        }
        break;

    case SLIMP3_DATA:
        /* MPEG data (v1.3 and later)
        *
        *  [0]       'm'
        *  [1..5]    reserved
        *  [6..7]    Write pointer (in words)
        *  [8..9]    reserved
        *  [10..11]  Sequence number
        *  [12..17]  reserved
        *  [18..]    MPEG data
        */
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data,
                                              tvb, offset, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            if (old_protocol) {
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
                                    "Length: %d bytes",
                                    tvb_reported_length_remaining(tvb, offset+18));
                proto_tree_add_text(slimp3_tree, tvb, offset+2, 2,
                                    "Buffer offset: %d bytes.",
                                    tvb_get_ntohs(tvb, offset+2) * 2);
            }
            else {
                proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s",
                                    val_to_str(tvb_get_guint8(tvb, offset+1),
                                               slimp3_mpg_control, "Unknown (0x%0x)"));
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
                                    "Length: %d bytes",
                                    tvb_reported_length_remaining(tvb, offset+18));
                proto_tree_add_text(slimp3_tree, tvb, offset+6, 2,
                                    "Write Pointer: %d",
                                    tvb_get_ntohs(tvb, offset+6) * 2);
                proto_tree_add_text(slimp3_tree, tvb, offset+10, 2,
                                    "Sequence: %d",
                                    tvb_get_ntohs(tvb, offset+10));
            }
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            if (old_protocol) {
                col_append_fstr(pinfo->cinfo, COL_INFO,
                                ", Length: %d bytes, Offset: %d bytes.",
                                tvb_reported_length_remaining(tvb, offset+18),
                                tvb_get_ntohs(tvb, offset+2) * 2);
            }
            else {
                col_append_fstr(pinfo->cinfo, COL_INFO,
                                ", %s, %d bytes at %d, Sequence: %d",
                                val_to_str(tvb_get_guint8(tvb, offset+1),
                                           slimp3_mpg_control, "Unknown (0x%0x)"),
                                tvb_reported_length_remaining(tvb, offset+18),
                                tvb_get_ntohs(tvb, offset+6) * 2,
                                tvb_get_ntohs(tvb, offset+10));
            }
        }
        break;

    case SLIMP3_DISC_REQ:
        if (tree) {
            guint8 fw_ver;
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_discover_request,
                                              tvb, offset, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+1, 1,
                                "Device ID: %d.", tvb_get_guint8(tvb, offset+1));
            fw_ver = tvb_get_guint8(tvb, offset+2);
            proto_tree_add_text(slimp3_tree, tvb, offset+2, 1, "Firmware Revision: %d.%d (0x%0x)",
                                fw_ver>>4, fw_ver & 0xf, fw_ver);
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            guint8 fw_ver = tvb_get_guint8(tvb, offset+2);
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Device ID: %d. Firmware: %d.%d",
                            tvb_get_guint8(tvb, offset+1), fw_ver>>4, fw_ver & 0xf);
        }
Esempio n. 9
0
/*
 * This function dissects an "Ice string", adds hf to "tree" and returns consumed
 * bytes in "*consumed", if errors "*consumed" is -1.
 *
 * "*dest" is a null terminated version of the dissected Ice string.
 */
static void dissect_ice_string(packet_info *pinfo, proto_tree *tree, proto_item *item, int hf_icep,
							   tvbuff_t *tvb, guint32 offset, gint32 *consumed, char **dest)
{
	/* p. 586 chapter 23.2.1 and p. 588 chapter 23.2.5
	 * string == Size + content
	 * string = 1byte (0..254) + string not null terminated
	 * or
	 * string = 1byte (255) + 1int (255..2^32-1) + string not null terminated
	 */

	guint32 Size = 0;
	char *s = NULL;

	(*consumed) = 0;

	/* check for first byte */
	if ( !tvb_bytes_exist(tvb, offset, 1) ) {

		if (item)
			expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "1st byte of Size missing");

		col_append_str(mypinfo->cinfo, COL_INFO, " (1st byte of Size missing)");

		(*consumed) = -1;
		return;
	}

	/* get the Size */
	Size = tvb_get_guint8(tvb, offset);
	offset++;
	(*consumed)++;

	if ( Size == 255 ) {

		/* check for next 4 bytes */
		if ( !tvb_bytes_exist(tvb, offset, 4) ) {

			if (item)
				expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "second field of Size missing");

			col_append_str(mypinfo->cinfo, COL_INFO, " (second field of Size missing)");

			(*consumed) = -1;
			return;
		}

		/* get second field of Size */
		Size = tvb_get_letohl(tvb, offset);
		offset += 4;
		(*consumed) += 4;
	}

	DBG1("string.Size --> %d\n", Size);

	/* check if the string exists */
	if ( !tvb_bytes_exist(tvb, offset, Size) ) {

		if (item)
			expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "missing or truncated string");

		col_append_str(mypinfo->cinfo, COL_INFO, " (missing or truncated string)");

		(*consumed) = -1;
		return;
	}

	if ( Size > icep_max_ice_string_len ) {

		if (item)
			expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "string too long");

		col_append_str(mypinfo->cinfo, COL_INFO, " (string too long)");

		(*consumed) = -1;
		return;
	}


	if ( Size != 0 ) {
		s = tvb_get_ephemeral_string(tvb, offset, Size);
		if (tree)
			proto_tree_add_string(tree, hf_icep, tvb, offset, Size, s);
	} else {
		s = g_strdup("(empty)");
		/* display the 0x00 Size byte when click on a empty ice_string */
		if (tree)
			proto_tree_add_string(tree, hf_icep, tvb, offset - 1, 1, s);
	}

	if ( dest != NULL )
		*dest = s;

	/*offset += Size;*/
	(*consumed) += Size;
	return;
}
Esempio n. 10
0
/*
 * This function dissects an "Ice context", adds hf(s) to "tree" and returns consumed
 * bytes in "*consumed", if errors "*consumed" is -1.
 */
static void dissect_ice_context(proto_tree *tree, tvbuff_t *tvb, guint32 offset,
				gint32 *consumed)
{
	/*  p. 588, chapter 23.2.7 and p. 613, 23.3.2:
	 *  "context" is a dictionary<string, string>
	 *
	 * dictionary<string, string> == Size + SizeKeyValuePairs
	 * dictionary<string, string> = 1byte (0..254) + SizeKeyValuePairs
	 * or
	 * dictionary<string, string>= 1byte (255) + 1int (255..2^32-1)+SizeKeyValuePairs
	 *
	 */

	guint32 Size = 0; /* number of key-value in the dictionary */
	guint32 i = 0;
	const char *s = NULL;

	(*consumed) = 0;

	/* check first byte */
	if ( !tvb_bytes_exist(tvb, offset, 1) ) {

		if (tree)
			proto_tree_add_text(tree, tvb, offset, -1, "context missing");

		col_append_str(mypinfo->cinfo, COL_INFO,
				       " (context missing)");

		(*consumed) = -1;
		return;
	}

	/* get first byte of Size */
	Size = tvb_get_guint8(tvb, offset);
	offset++;
	(*consumed)++;

	if ( Size == 255 ) {

		/* check for next 4 bytes */
		if ( !tvb_bytes_exist(tvb, offset, 4) ) {

			if (tree)
				proto_tree_add_text(tree, tvb, offset, -1,
						    "second field of Size missing");

			col_append_str(mypinfo->cinfo, COL_INFO,
					       " (second field of Size missing)");

			(*consumed) = -1;
			return;
		}

		/* get second field of Size */
		Size = tvb_get_letohl(tvb, offset);
		offset += 4;
		(*consumed) += 4;
	}

	DBG1("context.Size --> %d\n", Size);

	if ( Size > ICEP_MAX_ICE_CONTEXT_PAIRS ) {

		if (tree)
			/* display the XX Size byte when click here */
			proto_tree_add_text(tree, tvb, offset - 1, 1, "too long context");

		col_append_str(mypinfo->cinfo, COL_INFO,
				       " (too long context)");

		(*consumed) = -1;
		return;
	}

	if (Size == 0) {
		s = "(empty)";
		/* display the 0x00 Size byte when click on a empty context */
		if (tree)
			proto_tree_add_string(tree, hf_icep_context, tvb, offset - 1, 1, s);
		return;
	}

	/* looping through the dictionary */
	for ( i = 0; i < Size; i++ ) {
		/* key */
		gint32 consumed_key = 0;
		char *str_key = NULL;
		/* value */
		gint32 consumed_value = 0;
		char *str_value = NULL;


		DBG1("looping through context dictionary, loop #%d\n", i);

		dissect_ice_string(tree, -1, tvb, offset, &consumed_key,
				   &str_key, FALSE);

		if ( consumed_key == -1 ) {
			(*consumed) = -1;
			return;
		}

		offset += consumed_key;
		(*consumed) += consumed_key;

		dissect_ice_string(tree, -1, tvb, offset, &consumed_value,
				   &str_value, FALSE);

		if ( consumed_value == -1 ) {
			(*consumed) = -1;
			return;
		}

		offset += consumed_value;
		(*consumed) += consumed_value;

		if (tree && str_value && str_key) {

			proto_tree_add_text(tree, tvb,
					    offset - (consumed_key + consumed_value) - 1,
					    (consumed_key + consumed_value) + 1,
					    "Invocation Context: %s/%s",
					    str_key, str_value);
		}

	}
}
static gboolean
dissect_mpeg_audio_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint32 h;
	struct mpa mpa;
	int data_size = 0;
	asn1_ctx_t asn1_ctx;
	int offset = 0;
	static const char *version_names[] = { "1", "2", "2.5" };

	if (!tvb_bytes_exist(tvb, 0, 4))
		return FALSE;	/* not enough data for an MPEG audio frame */

	h = tvb_get_ntohl(tvb, 0);
	MPA_UNMARSHAL(&mpa, h);
	if (!MPA_SYNC_VALID(&mpa))
		return FALSE;
	if (!MPA_VERSION_VALID(&mpa))
		return FALSE;
	if (!MPA_LAYER_VALID(&mpa))
		return FALSE;
		
	col_add_fstr(pinfo->cinfo, COL_PROTOCOL,
			"MPEG-%s", version_names[mpa_version(&mpa)]);
	col_add_fstr(pinfo->cinfo, COL_INFO,
				"Audio Layer %d", mpa_layer(&mpa) + 1);
	if (MPA_BITRATE_VALID(&mpa) && MPA_FREQUENCY_VALID(&mpa)) {
		data_size = (int)(MPA_DATA_BYTES(&mpa) - sizeof mpa);
		if (check_col(pinfo->cinfo, COL_DEF_SRC)) {
			SET_ADDRESS(&pinfo->src, AT_NONE, 0, NULL);
			col_add_fstr(pinfo->cinfo, COL_DEF_SRC,
					"%d kb/s", mpa_bitrate(&mpa) / 1000);
		}
		if (check_col(pinfo->cinfo, COL_DEF_DST)) {
			SET_ADDRESS(&pinfo->dst, AT_NONE, 0, NULL);
			col_add_fstr(pinfo->cinfo, COL_DEF_DST,
					"%g kHz", mpa_frequency(&mpa) / (float)1000);
		}
	}

	if (tree == NULL)
		return TRUE;

	asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo);
	offset = dissect_mpeg_audio_Audio(tvb, offset, &asn1_ctx,
			tree, proto_mpeg_audio);
	if (data_size > 0) {
		unsigned int padding;

		proto_tree_add_item(tree, hf_mpeg_audio_data, tvb,
				offset / 8, data_size, FALSE);
		offset += data_size * 8;
		padding = mpa_padding(&mpa);
		if (padding > 0) {
			proto_tree_add_item(tree, hf_mpeg_audio_padbytes, tvb,
					offset / 8, padding, FALSE);
			offset += padding * 8;
		}
	}
	return TRUE;
}
Esempio n. 12
0
static void
dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_tree     *clnp_tree = NULL;
  proto_item     *ti;
  guint8          cnf_proto_id;
  guint8          cnf_hdr_len;
  guint8          cnf_vers;
  guint8          cnf_ttl;
  guint8          cnf_type;
  char            flag_string[6+1];
  const char     *pdu_type_string;
  proto_tree     *type_tree;
  guint16         segment_length;
  guint16         du_id = 0;
  guint16         segment_offset = 0;
  guint16         cnf_cksum;
  cksum_status_t  cksum_status;
  int             offset;
  guchar          src_len, dst_len, nsel, opt_len = 0;
  const guint8   *dst_addr, *src_addr;
  guint           next_length;
  proto_tree     *discpdu_tree;
  gboolean        save_in_error_pkt;
  fragment_data  *fd_head;
  tvbuff_t       *next_tvb;
  gboolean        update_col_info = TRUE;
  gboolean        save_fragmented;

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

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

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

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

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

  cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
  pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
                               "Unknown (0x%02x)");
  flag_string[0] = '\0';
  if (cnf_type & CNF_SEG_OK)
    g_strlcat(flag_string, "S ", 7);
  if (cnf_type & CNF_MORE_SEGS)
    g_strlcat(flag_string, "M ", 7);
  if (cnf_type & CNF_ERR_OK)
    g_strlcat(flag_string, "E ", 7);
  if (tree) {
    ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
                                    cnf_type,
                                    "PDU Type     : 0x%02x (%s%s)",
                                    cnf_type,
                                    flag_string,
                                    pdu_type_string);
    type_tree = proto_item_add_subtree(ti, ett_clnp_type);
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8,
                                                "Segmentation permitted",
                                                "Segmentation not permitted"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8,
                                                "More segments",
                                                "Last segment"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8,
                                                "Report error if PDU discarded",
                                                "Don't report error if PDU discarded"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8,
                                                   npdu_type_vals, "%s"));
  }

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

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

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

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

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

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

  /* address part */

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

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

    opt_len -= dst_len + src_len +2;
  }

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

  /* Segmentation Part */

  offset += dst_len + src_len + 2;

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

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

    offset  += 6;
    opt_len -= 6;
  }

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

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

  offset = cnf_hdr_len;

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

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

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

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

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

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

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

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

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

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

      break;

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

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

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

          call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);

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

    case ERQ_NPDU:
    case ERP_NPDU:
      /* XXX - dissect this */
      break;
    }
  }
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
  call_dissector(data_handle,next_tvb, pinfo, tree);
  pinfo->fragmented = save_fragmented;
} /* dissect_clnp */
Esempio n. 13
0
static gboolean
dissect_ses_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
	/* must check that this really is a ses packet */
	int offset = 0;
	guint8 type;
	int len_len;
	guint16 len;

	/* first, check do we have at least 4 bytes (type+length) */
	if (tvb_length(tvb) < 2)
		return FALSE;	/* no */

	/* can we recognize session PDU ? Return FALSE if  not */
	/*   get SPDU type */
	type = tvb_get_guint8(tvb, offset);
	/* check SPDU type */
	if (match_strval(type, ses_vals) == NULL)
	{
		return FALSE;  /* no, it isn't a session PDU */
	}

	/* can we recognize the second session PDU if the first one was
	 * a Give Tokens PDU? Return FALSE if not */
	if(tvb_bytes_exist(tvb, 2, 2) && type == SES_GIVE_TOKENS) {
		/*   get SPDU type */
		type = tvb_get_guint8(tvb, offset+2);
		/* check SPDU type */
		if (match_strval(type, ses_vals) == NULL)
		{
			return FALSE;  /* no, it isn't a session PDU */
		}
	}

	/* some Siemens SIMATIC protocols also use COTP, and shouldn't be
	 * misinterpreted as SES.
	 * the starter in this case is fixed to 0x32 (SES_MINOR_SYNC_ACK for SES),
	 * so if the parameter type is unknown, it's probably SIMATIC */
	if(type == 0x32 && tvb_length(tvb) >= 3) {
		type = tvb_get_guint8(tvb, offset+2);
		if (match_strval(type, param_vals) == NULL) {
			return FALSE; /* it's probably a SIMATIC protocol */
		}
	}

	/*  OK,let's check SPDU length  */
	/*  get length of SPDU */
	len = get_item_len(tvb, offset+1, &len_len);

	/*  add header length     */
	len+=len_len;
	/* do we have enough bytes ? */
	if (tvb_length(tvb) < len)
		return FALSE;	/* no */

	/* final check to see if the next SPDU, if present, is also valid */
	if (tvb_length(tvb) > len) {
	  type = tvb_get_guint8(tvb, offset + len + 1);
	  /* check SPDU type */
	  if (match_strval(type, ses_vals) == NULL) {
	    return FALSE;  /* no, it isn't a session PDU */
	  }
	}

	dissect_ses(tvb, pinfo, parent_tree);
	return TRUE;
}
Esempio n. 14
0
gboolean
osi_check_and_get_checksum( tvbuff_t *tvb, int offset, guint len, int offset_check, guint16* result) {
  const guint8 *p;
  guint8        discard         = 0;
  guint32       c0, c1, factor;
  guint         seglen, initlen = len;
  guint         i;
  int           block, x, y;

  /* Make sure the checksum is part of the data being checksummed. */
  DISSECTOR_ASSERT(offset_check >= offset);
  DISSECTOR_ASSERT((guint)offset_check + 2 <= (guint)offset + len);

  /*
   * If we don't have all the data to be checksummed, report that and don't
   * try checksumming.
   */
  if (!tvb_bytes_exist(tvb, offset, len))
    return FALSE;
  offset_check -= offset;

  p = tvb_get_ptr( tvb, offset, len );
  block  = offset_check / 5803;

  /*
   * The maximum values of c0 and c1 will occur if all bytes have the
   * value 255; if so, then c0 will be len*255 and c1 will be
   * (len*255 + (len-1)*255 + ... + 255), which is
   * (len + (len - 1) + ... + 1)*255, or 255*(len*(len + 1))/2.
   * This means it can overflow if "len" is 5804 or greater.
   *
   * (A+B) mod 255 = ((A mod 255) + (B mod 255) mod 255, so
   * we can solve this by taking c0 and c1 mod 255 every
   * 5803 bytes.
   */
  c0 = 0;
  c1 = 0;

  while (len != 0) {
    seglen = len;
    if ( block-- == 0 ) {
      seglen = offset_check % 5803;
      discard = 1;
    } else if ( seglen > 5803 )
      seglen = 5803;
    for (i = 0; i < seglen; i++) {
      c0 = c0 + *(p++);
      c1 += c0;
    }
    if ( discard ) {
      /*
       * This works even if (offset_check % 5803) == 5802
       */
      p += 2;
      c1 += 2*c0;
      len -= 2;
      discard = 0;
    }

    c0 = c0 % 255;
    c1 = c1 % 255;

    len -= seglen;
  }

  factor = ( initlen - offset_check ) * c0;
  x = factor - c0 - c1;
  y = c1 - factor - 1;

  /*
   * This algorithm uses the 8 bits one's complement arithmetic.
   * Therefore, we must correct an effect produced
   * by the "standard" arithmetic (two's complement)
   */

  if (x < 0 ) x--;
  if (y > 0 ) y++;

  x %= 255;
  y %= 255;

  if (x == 0) x = 0xFF;
  if (y == 0) y = 0x01;

  *result = ( x << 8 ) | ( y & 0xFF );
  return TRUE;
}
Esempio n. 15
0
/* This routine attempts to locate the position of the next header in the
 * provided segment
 */
static guint
get_next_fcip_header_offset (tvbuff_t *tvb, packet_info *pinfo, gint offset)
{
    gint       bytes_remaining = tvb_reported_length_remaining (tvb, offset);
    gint       frame_len;
    guint16    flen, flen1;
    fcip_eof_t eof, eofc;

    /*
     * As per the FCIP standard, the following tests must PASS:
     * 1)  Frame Length field validation -- 15 < Frame Length < 545;
     * 2)  Comparison of Frame Length field to its ones complement; and
     * 3)  A valid EOF is found in the word preceding the start of the next
     *     FCIP header as indicated by the Frame Length field, to be tested
     *     as follows:
     *     1)  Bits 24-31 and 16-23 contain identical legal EOF values (the
     *         list of legal EOF values is in the FC Frame Encapsulation
     *         [21]); and
     *     2)  Bits 8-15 and 0-7 contain the ones complement of the EOF
     *         value found in bits 24-31.
     *
     * As per the FCIP standard, in addition, at least 3 of the following set
     * of tests must be performed to identify that we've located the start of
     * an FCIP frame.
     * a)  Protocol# ones complement field (1 test);
     * b)  Version ones complement field (1 test);
     * c)  Replication of encapsulation word 0 in word 1 (1 test);
     * d)  Reserved field and its ones complement (2 tests);
     * e)  Flags field and its ones complement (2 tests);
     *    f)  CRC field is equal to zero (1 test); (DON'T DO THIS TEST!)
     * g)  SOF fields and ones complement fields (4 tests);
     * h)  Format and values of FC header (1 test);
     * i)  CRC of FC Frame (2 tests);
     * j)  FC Frame Encapsulation header information in the next FCIP Frame
     *     (1 test).
     *
     * At least 3 of the 16 tests listed above SHALL be performed. Failure
     * of any of the above tests actually performed SHALL indicate an
     * encapsulation error and the FC Frame SHALL NOT be forwarded on to
     * the FC Entity.
     */

NXT_BYTE: while (bytes_remaining) {
        if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) {
            if(fcip_desegment && pinfo->can_desegment) {
                /*
                 * This frame doesn't have all of the data for
                 * the message header, but we can do reassembly on it.
                 *
                 * Tell the TCP dissector where the data for this
                 * message starts in the data it handed us, and that we need
                 * "some more data."  Don't tell it exactly how many bytes
                 * we need because if/when we ask for even more (after the
                 * header) that will break reassembly.
                 */
                pinfo->desegment_offset = offset;
                pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
                return -2;
            }
        }

        /* I check that we have a valid header before checking for the frame
         * length and the other initial tests.
         */

        /*
         * Tests a, b and c
         */
        if (tvb_memeql(tvb, offset, fcip_header_8_bytes, 8) != 0) {
            offset++;
            bytes_remaining--;
            goto NXT_BYTE;
        }

        flen = (tvb_get_ntohs (tvb, offset+12)) & 0x03FF;
        frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;

        if ((flen < 15) || (flen > 545)) {
            /* Frame length check failed. Skip byte and try again */
            offset++;
            bytes_remaining--;
            goto NXT_BYTE;
        }

        flen1 = (tvb_get_ntohs (tvb, offset+14)) & 0x03FF;

        if ((flen & 0x03FF) != ((~flen1)&0x03FF)) {
            /* frame_len and its one's complement are not the same */
            offset++;
            bytes_remaining--;
            goto NXT_BYTE;
        }

        /* Valid EOF check */
        if (tvb_bytes_exist (tvb, offset+(frame_len-1)*4, 4)) {
            eof = (fcip_eof_t)tvb_get_guint8 (tvb, offset+(frame_len-1)*4);
            eofc = (fcip_eof_t)tvb_get_guint8 (tvb, offset+(frame_len-1)*4+2);

            if ((eof != FCIP_EOFn) && (eof != FCIP_EOFt) && (eof != FCIP_EOFrt)
                && (eof != FCIP_EOFdt) && (eof != FCIP_EOFni) &&
                (eof != FCIP_EOFdti) && (eof != FCIP_EOFrti) &&
                (eof != FCIP_EOFa)) {
                offset++;
                bytes_remaining--;
                goto NXT_BYTE;
            }

            if ((eof != ~eofc) ||
                (eof != tvb_get_guint8 (tvb, offset+(frame_len-1)*4+1)) ||
                (eofc != tvb_get_guint8 (tvb, offset+(frame_len-1)*4+3))) {
                offset++;
                bytes_remaining--;
                goto NXT_BYTE;
            }
        }

        /* Test d */
        if ((tvb_get_guint8 (tvb, offset+9) != 0) ||
            (tvb_get_guint8 (tvb, offset+11) != 0xFF)) {
            /* Failed */
            offset++;
            bytes_remaining--;
            goto NXT_BYTE;
        }

        /* Test e */


        /* Test f
         * We don't test this since some implementations actually provide
         * a CRC here.
         */

        if (bytes_remaining >= (frame_len)) {
            if (tvb_bytes_exist (tvb, offset+frame_len, 8)) {
                /* The start of the next header matches what we wish to see */
                if (tvb_memeql (tvb, offset+frame_len, fcip_header_8_bytes,
                                8) == 0) {
                    return (offset);
                }
                else {
                    offset++;
                    bytes_remaining--;
                    goto NXT_BYTE;
                }
            }
            else {
                return (offset);
            }
        }
        else {
            if(fcip_desegment && pinfo->can_desegment) {
                /*
                 * This frame doesn't have all of the data for
                 * this message, but we can do reassembly on it.
                 *
                 * Tell the TCP dissector where the data for this
                 * message starts in the data it handed us, and
                 * how many more bytes we need, and return.
                 */
                pinfo->desegment_offset = offset;
                pinfo->desegment_len = frame_len - bytes_remaining;
                return -2;
            }
            else {
                return (offset);
            }
        }
    }

    return (-1);                /* Unable to find FCIP header */
}
Esempio n. 16
0
/*
 * This function dissects an "Ice facet", adds hf(s) to "tree" and returns consumed
 * bytes in "*consumed", if errors "*consumed" is -1.
 */
static void dissect_ice_facet(packet_info *pinfo, proto_tree *tree, proto_item *item, int hf_icep,
			      tvbuff_t *tvb, guint32 offset, gint32 *consumed)
{
	/*  p. 588, chapter 23.2.6:
	 *  "facet" is a StringSeq, a StringSeq is a:
	 *  sequence<string>
	 *
	 *
	 * sequence == Size + SizeElements
	 * sequence = 1byte (0..254) + SizeElements
	 * or
	 * sequence = 1byte (255) + 1int (255..2^32-1) + SizeElements
	 *
	 *
	 * p.613. chapter 23.3.2
	 * "facet has either zero elements (empty) or one element"
	 *
	 *
	 */

	guint32 Size = 0; /* number of elements in the sequence */

	(*consumed) = 0;

	/* check first byte */
	if ( !tvb_bytes_exist(tvb, offset, 1) ) {

		if (item)
			expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "facet field missing");

		col_append_str(mypinfo->cinfo, COL_INFO,
				       " (facet field missing)");

		(*consumed) = -1;
		return;
	}

	/* get first byte of Size */
	Size = tvb_get_guint8(tvb, offset);
	offset++;
	(*consumed)++;

	if ( Size == 0 ) {

		if (tree) {
			/* display the 0x00 Size byte when click on a empty ice_string */
			proto_tree_add_string(tree, hf_icep, tvb, offset - 1, 1, "(empty)");
		}
		return;
	}

	if ( Size == 1 ) {

		gint32 consumed_facet = 0;

		dissect_ice_string(pinfo, tree, item, hf_icep, tvb, offset, &consumed_facet, NULL);

		if ( consumed_facet == -1 ) {
			(*consumed) = -1;
			return;
		}

		/*offset += consumed_facet;*/
		(*consumed) += consumed_facet;
		return;
	}

	/* if here => Size > 1 => not possible */

	if (item)
		/* display the XX Size byte when click here */
		expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "facet can be max one element");

	col_append_str(mypinfo->cinfo, COL_INFO,
			       " (facet can be max one element)");

	(*consumed) = -1;
	return;
}
Esempio n. 17
0
static gboolean
dissect_fcip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
              gboolean check_port)
{
    gint offset = 0,
         start  = 0,
         frame_len = 0;
    gint bytes_remaining = tvb_captured_length (tvb);
    guint8 pflags, sof = 0, eof = 0;
   /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti;
    proto_tree *fcip_tree = NULL;
    tvbuff_t *next_tvb;
    fc_data_t fc_data;

    if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) {
        return FALSE;
    }

    if (check_port &&
        ((pinfo->srcport != fcip_port) && (pinfo->destport != fcip_port))) {
        return FALSE;
    }

    while (bytes_remaining > FCIP_ENCAP_HEADER_LEN) {
        if ((offset = get_next_fcip_header_offset (tvb, pinfo, offset)) == -1) {
            return FALSE;
        }
        else if (offset == -2) {
            /* We need more data to desegment */
            return (TRUE);
        }

        start = offset;
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCIP");

        frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;

        if (bytes_remaining < frame_len) {
            if(fcip_desegment && pinfo->can_desegment) {
                /*
                 * This frame doesn't have all of the data for
                 * this message, but we can do reassembly on it.
                 *
                 * Tell the TCP dissector where the data for this
                 * message starts in the data it handed us, and
                 * how many more bytes we need, and return.
                 */
                pinfo->desegment_offset = offset;
                pinfo->desegment_len = frame_len - bytes_remaining;
                return (TRUE);
            }
        }

        pflags = tvb_get_guint8 (tvb, start+8);

        if (tree) {
            if (FCIP_IS_SF (pflags)) {
                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP");
            }
            else if (tvb_bytes_exist (tvb, offset, offset+frame_len-4)) {
                sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);
                eof = tvb_get_guint8 (tvb, offset+frame_len - 4);

                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP (%s/%s)",
                                                     val_to_str (sof, fcip_sof_vals,
                                                                 "0x%x"),
                                                     val_to_str (eof, fcip_eof_vals,
                                                                 "0x%x"));
            }
            else {
                sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);

                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP (%s/%s)",
                                                     val_to_str (sof, fcip_sof_vals,
                                                                 "0x%x"),
                                                     "NA");
            }
            fcip_tree = proto_item_add_subtree (ti, ett_fcip);
            /* Dissect the Common FC Encap header */
            dissect_fcencap_header (tvb, fcip_tree, offset);

            offset += FCIP_ENCAP_HEADER_LEN;

            if (!FCIP_IS_SF (pflags)) {
                /* print SOF */
                proto_tree_add_item (fcip_tree, hf_fcip_sof, tvb, offset, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item (fcip_tree, hf_fcip_sof_c, tvb, offset+2, 1, ENC_BIG_ENDIAN);
                /* print EOF */

                offset += (frame_len-FCIP_ENCAP_HEADER_LEN-4);
                if (tvb_bytes_exist (tvb, offset, 4)) {
                    proto_tree_add_item (fcip_tree, hf_fcip_eof, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item (fcip_tree, hf_fcip_eof_c, tvb, offset+2, 1, ENC_BIG_ENDIAN);
                }
            }
        }

        /* Call the FC Dissector if this is carrying an FC frame */
        if (!FCIP_IS_SF(pflags)) {
            /* Set the SOF/EOF flags in the packet_info header */
            fc_data.sof_eof = 0;

            if (sof) {
                if ((sof == FCIP_SOFi3) || (sof == FCIP_SOFi2) || (sof == FCIP_SOFi4)) {
                    fc_data.sof_eof = FC_DATA_SOF_FIRST_FRAME;
                }
                else if (sof == FCIP_SOFf) {
                    fc_data.sof_eof = FC_DATA_SOF_SOFF;
                }

                if (eof != FCIP_EOFn) {
                    fc_data.sof_eof |= FC_DATA_EOF_LAST_FRAME;
                }
                else if (eof != FCIP_EOFt) {
                    fc_data.sof_eof |= FC_DATA_EOF_INVALID;
                }
            }

            /* Special frame bit is not set */
            next_tvb = tvb_new_subset_remaining (tvb, FCIP_ENCAP_HEADER_LEN+4);
            if (fc_handle) {
                fc_data.ethertype = 0;
                call_dissector_with_data(fc_handle, next_tvb, pinfo, tree, &fc_data);
            }
            else if (data_handle) {
                call_dissector (data_handle, next_tvb, pinfo, tree);
            }
        }
        else {
            col_set_str(pinfo->cinfo, COL_INFO, "Special Frame");
            if (FCIP_IS_CH (pflags)) {
                col_append_str(pinfo->cinfo, COL_INFO, "(Changed)");
            }

            dissect_fcip_sf (tvb, fcip_tree, offset+4);
        }

        bytes_remaining -= frame_len;
    }

    return (TRUE);
}
Esempio n. 18
0
/*
 * This function dissects an "Ice context", adds hf(s) to "tree" and returns consumed
 * bytes in "*consumed", if errors "*consumed" is -1.
 */
static void dissect_ice_context(packet_info *pinfo, proto_tree *tree, proto_item *item, 
								tvbuff_t *tvb, guint32 offset, gint32 *consumed)
{
	/*  p. 588, chapter 23.2.7 and p. 613, 23.3.2:
	 *  "context" is a dictionary<string, string>
	 *
	 * dictionary<string, string> == Size + SizeKeyValuePairs
	 * dictionary<string, string> = 1byte (0..254) + SizeKeyValuePairs
	 * or
	 * dictionary<string, string>= 1byte (255) + 1int (255..2^32-1)+SizeKeyValuePairs
	 *
	 */

	guint32 Size = 0; /* number of key-value in the dictionary */
	guint32 i = 0;
	const char *s = NULL;

	(*consumed) = 0;

	/* check first byte */
	if ( !tvb_bytes_exist(tvb, offset, 1) ) {

		if (item)
			expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "context missing");

		col_append_str(mypinfo->cinfo, COL_INFO,
				       " (context missing)");

		(*consumed) = -1;
		return;
	}

	/* get first byte of Size */
	Size = tvb_get_guint8(tvb, offset);
	offset++;
	(*consumed)++;

	if ( Size == 255 ) {

		/* check for next 4 bytes */
		if ( !tvb_bytes_exist(tvb, offset, 4) ) {

			if (item)
				expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "second field of Size missing");

			col_append_str(mypinfo->cinfo, COL_INFO, " (second field of Size missing)");

			(*consumed) = -1;
			return;
		}

		/* get second field of Size */
		Size = tvb_get_letohl(tvb, offset);
		offset += 4;
		(*consumed) += 4;
	}

	DBG1("context.Size --> %d\n", Size);

	if ( Size > icep_max_ice_context_pairs ) {

		if (item)
			/* display the XX Size byte when click here */
			expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "too long context");

		col_append_str(mypinfo->cinfo, COL_INFO, " (too long context)");

		(*consumed) = -1;
		return;
	}

	if (Size == 0) {
		s = "(empty)";
		/* display the 0x00 Size byte when click on a empty context */
		if (tree)
			proto_tree_add_string(tree, hf_icep_context, tvb, offset - 1, 1, s);
		return;
	}

	/* looping through the dictionary */
	for ( i = 0; i < Size; i++ ) {
		/* key */
		gint32 consumed_key = 0;
		char *str_key = NULL;
		/* value */
		gint32 consumed_value = 0;
		char *str_value = NULL;
		proto_item *ti = NULL;

		DBG1("looping through context dictionary, loop #%d\n", i);
		ti = proto_tree_add_text(tree, tvb, offset, -1, "Invocation Context");

		dissect_ice_string(pinfo, tree, ti, hf_icep_invocation_key, tvb, offset, &consumed_key, &str_key);

		if ( consumed_key == -1 ) {
			(*consumed) = -1;
			return;
		}

		offset += consumed_key;
		(*consumed) += consumed_key;

		dissect_ice_string(pinfo, tree, ti, hf_icep_invocation_value, tvb, offset, &consumed_value, &str_value);

		if ( consumed_value == -1 ) {
			(*consumed) = -1;
			return;
		}

		offset += consumed_value;
		(*consumed) += consumed_value;
		if (ti)
			proto_item_set_len(ti, (consumed_key + consumed_value) + 1);
	}
}
Esempio n. 19
0
static void
dissect_ifcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
    gint offset = 0, frame_len = 0;
    guint8 sof = 0, eof = 0;
    proto_item *ti;
    proto_tree *tree = NULL;
    tvbuff_t *next_tvb;
    guint8 protocol;
    proto_tree *protocol_tree=NULL;
    proto_tree *version_tree=NULL;
    proto_tree *frame_len_tree=NULL;
    proto_tree *sof_tree=NULL;
    proto_tree *eof_tree=NULL;

    /* verify we have a full header  (do we need to do this? */
    if(tvb_length(tvb)<iFCP_ENCAP_HEADER_LEN) {
        return;
    }

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

    frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;


    if (parent_tree) {
        if (tvb_bytes_exist (tvb, offset, frame_len-4)) {
            sof = tvb_get_guint8 (tvb, offset+iFCP_ENCAP_HEADER_LEN);
            eof = tvb_get_guint8 (tvb, offset+frame_len - 4);

            ti = proto_tree_add_protocol_format (parent_tree, proto_ifcp, tvb, offset,
                                                 iFCP_ENCAP_HEADER_LEN,
                                                 "iFCP (%s/%s)",
                                                 val_to_str (sof, ifcp_sof_vals,
                                                         "0x%x"),
                                                 val_to_str (eof, ifcp_eof_vals,
                                                         "0x%x"));
        } else {
            sof = tvb_get_guint8 (tvb, offset+iFCP_ENCAP_HEADER_LEN);

            ti = proto_tree_add_protocol_format (parent_tree, proto_ifcp, tvb, offset,
                                                 iFCP_ENCAP_HEADER_LEN,
                                                 "iFCP (%s/%s)",
                                                 val_to_str (sof, ifcp_sof_vals,
                                                         "0x%x"),
                                                 "NA");
        }
        tree = proto_item_add_subtree (ti, ett_ifcp);
    }



    /* The Common FC Encap header */
    /* protocol */
    protocol = tvb_get_guint8 (tvb, offset);
    ti=proto_tree_add_item(tree, hf_ifcp_protocol, tvb, offset, 1, 0);
    if(ti) {
        protocol_tree=proto_item_add_subtree(ti, ett_ifcp_protocol);
    }
    offset++;

    /* version */
    ti=proto_tree_add_item(tree, hf_ifcp_version, tvb, offset, 1, 0);
    if(ti) {
        version_tree=proto_item_add_subtree(ti, ett_ifcp_version);
    }
    offset++;

    /* protocol complement */
    proto_tree_add_item(protocol_tree, hf_ifcp_protocol_c, tvb, offset, 1, 0);
    offset++;

    /* version complement */
    proto_tree_add_item(version_tree, hf_ifcp_version_c, tvb, offset, 1, 0);
    offset++;

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

    /* iFCP specific fields */
    if(protocol==FCENCAP_PROTO_iFCP) {
        /* LS_COMMAND_ACC */
        proto_tree_add_item(tree, hf_ifcp_ls_command_acc, tvb, offset, 1, 0);
        offset++;

        /* iFCP Flags */
        offset=dissect_ifcpflags(tvb, offset, tree);

        /* SOF */
        ti=proto_tree_add_item(tree, hf_ifcp_sof, tvb, offset, 1, 0);
        if(ti) {
            sof_tree=proto_item_add_subtree(ti, ett_ifcp_sof);
        }
        offset++;

        /* EOF */
        ti=proto_tree_add_item(tree, hf_ifcp_eof, tvb, offset, 1, 0);
        if(ti) {
            eof_tree=proto_item_add_subtree(ti, ett_ifcp_eof);
        }
        offset++;
    } else {
        offset+=4;
        sof_tree=tree; /* better than nothing */
        eof_tree=tree;
    }

    /* Common Flags */
    dissect_commonflags(tvb, offset, tree);

    /* frame len */
    ti=proto_tree_add_item(tree, hf_ifcp_framelen, tvb, offset, 2, 0);
    if(ti) {
        frame_len_tree=proto_item_add_subtree(ti, ett_ifcp_frame_len);
    }
    offset+=2;

    /* complement of flags and frame len */
    proto_tree_add_item(frame_len_tree, hf_ifcp_encap_flags_c, tvb, offset, 1, 0);
    proto_tree_add_item(frame_len_tree, hf_ifcp_framelen_c, tvb, offset, 2, 0);
    offset+=2;

    /* timestamp seconds */
    proto_tree_add_item(tree, hf_ifcp_tsec, tvb, offset, 4, 0);
    offset+=4;

    /* timestamp fractions */
    proto_tree_add_item(tree, hf_ifcp_tusec, tvb, offset, 4, 0);
    offset+=4;

    /* crc */
    proto_tree_add_item(tree, hf_ifcp_encap_crc, tvb, offset, 4, 0);
    offset+=4;


    /* FC SOF/-SOF */
    proto_tree_add_item(sof_tree, hf_ifcp_sof, tvb, offset, 1, 0);
    offset++;
    proto_tree_add_item(sof_tree, hf_ifcp_sof, tvb, offset, 1, 0);
    offset++;
    proto_tree_add_item(sof_tree, hf_ifcp_sof_c, tvb, offset, 1, 0);
    offset++;
    proto_tree_add_item(sof_tree, hf_ifcp_sof_c, tvb, offset, 1, 0);
    offset++;

    /* FC EOF/-EOF */
    if(tvb_bytes_exist(tvb, frame_len-4, 4)) {
        proto_tree_add_item(eof_tree, hf_ifcp_eof, tvb, frame_len-4, 1, 0);
        proto_tree_add_item(eof_tree, hf_ifcp_eof, tvb, frame_len-3, 1, 0);
        proto_tree_add_item(eof_tree, hf_ifcp_eof_c, tvb, frame_len-2, 1, 0);
        proto_tree_add_item(eof_tree, hf_ifcp_eof_c, tvb, frame_len-1, 1, 0);
    }


    /* Call the FC Dissector if this is carrying an FC frame */
    /* Set the SOF/EOF flags in the packet_info header */
    pinfo->sof_eof = 0;

    switch(sof) {
    case iFCP_SOFi3:
    case iFCP_SOFi2:
    case iFCP_SOFi4:
        pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
        break;
    case iFCP_SOFf:
        pinfo->sof_eof = PINFO_SOF_SOFF;
        break;
    default:
        if(sof) {
            if (eof != iFCP_EOFn) {
                pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
            } else if (eof != iFCP_EOFt) {
                pinfo->sof_eof |= PINFO_EOF_INVALID;
            }
        }
    }

    next_tvb=tvb_new_subset(tvb, offset, frame_len-offset-4, frame_len-offset-4);

    if(fc_handle) {
        call_dissector(fc_handle, next_tvb, pinfo, parent_tree);
    } else if(data_handle) {
        call_dissector(data_handle, next_tvb, pinfo, parent_tree);
    }

    return;
}
Esempio n. 20
0
/*
 * This function dissects an "Ice params", adds hf(s) to "tree" and returns consumed
 * bytes in "*consumed", if errors "*consumed" is -1.
 */
static void dissect_ice_params(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
							   guint32 offset, gint32 *consumed)
{
	/*  p. 612, chapter 23.3.2 and p. 587, 23.2.2:
	 *  "params" is an Encapsulation
	 *
	 *  struct Encapsulation {
	 *  	int size;
	 *  	byte major;
	 *      byte minor;
	 *      //(size - 6) bytes of data
	 *  }
	 *
	 */

	gint32 size = 0;
	gint tvb_data_remained = 0;

	(*consumed) = 0;

	/* check first 6 bytes */
	if ( !tvb_bytes_exist(tvb, offset, ICEP_MIN_PARAMS_SIZE) ) {

		if (item)
			expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "params missing");

		col_append_str(mypinfo->cinfo, COL_INFO, " (params missing)");

		(*consumed) = -1;
		return;
	}

	/* get the size */
	size = tvb_get_letohl(tvb, offset);

	DBG1("params.size --> %d\n", size);

	if ( size < ICEP_MIN_PARAMS_SIZE ) {

		if (item)
			expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "params size too small");

		col_append_str(mypinfo->cinfo, COL_INFO, " (params size too small)");

		(*consumed) = -1;
		return;
	}

	if ( tree ) {

		proto_tree_add_item(tree, hf_icep_params_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;
		(*consumed) += 4;

		proto_tree_add_item(tree, hf_icep_params_major, tvb, offset, 1, ENC_LITTLE_ENDIAN);
		offset += 1;
		(*consumed)++;

		proto_tree_add_item(tree, hf_icep_params_minor, tvb, offset, 1, ENC_LITTLE_ENDIAN);
		offset += 1;
		(*consumed)++;

	} else {
		/* skip size, major, minor */
		offset += 6;
		(*consumed) += 6;
	}

	if( size == ICEP_MIN_PARAMS_SIZE ) /* no encapsulatd data present, it's normal */
		return;

	/* check if I got all encapsulated data */
	tvb_data_remained = tvb_reported_length_remaining(tvb, offset);

	if ( tvb_data_remained < ( size - ICEP_MIN_PARAMS_SIZE ) ) {

		if (item)
			expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "missing encapsulated data (%d bytes)",
									size - ICEP_MIN_PARAMS_SIZE - tvb_data_remained);

		if ( check_col(mypinfo->cinfo, COL_INFO) ) {
			col_append_fstr(mypinfo->cinfo, COL_INFO,
					" (missing encapsulated data (%d bytes))",
					size
					- ICEP_MIN_PARAMS_SIZE
					- tvb_data_remained);
		}

		(*consumed) = -1;
		return;
	}

	/* encapsulated params */

	if (tree) {
		proto_tree_add_item(tree, hf_icep_params_encapsulated, tvb, offset, (size - ICEP_MIN_PARAMS_SIZE), ENC_LITTLE_ENDIAN);
	}

	(*consumed) += (size - ICEP_MIN_PARAMS_SIZE);
}
static void
dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree     *clnp_tree;
    proto_item     *ti, *ti_len = NULL, *ti_pdu_len = NULL, *ti_tot_len = NULL;
    guint8          cnf_proto_id;
    guint8          cnf_hdr_len;
    guint8          cnf_vers;
    guint8          cnf_ttl;
    guint8          cnf_type;
    char            flag_string[6+1];
    const char     *pdu_type_string;
    proto_tree     *type_tree;
    guint16         segment_length;
    guint16         du_id = 0;
    guint16         segment_offset = 0;
    guint16         total_length;
    guint16         cnf_cksum;
    cksum_status_t  cksum_status;
    int             offset;
    guchar          src_len, dst_len, nsel, opt_len = 0;
    const guint8   *dst_addr, *src_addr;
    guint           next_length;
    proto_tree     *discpdu_tree;
    gboolean        save_in_error_pkt;
    fragment_head  *fd_head;
    tvbuff_t       *next_tvb;
    gboolean        update_col_info = TRUE;
    gboolean        save_fragmented;
    heur_dtbl_entry_t *hdtbl_entry;

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

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

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

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

    ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA);
    clnp_tree = proto_item_add_subtree(ti, ett_clnp);
    proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
            cnf_proto_id);
    ti_len = proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
            cnf_hdr_len);
    if (cnf_hdr_len < FIXED_PART_LEN) {
        /* Header length is less than the length of the fixed part of
           the header. */
        expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
                "Header length value < minimum length %u",
                FIXED_PART_LEN);
        return;
    }
    proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
                cnf_vers);
    cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
    proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
            cnf_ttl,
            "Holding Time : %u (%u.%u secs)",
            cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
    cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
    pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
            "Unknown (0x%02x)");
    flag_string[0] = '\0';
    if (cnf_type & CNF_SEG_OK)
        g_strlcat(flag_string, "S ", 7);
    if (cnf_type & CNF_MORE_SEGS)
        g_strlcat(flag_string, "M ", 7);
    if (cnf_type & CNF_ERR_OK)
        g_strlcat(flag_string, "E ", 7);
    ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
            cnf_type,
            "PDU Type     : 0x%02x (%s%s)",
            cnf_type,
            flag_string,
            pdu_type_string);
    type_tree = proto_item_add_subtree(ti, ett_clnp_type);
    proto_tree_add_item(type_tree, hf_clnp_cnf_segmentation, tvb, P_CLNP_TYPE, 1, ENC_NA);
    proto_tree_add_item(type_tree, hf_clnp_cnf_more_segments, tvb, P_CLNP_TYPE, 1, ENC_NA);
    proto_tree_add_item(type_tree, hf_clnp_cnf_report_error, tvb, P_CLNP_TYPE, 1, ENC_NA);
    proto_tree_add_item(type_tree, hf_clnp_cnf_type, tvb, P_CLNP_TYPE, 1, ENC_NA);

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

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

    segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
    ti_pdu_len = proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
            segment_length);
    if (segment_length < cnf_hdr_len) {
        /* Segment length is less than the header length. */
        expert_add_info_format(pinfo, ti_pdu_len, &ei_clnp_length,
                "PDU length < header length %u", cnf_hdr_len);
        return;
    }
    cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
    cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
    switch (cksum_status) {
        default:
            /*
             * No checksum present, or not enough of the header present to
             * checksum it.
             */
            proto_tree_add_uint(clnp_tree, hf_clnp_checksum, tvb,
                    P_CLNP_CKSUM, 2,
                    cnf_cksum);
            break;

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

        case CKSUM_NOT_OK:
            /*
             * Checksum is not correct.
             */
            proto_tree_add_uint_format_value(clnp_tree, hf_clnp_checksum, tvb,
                    P_CLNP_CKSUM, 2,
                    cnf_cksum,
                    "0x%04x (incorrect)",
                    cnf_cksum);
            break;
    }

    opt_len = cnf_hdr_len;
    opt_len -= FIXED_PART_LEN; /* Fixed part of Header */

    /* address part */

    offset = P_CLNP_ADDRESS_PART;
    if (opt_len < 1) {
        /* Header length is less than the minimum value in CLNP,
           including the destination address length. */
        expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
                "Header length value < %u",
                FIXED_PART_LEN + 1);
        return;
    }
    dst_len  = tvb_get_guint8(tvb, offset);
    if (tree) {
        proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
                dst_len);
    }
    offset += 1;
    opt_len -= 1;

    if (opt_len < dst_len) {
        /* Header length is less than the minimum value,
           including the destination address length and the
           destination address. */
        expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
                "Header length value < %u",
                FIXED_PART_LEN + 1 + dst_len);
        return;
    }
    dst_addr = tvb_get_ptr(tvb, offset, dst_len);
    nsel     = tvb_get_guint8(tvb, offset + dst_len - 1);
    SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
    SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);
    proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_dest, tvb, offset, dst_len,
            dst_addr,
            "%s",
            print_nsap_net(dst_addr, dst_len));
    offset += dst_len;
    opt_len -= dst_len;

    if (opt_len < 1) {
        /* Header length is less than the minimum value,
           including the destination address length, the
           destination address, and the source address length. */
        expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
                "Header length value < %u",
                FIXED_PART_LEN + 1 + dst_len + 1);
        return;
    }
    src_len  = tvb_get_guint8(tvb, offset);
    if (tree) {
        proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
                offset, 1, src_len);
    }
    offset += 1;
    opt_len -= 1;

    if (opt_len < src_len) {
        /* Header length is less than the minimum value,
           including the destination address length, the
           destination address, the source address length,
           and the source address. */
        expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
                "Header length value < %u",
                FIXED_PART_LEN + 1 + dst_len + 1 + src_len);
        return;
    }
    src_addr = tvb_get_ptr(tvb, offset, src_len);
    SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
    SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
    proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_src, tvb,
            offset, src_len,
            src_addr,
            "%s",
            print_nsap_net(src_addr, src_len));

    offset += src_len;
    opt_len -= src_len;

    /* Segmentation Part */

    if (cnf_type & CNF_SEG_OK) {
        if (opt_len < SEGMENTATION_PART_LEN) {
            /* Header length is less than the minimum value,
               including the destination address length, the
               destination address, the source address length,
               the source address, and the segmentation part. */
            expert_add_info_format(pinfo, ti_len, &ei_clnp_length,
                    "Header length value < %u",
                    FIXED_PART_LEN + 1 + dst_len + 1 + SEGMENTATION_PART_LEN);
            return;
        }
        du_id = tvb_get_ntohs(tvb, offset);
        proto_tree_add_text(clnp_tree, tvb, offset, 2,
                "Data unit identifier: %06u",
                du_id);
        segment_offset = tvb_get_ntohs(tvb, offset + 2);
        proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
                "Segment offset      : %6u",
                segment_offset);
        total_length = tvb_get_ntohs(tvb, offset + 4);
        ti_tot_len = proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
                "Total length        : %6u",
                total_length);
        if (total_length < segment_length) {
            /* Reassembled length is less than the length of this segment. */
            expert_add_info_format(pinfo, ti_tot_len, &ei_clnp_length,
                    "Total length < segment length %u", segment_length);
            return;
        }
        offset  += SEGMENTATION_PART_LEN;
        opt_len -= SEGMENTATION_PART_LEN;
    }

    dissect_osi_options(opt_len, tvb, offset, clnp_tree);

    offset += opt_len;

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

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

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

            /* Get a tvbuff for the payload.  Set its length to the segment
               length, and flag it as a fragment, so going past the end
               reports FragmentBoundsError, i.e. "there's data missing
               because this isn't reassembled", not ReportedBoundsError,
               i.e. "the dissector ran past the end of the packet, so the
               packet must not have been constructed properly". */
            next_tvb = tvb_new_subset_length(tvb, offset, segment_length - cnf_hdr_len);
            tvb_set_fragment(next_tvb);

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

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

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

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

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

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

                break;

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

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

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

                    call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);

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

            case ERQ_NPDU:
            case ERP_NPDU:
                /* XXX - dissect this */
                break;
        }
    }
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
    call_dissector(data_handle,next_tvb, pinfo, tree);
    pinfo->fragmented = save_fragmented;
} /* dissect_clnp */
Esempio n. 22
0
static void dissect_icep_request_common(tvbuff_t *tvb, guint32 offset,
					packet_info *pinfo, proto_tree *icep_sub_tree, proto_item* icep_sub_item, gint32 *total_consumed)
{
	/*  p. 613, chapter 23.3.3 and p. 612 chapter 23.3.2:
	 *  Request and BatchRequest differ only in the first 4 bytes (requestID)
	 *  so them share this part
	 *
	 *	 Ice::Identity id;
	 *	 Ice::StringSeq facet;
	 *	 string operation;
	 *	 byte mode;
	 *	 Ice::Context context;
	 *	 Encapsulation params;
	 *  }
	 */

	gint32 consumed = 0;
	char *namestr = NULL;
	char *opstr = NULL;

	(*total_consumed) = 0;

	/* check common header (i.e. the batch request one)*/
	if ( !tvb_bytes_exist(tvb, offset, ICEP_MIN_COMMON_REQ_HEADER_SIZE) ) {

		if (icep_sub_item)
			expert_add_info_format(pinfo, icep_sub_item, PI_MALFORMED, PI_ERROR, "too short header");

		col_append_str(mypinfo->cinfo, COL_INFO,
				       " (too short header)");

		goto error;
	}

	/* got at least 15 bytes */

	/*  "id" is a:
	 *  struct Identity {
	 *      string name;
	 *	string category;
	 *  }
	 */

	dissect_ice_string(pinfo, icep_sub_tree, icep_sub_item, hf_icep_id_name, tvb, offset, &consumed, &namestr);

	if ( consumed == -1 )
		goto error;

	offset += consumed; DBG1("consumed --> %d\n", consumed);
	(*total_consumed) += consumed;


	dissect_ice_string(pinfo, icep_sub_tree, icep_sub_item, hf_icep_id_category, tvb, offset, &consumed, NULL);

	if ( consumed == -1 )
		goto error;

	offset += consumed; DBG1("consumed --> %d\n", consumed);
	(*total_consumed) += consumed;


	/*  "facet" is a:
	 *  sequence<string> StringSeq
	 *
	 */

	dissect_ice_facet(pinfo, icep_sub_tree, icep_sub_item, hf_icep_facet, tvb, offset, &consumed);

	if ( consumed == -1 )
		goto error;

	offset += consumed; DBG1("consumed --> %d\n", consumed);
	(*total_consumed) += consumed;

	/*  "operation" is an ice_string
	 *
	 */

	dissect_ice_string(pinfo, icep_sub_tree, icep_sub_item, hf_icep_operation, tvb, offset, &consumed, &opstr);

	if ( consumed == -1 )
		goto error;
	else {
		offset += consumed; DBG1("consumed --> %d\n", consumed);
		(*total_consumed) += consumed;

		if ( opstr && namestr ) {
			DBG2("operation --> %s.%s()\n", namestr, opstr);
			if ( check_col(mypinfo->cinfo, COL_INFO) ) {
				col_append_fstr(mypinfo->cinfo, COL_INFO, " %s.%s()",
						namestr, opstr);
			}
			opstr = NULL;
			namestr = NULL;
		}
	}

	/* check and get mode byte */
	if ( !tvb_bytes_exist(tvb, offset, 1) ) {

		if (icep_sub_item)
			expert_add_info_format(pinfo, icep_sub_item, PI_MALFORMED, PI_ERROR, "mode field missing");

		col_append_str(mypinfo->cinfo, COL_INFO, " (mode field missing)");
		goto error;
	}

	if (icep_sub_tree)
		proto_tree_add_item(icep_sub_tree, hf_icep_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);

	offset++; DBG0("consumed --> 1\n");
	(*total_consumed)++;


	/*  "context" is a dictionary<string, string>
	 *
	 */

	dissect_ice_context(pinfo, icep_sub_tree, icep_sub_item, tvb, offset, &consumed);

	if ( consumed == -1 )
		goto error;

	offset += consumed; DBG1("consumed --> %d\n", consumed);
	(*total_consumed) += consumed;

	/*  "params" is a Encapsulation
	 *
	 */

	dissect_ice_params(pinfo, icep_sub_tree, icep_sub_item, tvb, offset, &consumed);

	if ( consumed == -1 )
		goto error;

	/*offset += consumed;*/
	 DBG1("consumed --> %d\n", consumed);
	(*total_consumed) += consumed;

	return;

error:
	(*total_consumed) = -1;
}
Esempio n. 23
0
static void
dissect_fip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    guint       op;
    guint       sub;
    guint       rlen;
    proto_item *ti;
    proto_item *item;
    proto_tree *fip_tree;
    proto_tree *subtree;
    guint       dtype;
    guint       dlen;
    guint       desc_offset;
    guint       val;
    tvbuff_t   *desc_tvb;
    const char *info;
    char       *text;

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

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

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

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

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

    rlen = tvb_get_ntohs(tvb, 6);

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

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

    desc_offset = FIP_HEADER_LEN;
    rlen *= FIP_BPW;
    proto_tree_add_text(fip_tree, tvb, desc_offset, rlen, "Descriptors:");

    while ((rlen > 0) && tvb_bytes_exist(tvb, desc_offset, 2)) {
        dlen = tvb_get_guint8(tvb, desc_offset + 1) * FIP_BPW;
        if (!dlen) {
            proto_tree_add_text(fip_tree, tvb, desc_offset, -1,
                    "Descriptor [length error]");
            break;
        }
        if (!tvb_bytes_exist(tvb, desc_offset, dlen) || dlen > rlen) {
            break;
        }
        desc_tvb = tvb_new_subset(tvb, desc_offset, dlen, -1);
        dtype = tvb_get_guint8(desc_tvb, 0);
        desc_offset += dlen;
        rlen -= dlen;

        item = proto_tree_add_text(fip_tree, desc_tvb, 0, -1, "Descriptor: %s ",
          val_to_str(dtype, fip_desc_types, "Unknown 0x%x"));

        switch (dtype) {
        case FIP_DT_PRI:
            subtree = proto_item_add_subtree(item, ett_fip_dt_pri);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_pri, desc_tvb,
                    3, 1, ENC_BIG_ENDIAN);
            proto_item_append_text(item, "%u", tvb_get_guint8(desc_tvb, 3));
            break;
        case FIP_DT_MAC:
            subtree = proto_item_add_subtree(item, ett_fip_dt_mac);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_mac, desc_tvb,
                    2, 6, ENC_NA);
            proto_item_append_text(item, "%s",
                    tvb_bytes_to_str_punct(desc_tvb, 2, 6, ':'));
            break;
        case FIP_DT_MAP_OUI:
            subtree = proto_item_add_subtree(item, ett_fip_dt_map);
            fip_desc_type_len(subtree, desc_tvb);
            text = tvb_fc_to_str(desc_tvb, 5);
            proto_tree_add_string(subtree, hf_fip_desc_map, desc_tvb,
                    5, 3, text);
            proto_item_append_text(item, "%s", text);
            break;
        case FIP_DT_NAME:
            subtree = proto_item_add_subtree(item, ett_fip_dt_name);
            fip_desc_type_len(subtree, desc_tvb);
            text = tvb_fcwwn_to_str(desc_tvb, 4);
            proto_tree_add_string(subtree, hf_fip_desc_name,
                    desc_tvb, 4, 8, text);
            proto_item_append_text(item, "%s", text);
            break;
        case FIP_DT_FAB:
            subtree = proto_item_add_subtree(item, ett_fip_dt_fab);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_fab_vfid, desc_tvb,
                    2, 2, ENC_BIG_ENDIAN);
            text = tvb_fc_to_str(desc_tvb, 5);
            proto_tree_add_string(subtree, hf_fip_desc_fab_map, desc_tvb,
                    5, 3, text);
            text = tvb_fcwwn_to_str(desc_tvb, 8);
            proto_tree_add_string(subtree, hf_fip_desc_fab_name,
                    desc_tvb, 8, 8, text);
            proto_item_append_text(item, "%s", text);
            break;
        case FIP_DT_FCOE_SIZE:
            subtree = proto_item_add_subtree(item, ett_fip_dt_mdl);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_fcoe_size, desc_tvb,
                    2, 2, ENC_BIG_ENDIAN);
            proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2));
            break;
        case FIP_DT_FLOGI:
        case FIP_DT_FDISC:
        case FIP_DT_LOGO:
        case FIP_DT_ELP: {
            tvbuff_t *ls_tvb;
            subtree = proto_item_add_subtree(item, ett_fip_dt_caps);
            fip_desc_type_len(subtree, desc_tvb);
            ls_tvb = tvb_new_subset(desc_tvb, 4, dlen - 4, -1);
            call_dissector(fc_handle, ls_tvb, pinfo, subtree);
            proto_item_append_text(item, "%u bytes", dlen - 4);
        }
            break;
        case FIP_DT_VN:
            subtree = proto_item_add_subtree(item, ett_fip_dt_vn);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_vn_mac, desc_tvb,
                    2, 6, ENC_NA);
            proto_tree_add_item(subtree, hf_fip_desc_vn_fid, desc_tvb,
                    9, 3, ENC_BIG_ENDIAN);
            text = tvb_fcwwn_to_str(desc_tvb, 12);
            proto_tree_add_string(subtree, hf_fip_desc_vn_wwpn,
                    desc_tvb, 12, 8, text);
            proto_item_append_text(item, "MAC %s  FC_ID %6.6x",
                    tvb_bytes_to_str_punct(desc_tvb, 2, 6, ':'),
                    tvb_get_ntoh24(desc_tvb, 9));
            break;
        case FIP_DT_FKA:
            subtree = proto_item_add_subtree(item, ett_fip_dt_fka);
            fip_desc_type_len(subtree, desc_tvb);
            val = tvb_get_ntohl(desc_tvb, 4);
            proto_tree_add_uint_format_value(subtree, hf_fip_desc_fka,
                    desc_tvb, 4, 4, val, "%u ms", val);
            proto_item_append_text(item, "%u ms", val);
            break;
        case FIP_DT_VEND:
            subtree = proto_item_add_subtree(item, ett_fip_dt_vend);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_vend, desc_tvb,
                    4, 8, ENC_NA);
            if (tvb_bytes_exist(desc_tvb, 9, -1)) {
                proto_tree_add_item(subtree, hf_fip_desc_vend_data,
                     desc_tvb, 9, -1, ENC_NA);
            }
            break;
        case FIP_DT_VLAN:
            subtree = proto_item_add_subtree(item, ett_fip_dt_vlan);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_vlan, desc_tvb,
                    2, 2, ENC_BIG_ENDIAN);
            proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2));
            break;
        case FIP_DT_FC4F:
            subtree = proto_item_add_subtree(item, ett_fip_dt_fc4f);
            fip_desc_type_len(subtree, desc_tvb);
            fip_desc_fc4f(desc_tvb, subtree, item);
            break;
        default:
            subtree = proto_item_add_subtree(item, ett_fip_dt_unk);
            fip_desc_type_len(subtree, desc_tvb);
            proto_tree_add_item(subtree, hf_fip_desc_unk, desc_tvb,
                    2, -1, ENC_NA);
            break;
        }
    }
}
Esempio n. 24
0
static void dissect_icep_request(tvbuff_t *tvb, guint32 offset, 
								 packet_info *pinfo, proto_tree *icep_tree, proto_item* icep_item)
{
	/*  p. 612, chapter 23.3.2:
	 *
	 *  struct RequestData {
	 * 	 int requestID;
	 *	 Ice::Identity id;
	 *	 Ice::StringSeq facet;
	 *	 string operation;
	 *	 byte mode;
	 *	 Ice::Context context;
	 *	 Encapsulation params;
	 *  }
	 */

	proto_item *ti = NULL;
	proto_tree *icep_sub_tree = NULL;
	gint32 consumed = 0;
	guint32 reqid = 0;

	DBG0("dissect request\n");

	/* check for req id */
	if ( !tvb_bytes_exist(tvb, offset, 4) ) {

		if (icep_item)
			expert_add_info_format(pinfo, icep_item, PI_MALFORMED, PI_ERROR, "too short header");

		col_append_str(mypinfo->cinfo, COL_INFO, " (too short header)");

		return;
	}

	/* got at least 4 bytes */

	/* create display subtree for this message type */

	reqid = tvb_get_letohl(tvb, offset);

	if (icep_tree) {

		ti = proto_tree_add_text(icep_tree, tvb, offset, -1,
					 "Request Message Body");

		icep_sub_tree = proto_item_add_subtree(ti, ett_icep_msg);

		proto_tree_add_item(icep_sub_tree, hf_icep_request_id, tvb, offset, 4,
				    ENC_LITTLE_ENDIAN);

	}

	if ( reqid != 0 ) {
		if ( check_col(mypinfo->cinfo, COL_INFO) ) {
			col_append_fstr(mypinfo->cinfo, COL_INFO, "(%d):",
					tvb_get_letohl(tvb, offset));
		}
	} else
		col_append_str(mypinfo->cinfo, COL_INFO, "(oneway):");


	offset += 4;
	DBG0("consumed --> 4\n");

	dissect_icep_request_common(tvb, offset, pinfo, icep_sub_tree, ti, &consumed);

	if ( consumed == -1 )
		return;

	/*offset += consumed;*/
	DBG1("consumed --> %d\n", consumed);
}
Esempio n. 25
0
static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
	proto_tree *tree, proto_tree *tns_tree)
{
	proto_tree *data_tree = NULL, *ti;
	proto_item *hidden_item;
	int is_sns = 0;

	if ( tvb_bytes_exist(tvb, offset+2, 4) )
	{
		if ( tvb_get_guint8(tvb, offset+2) == 0xDE &&
		     tvb_get_guint8(tvb, offset+3) == 0xAD &&
		     tvb_get_guint8(tvb, offset+4) == 0xBE &&
		     tvb_get_guint8(tvb, offset+5) == 0xEF )
		{
			is_sns = 1;
		}
	}

	if ( tree )
	{
		if ( is_sns )
		{
			ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
			    "Secure Network Services");
		}
		else
		{
			ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
			    "Data");
		}
		data_tree = proto_item_add_subtree(ti, ett_tns_data);

		hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_data, tvb, 0, 0,
					TRUE);
		PROTO_ITEM_SET_HIDDEN(hidden_item);
	}

	if ( tree )
	{
		proto_tree *df_tree = NULL;

		ti = proto_tree_add_item(data_tree, hf_tns_data_flag, tvb, offset, 2, ENC_BIG_ENDIAN);

		df_tree = proto_item_add_subtree(ti, ett_tns_data_flag);
		proto_tree_add_item(df_tree, hf_tns_data_flag_send, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_rc, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_c, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_more, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_eof, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_dic, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_rts, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_sntt, tvb, offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( is_sns )
	{
		col_append_str(pinfo->cinfo, COL_INFO, ", SNS");
	}
	else
	{
		col_append_str(pinfo->cinfo, COL_INFO, ", Data");
	}

	call_dissector(data_handle,
		    tvb_new_subset_remaining(tvb, offset), pinfo, data_tree);

	return;
}
Esempio n. 26
0
static void dissect_icep_batch_request(tvbuff_t *tvb, guint32 offset,
										packet_info *pinfo, proto_tree *icep_tree, proto_item* icep_item)
{
	/*  p. 613, chapter 23.3.3
	 *  A batch request msg is a "sequence" of batch request
	 *  Sequence is Size + elements
	 *
	 *  struct BatchRequestData {
	 *	 Ice::Identity id;
	 *	 Ice::StringSeq facet;
	 *	 string operation;
	 *	 byte mode;
	 *	 Ice::Context context;
	 *	 Encapsulation params;
	 *  }
	 *
	 * NOTE!!!:
	 * The only real implementation of the Ice protocol puts a 32bit count in front
	 * of a Batch Request, *not* an Ice::Sequence (as the standard says). Basically the
	 * same people wrote both code and standard so I'll follow the code.
	 */

	proto_item *ti = NULL;
	proto_tree *icep_sub_tree = NULL;
	guint32 num_reqs = 0;
	guint32 i = 0;
	gint32 consumed = 0;

	DBG0("dissect batch request\n");

	/* check for first 4 byte */
	if ( !tvb_bytes_exist(tvb, offset, 4) ) {

		if (icep_item)
			expert_add_info_format(pinfo, icep_item, PI_MALFORMED, PI_ERROR, "counter of batch requests missing");

		col_append_str(mypinfo->cinfo, COL_INFO,
				       " (counter of batch requests missing)");

		return;
	}

	num_reqs = tvb_get_letohl(tvb, offset);
	offset += 4;

	DBG1("batch_requests.count --> %d\n", num_reqs);

	if ( num_reqs > icep_max_batch_requests ) {

		if (icep_item)
			expert_add_info_format(pinfo, icep_item, PI_PROTOCOL, PI_WARN, "too many batch requests (%d)", num_reqs);

		if ( check_col(mypinfo->cinfo, COL_INFO) ) {
			col_append_fstr(mypinfo->cinfo, COL_INFO,
					" (too many batch requests, %d)",
					num_reqs);
		}

		return;
	}

	if ( num_reqs == 0 ) {

		if (icep_tree)
			proto_tree_add_text(icep_tree, tvb, offset, -1,
					    "empty batch requests sequence");
		col_append_str(mypinfo->cinfo, COL_INFO,
					" (empty batch requests sequence)");

		return;
	}


	col_append_str(mypinfo->cinfo, COL_INFO,
				":");

	/*
	 * process requests
	 */

	for ( i = 0; i < num_reqs; i++ ) {

		DBG1("looping through sequence of batch requests, loop #%d\n", i);

		/* create display subtree for this message type */

		if (icep_tree) {

			ti = proto_tree_add_text(icep_tree, tvb, offset, -1,
						 "Batch Request Message Body: #%d", i);

			icep_sub_tree = proto_item_add_subtree(ti, ett_icep_msg);

		}

		if ( check_col(mypinfo->cinfo, COL_INFO) && (i != 0) ) {
			col_append_str(mypinfo->cinfo, COL_INFO,
					",");
		}

		dissect_icep_request_common(tvb, offset, pinfo, icep_sub_tree, ti, &consumed);

		if ( consumed == -1 )
			return;

		if ( icep_tree && ti )
			proto_item_set_len(ti, consumed);

		offset += consumed;
		DBG1("consumed --> %d\n", consumed);
	}
}
Esempio n. 27
0
/* Dissect details of packet */
static void rlogin_display(rlogin_hash_entry_t *hash_info,
			   tvbuff_t *tvb,
			   packet_info *pinfo,
			   proto_tree *tree,
			   struct tcpinfo *tcpinfo)
{
	/* Display the proto tree */
	int             offset = 0;
	proto_tree      *rlogin_tree, *user_info_tree, *window_tree;
	proto_item      *ti;
	guint           length;
	int             str_len;
	gint            ti_offset;
	proto_item      *user_info_item, *window_info_item;

	/* Create rlogin subtree */
	ti = proto_tree_add_item(tree, proto_rlogin, tvb, 0, -1, ENC_NA);
	rlogin_tree = proto_item_add_subtree(ti, ett_rlogin);

	/* Return if data empty */
	length = tvb_captured_length(tvb);
	if (length == 0)
	{
		return;
	}

	/*
	 * XXX - this works only if the urgent pointer points to something
	 * in this segment; to make it work if the urgent pointer points
	 * to something past this segment, we'd have to remember the urgent
	 * pointer setting for this conversation.
	 */
	if (tcpinfo && IS_TH_URG(tcpinfo->flags) &&      /* if urgent pointer set */
	    length >= tcpinfo->urgent_pointer) /* and it's in this frame */
	{
		/* Get urgent byte into Temp */
		int urgent_offset = tcpinfo->urgent_pointer - 1;
		guint8 control_byte;

		/* Check for text data in front */
		if (urgent_offset > offset)
		{
			proto_tree_add_item(rlogin_tree, hf_data, tvb, offset, urgent_offset, ENC_ASCII|ENC_NA);
		}

		/* Show control byte */
		proto_tree_add_item(rlogin_tree, hf_control_message, tvb,
		                    urgent_offset, 1, ENC_BIG_ENDIAN);
		control_byte = tvb_get_guint8(tvb, urgent_offset);
		col_append_fstr(pinfo->cinfo, COL_INFO,
			               " (%s)", val_to_str_const(control_byte, control_message_vals, "Unknown"));

		offset = urgent_offset + 1; /* adjust offset */
	}
	else
	if (tvb_get_guint8(tvb, offset) == '\0')
	{
		/* Startup */
		if (pinfo->srcport == RLOGIN_PORT)   /* from server */
		{
			proto_tree_add_item(rlogin_tree, hf_startup_info_received_flag,
			                    tvb, offset, 1, ENC_BIG_ENDIAN);
		}
		else
		{
			proto_tree_add_item(rlogin_tree, hf_client_startup_flag,
			                    tvb, offset, 1, ENC_BIG_ENDIAN);
		}
		++offset;
	}

	if (!tvb_offset_exists(tvb, offset))
	{
		/* No more data to check */
		return;
	}

	if (hash_info->info_framenum == pinfo->num)
	{
		gint info_len;
		gint slash_offset;

		/* First frame of conversation, assume user info... */

		info_len = tvb_captured_length_remaining(tvb, offset);
		if (info_len <= 0)
			return;

		/* User info tree */
		user_info_item = proto_tree_add_string_format(rlogin_tree, hf_user_info, tvb,
		                                              offset, info_len, FALSE,
		                                              "User info (%s)",
		                                              tvb_format_text(tvb, offset, info_len));
		user_info_tree = proto_item_add_subtree(user_info_item,
		                                        ett_rlogin_user_info);

		/* Client user name. */
		str_len = tvb_strsize(tvb, offset);
		proto_tree_add_item(user_info_tree, hf_user_info_client_user_name,
		                    tvb, offset, str_len, ENC_ASCII|ENC_NA);
		offset += str_len;

		/* Server user name. */
		str_len = tvb_strsize(tvb, offset);
		proto_tree_add_item(user_info_tree, hf_user_info_server_user_name,
		                    tvb, offset, str_len, ENC_ASCII|ENC_NA);
		offset += str_len;

		/* Terminal type/speed. */
		slash_offset = tvb_find_guint8(tvb, offset, -1, '/');
		if (slash_offset != -1)
		{
			guint8* str = NULL;
			guint32 term_len = 0;
			gboolean term_len_valid;
			proto_item* pi = NULL;

			/* Terminal type */
			proto_tree_add_item(user_info_tree, hf_user_info_terminal_type,
			                    tvb, offset, slash_offset-offset, ENC_ASCII|ENC_NA);
			offset = slash_offset + 1;

			/* Terminal speed */
			str_len = tvb_strsize(tvb, offset);
			str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, str_len,
				ENC_NA|ENC_ASCII);
			term_len_valid = ws_strtou32(str, NULL, &term_len);
			pi = proto_tree_add_uint(user_info_tree,
				hf_user_info_terminal_speed,
				tvb, offset, str_len, term_len);
			if (!term_len_valid)
				expert_add_info(pinfo, pi, &ei_rlogin_termlen_invalid);

			offset += str_len;
		}
	}

	if (!tvb_offset_exists(tvb, offset))
	{
		/* No more data to check */
		return;
	}

	/* Test for terminal information, the data will have 2 0xff bytes */
	/* look for first 0xff byte */
	ti_offset = tvb_find_guint8(tvb, offset, -1, 0xff);

	/* Next byte must also be 0xff */
	if (ti_offset != -1 &&
	    tvb_bytes_exist(tvb, ti_offset + 1, 1) &&
	    tvb_get_guint8(tvb, ti_offset + 1) == 0xff)
	{
		guint16 rows, columns;

		/* Have found terminal info. */
		if (ti_offset > offset)
		{
			/* There's data before the terminal info. */
			proto_tree_add_item(rlogin_tree, hf_data, tvb,
			                    offset, ti_offset - offset, ENC_ASCII|ENC_NA);
		}

		/* Create window info tree */
		window_info_item =
			proto_tree_add_item(rlogin_tree, hf_window_info, tvb, offset, 12, ENC_NA);
		window_tree = proto_item_add_subtree(window_info_item, ett_rlogin_window);

		/* Cookie */
		proto_tree_add_item(window_tree, hf_magic_cookie, tvb, offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		/* These bytes should be "ss" */
		proto_tree_add_item(window_tree, hf_window_info_ss, tvb, offset, 2, ENC_ASCII|ENC_NA);
		offset += 2;

		/* Character rows */
		rows = tvb_get_ntohs(tvb, offset);
		proto_tree_add_item(window_tree, hf_window_info_rows, tvb,
		                    offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		/* Characters per row */
		columns = tvb_get_ntohs(tvb, offset);
		proto_tree_add_item(window_tree, hf_window_info_cols, tvb,
		                    offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		/* x pixels */
		proto_tree_add_item(window_tree, hf_window_info_x_pixels, tvb,
		                    offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		/* y pixels */
		proto_tree_add_item(window_tree, hf_window_info_y_pixels, tvb,
		                    offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		/* Show setting highlights in info column */
		col_append_fstr(pinfo->cinfo, COL_INFO, " (rows=%u, cols=%u)",
			                rows, columns);
	}

	if (tvb_offset_exists(tvb, offset))
	{
		/* There's more data in the frame. */
		proto_tree_add_item(rlogin_tree, hf_data, tvb, offset, -1, ENC_ASCII|ENC_NA);
	}
}
Esempio n. 28
0
static void dissect_icep_reply(tvbuff_t *tvb, guint32 offset, 
							   packet_info *pinfo, proto_tree *icep_tree, proto_item* icep_item)
{
	/*  p. 614, chapter 23.3.4:
	 *
	 *  struct ReplyData {
	 * 	 int requestId;
	 *	 byte replyStatus;
	 *	 [... messageSize - 19 bytes ...  ]
	 *  }
	 */

	gint32 messageSize = 0;
	guint32 tvb_data_remained = 0;
	guint32 reported_reply_data = 0;
	proto_item *ti = NULL;
	proto_tree *icep_sub_tree = NULL;

	DBG0("dissect reply\n");

	/* get at least a full reply message header */

	if ( !tvb_bytes_exist(tvb, offset, ICEP_MIN_REPLY_SIZE) ) {

		if (icep_item)
			expert_add_info_format(pinfo, icep_item, PI_MALFORMED, PI_ERROR, "too short header");

		col_append_str(mypinfo->cinfo, COL_INFO, " (too short header)");
		return;
	}

	/* got 5 bytes, then data */

	/* create display subtree for this message type */

	if (icep_tree) {

		ti = proto_tree_add_text(icep_tree, tvb, offset, -1,
					 "Reply Message Body");

		icep_sub_tree = proto_item_add_subtree(ti, ett_icep_msg);

		proto_tree_add_item(icep_sub_tree, hf_icep_request_id, tvb, offset, 4,
				    ENC_LITTLE_ENDIAN);
	}

	if ( check_col(mypinfo->cinfo, COL_INFO) ) {
		col_append_fstr(mypinfo->cinfo, COL_INFO, "(%d):",
				tvb_get_letohl(tvb, offset));
	}

	offset += 4;

	if (icep_tree)
		proto_tree_add_item(icep_sub_tree, hf_icep_reply_status, tvb, offset, 1,
				    ENC_LITTLE_ENDIAN);

	if ( check_col(mypinfo->cinfo, COL_INFO) ) {
		col_append_fstr(mypinfo->cinfo, COL_INFO, " %s",
				val_to_str_const(tvb_get_guint8(tvb, offset),
                                                 icep_replystatus_vals,
                                                 "unknown reply status"));
	}

	offset++;

	DBG1("consumed --> %d\n", 5);

	/* check if I got all reply data */
	tvb_data_remained = tvb_length_remaining(tvb, offset);
	messageSize = tvb_get_letohl(tvb, 10);
	reported_reply_data = messageSize - (ICEP_HEADER_SIZE + ICEP_MIN_REPLY_SIZE);

	/* no */
	if ( tvb_data_remained < reported_reply_data ) {

		if (icep_sub_tree)
			expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Reply Data (missing %d bytes out of %d)", 
									reported_reply_data - tvb_data_remained, 
									reported_reply_data);

		if ( check_col(mypinfo->cinfo, COL_INFO) ) {
			col_append_fstr(mypinfo->cinfo, COL_INFO,
					" (missing reply data, %d bytes)",
					reported_reply_data - tvb_data_remained);
		}

		/*offset += tvb_data_remained;*/
		DBG1("consumed --> %d\n", tvb_data_remained);
		return;
	}

	/* yes (reported_reply_data can be 0) */

	if (icep_sub_tree) {
		proto_tree_add_item(icep_sub_tree, hf_icep_reply_data, tvb, offset, reported_reply_data, ENC_NA);
	}

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

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

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

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

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

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

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

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

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

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

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

    if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
        pinfo->fragmented = save_fragmented;
    return;
}
Esempio n. 30
0
/* 
 * This function dissects an "Ice string", adds hf to "tree" and returns consumed 
 * bytes in "*consumed", if errors "*consumed" is -1.
 *
 * "*dest" is a null terminated version of the dissected Ice string.
 */
static void dissect_ice_string(proto_tree *tree, int hf_icep, 
			       tvbuff_t *tvb, guint32 offset, gint32 *consumed,
			       char **dest, gboolean add_hf)
{
	/* p. 586 chapter 23.2.1 and p. 588 chapter 23.2.5 
	 * string == Size + content 
	 * string = 1byte (0..254) + string not null terminated 
	 * or                                                  
	 * string = 1byte (255) + 1int (255..2^32-1) + string not null terminated 
	 */
	
	guint32 Size = 0;
	char *s = NULL;
	
	(*consumed) = 0;
	
	/* check for first byte */
	if ( !tvb_bytes_exist(tvb, offset, 1) ) {
		
		if (tree)
			proto_tree_add_text(tree, tvb, offset, -1, 
					    "1st byte of Size missing");
		
		if ( check_col(mypinfo->cinfo, COL_INFO) ) {
			col_append_str(mypinfo->cinfo, COL_INFO, 
				       " (1st byte of Size missing)");
		}
		
		(*consumed) = -1;
		return;
	}
	
	/* get the Size */
	Size = tvb_get_guint8(tvb, offset);
	offset++;
	(*consumed)++;
	
	if ( Size == 255 ) {
		
		/* check for next 4 bytes */
		if ( !tvb_bytes_exist(tvb, offset, 4) ) {
			
			if (tree)
				proto_tree_add_text(tree, tvb, offset, -1,
						    "second field of Size missing");
			
			if ( check_col(mypinfo->cinfo, COL_INFO) ) {
				col_append_str(mypinfo->cinfo, COL_INFO, 
					       " (second field of Size missing)");
			}
			
			(*consumed) = -1;
			return;
		}
		
		/* get second field of Size */
		Size = tvb_get_letohl(tvb, offset);
		offset += 4;
		(*consumed) += 4;
	}
	
	DBG1("string.Size --> %d\n", Size);
	
	/* check if the string exists */
	if ( !tvb_bytes_exist(tvb, offset, Size) ) {
		
		if (tree)
			proto_tree_add_text(tree, tvb, offset, -1, 
					    "missing or truncated string");
		
		if ( check_col(mypinfo->cinfo, COL_INFO) ) {
			col_append_str(mypinfo->cinfo, COL_INFO, 
				       " (missing or truncated string)");
		}
		
		(*consumed) = -1;
		return;
	}

	if ( Size > ICEP_MAX_ICE_STRING_LEN ) {
		
		if (tree)
			proto_tree_add_text(tree, tvb, offset, -1, "string too long");
		
		if ( check_col(mypinfo->cinfo, COL_INFO) ) {
			col_append_str(mypinfo->cinfo, COL_INFO, 
				       " (string too long)");
		}
		
		(*consumed) = -1;
		return;
	}
	
	
		
	if ( Size != 0 ) {
		s = tvb_get_ephemeral_string(tvb, offset, Size);
		if (tree && add_hf)
			proto_tree_add_string(tree, hf_icep, tvb, offset, Size, s);
	} else {
		s = g_strdup("(empty)");
		/* display the 0x00 Size byte when click on a empty ice_string */
		if (tree && add_hf)
			proto_tree_add_string(tree, hf_icep, tvb, offset - 1, 1, s);
	}
	
	if ( dest != NULL )
		*dest = s;
	
	offset += Size;
	(*consumed) += Size;
	return;
}