static void
dissect_componentstatusprotocol_componentstatusreport_message(tvbuff_t *message_tvb, proto_tree *message_tree)
{
  tvbuff_t   *association_tvb;
  proto_tree *association_tree;
  /* gint        associations; - variable set but not used, so commented out */
  int         i;
  gint        offset;

  proto_tree_add_item(message_tree, hf_componentstatusreport_reportinterval, message_tvb, COMPONENTSTATUSREPORT_REPORTINTERVAL_OFFSET, COMPONENTSTATUSREPORT_REPORTINTERVAL_LENGTH, ENC_BIG_ENDIAN);
  proto_tree_add_item(message_tree, hf_componentstatusreport_location,       message_tvb, COMPONENTSTATUSREPORT_LOCATION_OFFSET,       COMPONENTSTATUSREPORT_LOCATION_LENGTH,       ENC_ASCII|ENC_NA);
  proto_tree_add_item(message_tree, hf_componentstatusreport_status,         message_tvb, COMPONENTSTATUSREPORT_STATUS_OFFSET,         COMPONENTSTATUSREPORT_STATUS_LENGTH,         ENC_ASCII|ENC_NA);
  proto_tree_add_item(message_tree, hf_componentstatusreport_workload,       message_tvb, COMPONENTSTATUSREPORT_WORKLOAD_OFFSET,       COMPONENTSTATUSREPORT_WORKLOAD_LENGTH,       ENC_BIG_ENDIAN);
  proto_tree_add_item(message_tree, hf_componentstatusreport_associations,   message_tvb, COMPONENTSTATUSREPORT_ASSOCIATIONS_OFFSET,   COMPONENTSTATUSREPORT_ASSOCIATIONS_LENGTH,   ENC_BIG_ENDIAN);

  /* associations = tvb_get_ntohs(message_tvb, COMPONENTSTATUSREPORT_ASSOCIATIONS_OFFSET); */
  offset = COMPONENTSTATUSREPORT_ASSOCIATIONARRAY_OFFSET;
  i = 1;
  while(tvb_reported_length_remaining(message_tvb, offset) >= COMPONENTASSOCIATION_LENGTH) {
     association_tree = proto_tree_add_subtree_format(message_tree, message_tvb, offset, COMPONENTASSOCIATION_LENGTH,
         ett_association, NULL, "Association #%d", i++);
     association_tvb  = tvb_new_subset_length_caplen(message_tvb, offset,
                                       MIN(COMPONENTASSOCIATION_LENGTH, tvb_reported_length_remaining(message_tvb, offset)),
                                       COMPONENTASSOCIATION_LENGTH);

     dissect_componentstatusprotocol_componentassociation_message(association_tvb, association_tree);
     offset += COMPONENTASSOCIATION_LENGTH;
  }
}
static int
krb5rpc_dissect_sendto_kdc_rqst (tvbuff_t * tvb, int offset,
                                 packet_info * pinfo, proto_tree * tree,
                                 dcerpc_info *di, guint8 *drep)
{
  guint32 keysize, spare1, remain;
  proto_item *item;
  tvbuff_t *krb5_tvb;
  proto_tree *subtree;


  /*
   *        [in]        handle_t        h,
   *        [in]        unsigned32      len,
   *        [in, size_is(len)]
   *        byte            message[],
   *        [in]        unsigned32      out_buf_len,
   */

  offset =
    dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
                       hf_krb5rpc_sendto_kdc_rqst_keysize, &keysize);
  offset =
    dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
                       hf_krb5rpc_sendto_kdc_rqst_spare1, &spare1);
  item = proto_tree_add_item (tree, hf_krb5rpc_krb5, tvb, offset, -1, ENC_NA);
  subtree = proto_item_add_subtree (item, ett_krb5rpc_krb5);

  remain = tvb_captured_length_remaining(tvb, offset);
  krb5_tvb = tvb_new_subset_length_caplen (tvb, offset, remain, remain);
  offset = dissect_kerberos_main (krb5_tvb, pinfo, subtree, TRUE, NULL);


  return offset;
}
static int
krb5rpc_dissect_sendto_kdc_resp (tvbuff_t * tvb, int offset,
                                 packet_info * pinfo, proto_tree * tree,
                                 dcerpc_info *di, guint8 *drep)
{
  guint32 resp_len, maxsize, spare1, keysize, remain;
  proto_item *item;
  tvbuff_t *krb5_tvb;
  proto_tree *subtree;


  /*
   *
   *        [out]       unsigned32      *resp_len,
   *        [out, length_is(*resp_len), size_is(out_buf_len)]
   *        byte            out_buf[],
   *        [out]       error_status_t  *st unsigned long
   *
   */

  offset =
    dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
                       hf_krb5rpc_sendto_kdc_resp_len, &resp_len);
  offset =
    dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
                       hf_krb5rpc_sendto_kdc_resp_max, &maxsize);
  offset =
    dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
                       hf_krb5rpc_sendto_kdc_resp_spare1, &spare1);
  offset =
    dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
                       hf_krb5rpc_sendto_kdc_resp_keysize, &keysize);


  item = proto_tree_add_item (tree, hf_krb5rpc_krb5, tvb, offset, -1, ENC_NA);
  subtree = proto_item_add_subtree (item, ett_krb5rpc_krb5);
  remain = tvb_captured_length_remaining(tvb, offset);
  krb5_tvb = tvb_new_subset_length_caplen (tvb, offset, remain, remain);

  offset = dissect_kerberos_main (krb5_tvb, pinfo, subtree, TRUE, NULL);
  offset += 16; /* no idea what this is, probably just extended encrypted text. */

  return offset;
}
Esempio n. 4
0
static void
gcsna_message_GCSNA1xCircuitService(proto_item *item, tvbuff_t *tvb, packet_info *pinfo, proto_tree *mainTree, proto_tree *tree, guint *offset)
{
    guint16 alt_gcsna_incl = 0, num_alt_gcsna_opt = -1, iws_incl = 0;
    guint8 num_res;
    guint bit_offset = *offset * 8;
    proto_tree *subtree = NULL;
    tvbuff_t *new_tvb;

    /* GCSNAOption 8 bits */
    item = proto_tree_add_item(tree, hf_gcsna_gcsna_option, tvb, *offset, 1, ENC_BIG_ENDIAN);
    subtree = proto_item_add_subtree(item, ett_gcsna_option);
    proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClass, tvb, bit_offset, 5, ENC_BIG_ENDIAN);
    bit_offset += 5;
    proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClassRev, tvb, bit_offset, 3, ENC_BIG_ENDIAN);
    bit_offset += 3;

    alt_gcsna_incl = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(subtree, hf_gcsna_altGCSNAOptionIncluded, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset += 1;
    if (alt_gcsna_incl)
    {
        num_alt_gcsna_opt = tvb_get_bits8(tvb, bit_offset, 8);
        proto_tree_add_bits_item(subtree, hf_gcsna_NumaltGCSNAOption, tvb, bit_offset, 8, ENC_BIG_ENDIAN);
        bit_offset += 8;

        while (num_alt_gcsna_opt != 0)
        {
            proto_tree_add_bits_item(subtree, hf_gcsna_altGCSNAOption, tvb, bit_offset, 8, ENC_BIG_ENDIAN);
            bit_offset += 8;
            num_alt_gcsna_opt--;
        }
    }

    iws_incl = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(subtree, hf_gcsna_iwsidIncluded, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (iws_incl)
    {
        proto_tree_add_bits_item(subtree, hf_gcsna_iwsidValue, tvb, bit_offset, 16, ENC_BIG_ENDIAN);
        bit_offset += 16;
    }

    proto_tree_add_bits_item(subtree, hf_gcsna_ackRequired, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;
    proto_tree_add_bits_item(subtree, hf_gcsna_stopDupDetect, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;
    proto_tree_add_bits_item(subtree, hf_gcsna_msgSequence, tvb, bit_offset, 6, ENC_BIG_ENDIAN);
    bit_offset += 6;

    proto_tree_add_bits_item(subtree, hf_gcsna_NumTLACEncapsulated1xL3PDU, tvb, bit_offset, 2, ENC_BIG_ENDIAN);
    bit_offset += 2;

    /* The sender shall include reserved bits to make this message integral number of octets up to TLACEncapsulated1xL3PDU field.
     * The sender 5 shall set all bits in this field to '0'. The receiver shall ignore this field.
     */

     /* calculate number of reserved bits */
    num_res = 8 - (bit_offset & 0x3);
    proto_tree_add_bits_item(subtree, hf_gcsna_tlacReserved, tvb, bit_offset, num_res, ENC_BIG_ENDIAN);
    bit_offset = bit_offset + num_res;
    *offset = bit_offset >> 3;

    proto_tree_add_item(subtree, hf_gcsna_tlacEncapsulated, tvb, *offset, -1, ENC_NA);

    if (cdma2k_handle) {
        new_tvb = tvb_new_subset_length_caplen(tvb, *offset, -1, -1);
        call_dissector(cdma2k_handle, new_tvb, pinfo, mainTree);
    }
    /* set the offset to the end of the message */
    *offset += tvb_reported_length_remaining(tvb, *offset);

}
Esempio n. 5
0
static int
dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int frame_offset,int ltp_type, guint64 session_num)
{
	guint64 client_id;
	guint64 data_offset;
	guint64 data_length;
	guint64 chkp_sno = 0;
	guint64 rpt_sno = 0;
	guint64 sda_client_id = 0;

	unsigned segment_size = 0;

	int sdnv_length;
	int sdnv_status;

	proto_tree *ltp_data_tree;
	proto_item *ti;

	fragment_head *frag_msg = NULL;
	gboolean more_frags = TRUE;

	tvbuff_t *new_tvb = NULL;

	/* Create a subtree for data segment and add the other fields under it */
	ltp_data_tree = proto_tree_add_subtree(ltp_tree, tvb, frame_offset, tvb_captured_length_remaining(tvb, frame_offset), ett_data_segm, NULL, "Data Segment");


	/* Client ID - 0 = Bundle Protocol, 1 = CCSDS LTP Service Data Aggregation */
	sdnv_status = evaluate_sdnv64(tvb, frame_offset, &sdnv_length, &client_id);
	ti = proto_tree_add_uint64_format_value(ltp_data_tree, hf_ltp_data_clid, tvb, frame_offset, sdnv_length, client_id,
						"%" G_GINT64_MODIFIER "u (%s)", client_id,
						val_to_str_const((const guint32) client_id, client_service_id_info, "Invalid"));
	if (!sdnv_status) {
		expert_add_info(pinfo, ti, &ei_ltp_sdnv_length);
		return 0;
	}
	frame_offset += sdnv_length;
	segment_size += sdnv_length;


	/* data segment offset */
	if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_offset, &data_offset, &ti)) > 0) {
		frame_offset += sdnv_length;
		segment_size += sdnv_length;
	} else {
		return 0;
	}

	/* data segment length */
	if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_length, &data_length, &ti)) > 0) {
		frame_offset += sdnv_length;
		segment_size += sdnv_length;

		/* add in the data length also */
		segment_size += (unsigned int) data_length;
	} else {
		return 0;
	}

	more_frags = FALSE;
	if (ltp_type != 0 && ltp_type < 4)
	{
		/* checkpoint serial number - 32 bits per CCSDS */
		if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_chkp, &chkp_sno, &ti)) > 0) {
			frame_offset += sdnv_length;
			segment_size += sdnv_length;

			if (chkp_sno > 4294967295U) {
				/* just a warning - continue processing */
				expert_add_info(pinfo, ti, &ei_ltp_sno_larger_than_ccsds);
			}
		} else {
			return 0;
		}

		/* report serial number - 32 bits per CCSDS */
		if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_rpt, &rpt_sno, &ti)) > 0) {
			frame_offset += sdnv_length;
			segment_size += sdnv_length;

			if (rpt_sno > 4294967295U) {
				/* just a warning - continue processing */
				expert_add_info(pinfo, ti, &ei_ltp_sno_larger_than_ccsds);
			}
		} else {
			return 0;
		}

	} else if (ltp_type != 7) {
		more_frags = TRUE;

	}

	if (segment_size >= tvb_captured_length(tvb)) {
		/* did not capture the entire packet */
		proto_tree_add_string(ltp_data_tree, hf_ltp_partial_packet, tvb, 0, 0, "<increase capture size?>");
		return tvb_captured_length(tvb);
	}

	frag_msg = fragment_add_check(&ltp_reassembly_table,
					tvb, frame_offset, pinfo, (guint32)session_num, NULL,
					(guint32)data_offset, (guint32)data_length, more_frags);

	if(frag_msg)
	{
		/* Checking if the segment is completely reassembled */
		if(!(frag_msg->flags & FD_PARTIAL_REASSEMBLY))
		{
			/* if the segment has not been fragmented, then no reassembly is needed */
			if(!more_frags && data_offset == 0)
			{
				new_tvb = tvb_new_subset_remaining(tvb, frame_offset);
			}
			else
			{
				new_tvb = process_reassembled_data(tvb, frame_offset, pinfo, "Reassembled LTP Segment",
									frag_msg, &ltp_frag_items,NULL, ltp_data_tree);

			}
		}
	}

	if(new_tvb)
	{
		int data_count = 1;

		int parse_length;
		int parse_offset = 0;
		parse_length = tvb_captured_length(new_tvb);
		while(parse_offset < parse_length)
		{
			int bundle_size;
			int sda_header_size;
			proto_tree *ltp_data_data_tree;
			tvbuff_t *datatvb;
			ltp_data_data_tree = proto_tree_add_subtree_format(ltp_data_tree, tvb,frame_offset, 0,
										ett_data_data_segm, NULL, "Data[%d]",data_count);

			sda_header_size = 0;
			if (client_id == 2) {
				sdnv_status = evaluate_sdnv64(tvb, frame_offset+parse_offset, &sdnv_length, &sda_client_id);
				ti = proto_tree_add_uint64_format_value(ltp_data_data_tree, hf_ltp_data_sda_clid, tvb, frame_offset+parse_offset, sdnv_length, sda_client_id,
									"%" G_GINT64_MODIFIER "u (%s)", sda_client_id, val_to_str_const((const guint32) sda_client_id, client_service_id_info, "Invalid"));

				if (!sdnv_status) {
					expert_add_info(pinfo, ti, &ei_ltp_sdnv_length);
					return 0;
				}

				sda_header_size = sdnv_length;

				parse_offset += sdnv_length;
				if (parse_offset == parse_length) {
					col_set_str(pinfo->cinfo, COL_INFO, "CCSDS LTP SDA Protocol Error");
					return 0;	/* Give up*/
				}
			}

			datatvb = tvb_new_subset_length_caplen(new_tvb, parse_offset, (int)parse_length - parse_offset, tvb_captured_length(new_tvb));
			bundle_size = call_dissector(bundle_handle, datatvb, pinfo, ltp_data_data_tree);
			if(bundle_size == 0) {  /*Couldn't parse bundle*/
				col_set_str(pinfo->cinfo, COL_INFO, "Dissection Failed");
				return 0;           /*Give up*/
			}

			/* update the length of the data set */
			proto_item_set_len(ltp_data_data_tree, bundle_size+sda_header_size);

			parse_offset += bundle_size;
			data_count++;
		}
	}
	else
	{
		if(frag_msg && more_frags)
		{
			col_append_frame_number(pinfo, COL_INFO, "[Reassembled in %d] ",frag_msg->reassembled_in);
		}
		else
		{
			col_append_str(pinfo->cinfo, COL_INFO, "[Unfinished LTP Segment] ");
		}

	}

	return segment_size;
}
Esempio n. 6
0
static gint
dissect_adb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item      *main_item;
    proto_tree      *main_tree;
    proto_item      *arg0_item;
    proto_tree      *arg0_tree;
    proto_item      *arg1_item;
    proto_tree      *arg1_tree;
    proto_item      *magic_item;
    proto_item      *crc_item;
    proto_tree      *crc_tree = NULL;
    proto_item      *sub_item;
    gint             offset = 0;
    guint32          command;
    guint32          arg0;
    guint32          arg1;
    guint32          data_length = 0;
    guint32          crc32 = 0;
    usb_conv_info_t *usb_conv_info = NULL;
    wmem_tree_key_t  key[5];
    guint32          interface_id;
    guint32          bus_id;
    guint32          device_address;
    guint32          side_id;
    guint32          frame_number;
    gboolean         is_command = TRUE;
    gboolean         is_next_fragment = FALSE;
    gboolean         is_service = FALSE;
    gint             proto;
    gint             direction = P2P_DIR_UNKNOWN;
    wmem_tree_t     *wmem_tree;
    command_data_t  *command_data = NULL;
    service_data_t  *service_data = NULL;

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

    main_item = proto_tree_add_item(tree, proto_adb, tvb, offset, -1, ENC_NA);
    main_tree = proto_item_add_subtree(main_item, ett_adb);

    frame_number       = pinfo->num;

    /* XXX: Why? If interface is USB only first try is correct
     * (and seems strange...), in other cases standard check for
     * previous protocol is correct */
    proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(/*wmem_list_frame_prev*/(wmem_list_tail(pinfo->layers))));
    if (proto != proto_usb) {
        proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers))));
    }

    if (proto == proto_usb) {
        usb_conv_info = (usb_conv_info_t *) data;
        DISSECTOR_ASSERT(usb_conv_info);

        direction = usb_conv_info->direction;
    } else if (proto == proto_tcp) {
        if (pinfo->destport == ADB_TCP_PORT)
            direction = P2P_DIR_SENT;
        else
            direction = P2P_DIR_RECV;
    } else {
        return offset;
    }

    if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
        interface_id = pinfo->phdr->interface_id;
    else
        interface_id = 0;

    if (proto == proto_usb) {
        bus_id             = usb_conv_info->bus_id;
        device_address     = usb_conv_info->device_address;

        key[0].length = 1;
        key[0].key = &interface_id;
        key[1].length = 1;
        key[1].key = &bus_id;
        key[2].length = 1;
        key[2].key = &device_address;
        key[3].length = 0;
        key[3].key = NULL;
    } else { /* tcp */
        key[0].length = 1;
        key[0].key = &interface_id;
        key[1].length = 1;
        key[2].length = 1;
        if (direction == P2P_DIR_SENT) {
            key[1].key = &pinfo->srcport;
            key[2].key = &pinfo->destport;
        } else {
            key[1].key = &pinfo->destport;
            key[2].key = &pinfo->srcport;
        }
        key[3].length = 0;
        key[3].key = NULL;
    }

    wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key);
    if (wmem_tree) {
        command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
        if (command_data && command_data->completed_in_frame >= frame_number &&
                command_data->command_in_frame <= frame_number) {

            if (command_data->command_in_frame != frame_number) {
                is_command = FALSE;
                is_next_fragment = TRUE;
            }

            data_length = command_data->data_length;
            crc32 = command_data->crc32;

            if (direction == P2P_DIR_SENT) {
                if (command_data->command == A_CLSE)
                    side_id = command_data->arg1; /* OUT: local id */
                else
                    side_id = command_data->arg0; /* OUT: local id */
            } else {
                    side_id = command_data->arg1; /* IN: remote id */
            }

            key[3].length = 1;
            key[3].key = &side_id;
            key[4].length = 0;
            key[4].key = NULL;

            wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key);
            if (wmem_tree) {
                service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
                if (service_data && command_data->command == A_OPEN) {
                    is_service = TRUE;
                }
            }
        }
    }

/* Simple heuristics to check if packet is command or data */
    if ((command_data && command_data->completed_in_frame <= frame_number) || !command_data) {
        if (tvb_reported_length(tvb) < 24) {
            is_command = FALSE;
        } else if (tvb_reported_length(tvb) >= 24) {
            command = tvb_get_letohl(tvb, offset);

            if (command != A_SYNC && command != A_CLSE && command != A_WRTE &&
                    command != A_AUTH && command != A_CNXN && command != A_OPEN && command != A_OKAY)
                is_command = FALSE;
            else if (command != (0xFFFFFFFF ^ tvb_get_letohl(tvb, offset + 20)))
                is_command = FALSE;

            if (is_command) {
                data_length = tvb_get_letohl(tvb, offset + 12);
                crc32 = tvb_get_letohl(tvb, offset + 16);
            }
            if (command == A_OPEN) is_service = TRUE;
        }
    }

    if (service_data && !(command_data->command == A_OPEN && is_next_fragment)) {
        sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service_data->service);
        PROTO_ITEM_SET_GENERATED(sub_item);
    }

    if (service_data) {
        sub_item = proto_tree_add_uint(main_tree, hf_service_start_in_frame, tvb, offset, 0, service_data->start_in_frame);
        PROTO_ITEM_SET_GENERATED(sub_item);

        if (service_data->close_local_in_frame < max_in_frame) {
            sub_item = proto_tree_add_uint(main_tree, hf_close_local_in_frame, tvb, offset, 0, service_data->close_local_in_frame);
            PROTO_ITEM_SET_GENERATED(sub_item);
        }

        if (service_data->close_remote_in_frame < max_in_frame) {
            sub_item = proto_tree_add_uint(main_tree, hf_close_remote_in_frame, tvb, offset, 0, service_data->close_remote_in_frame);
            PROTO_ITEM_SET_GENERATED(sub_item);
        }
    }

    if (is_command) {
        proto_tree_add_item(main_tree, hf_command, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        command = tvb_get_letohl(tvb, offset);
        offset += 4;

        col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(command, command_vals, "Unknown command"));

        arg0_item = proto_tree_add_item(main_tree, hf_argument_0, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        arg0_tree = proto_item_add_subtree(arg0_item, ett_adb_arg0);
        arg0 = tvb_get_letohl(tvb, offset);
        offset += 4;

        arg1_item = proto_tree_add_item(main_tree, hf_argument_1, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        arg1_tree = proto_item_add_subtree(arg1_item, ett_adb_arg1);
        arg1 = tvb_get_letohl(tvb, offset);
        offset += 4;

        switch (command) {
        case A_CNXN:
            proto_tree_add_item(arg0_tree, hf_version, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_max_data, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(version=%u.%u.%u, max_data=%u)", tvb_get_guint8(tvb, offset - 5), tvb_get_guint8(tvb, offset - 6), tvb_get_letohs(tvb, offset - 7), tvb_get_letohl(tvb, offset - 4));
            break;
        case A_AUTH:
            proto_tree_add_item(arg0_tree, hf_auth_type, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(type=%s, 0)", val_to_str_const(tvb_get_letohl(tvb, offset - 8), auth_type_vals, "Unknown"));
            break;
        case A_OPEN:
            proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, 0)", tvb_get_letohl(tvb, offset - 8));
            break;
        case A_WRTE:
            proto_tree_add_item(arg0_tree, hf_zero, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(0, remote=%u)", tvb_get_letohl(tvb, offset - 4));
            break;
        case A_CLSE:
        case A_OKAY:
            proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, remote=%u)", tvb_get_letohl(tvb, offset - 8), tvb_get_letohl(tvb, offset - 4));
            break;
        case A_SYNC:
            proto_tree_add_item(arg0_tree, hf_online, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_sequence, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(online=%s, sequence=%u)", tvb_get_letohl(tvb, offset - 8) ? "Yes": "No", tvb_get_letohl(tvb, offset - 4));
            break;
        }

        proto_tree_add_item(main_tree, hf_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        offset += 4;

        if (data_length > 0)
            col_append_fstr(pinfo->cinfo, COL_INFO, " length=%u ", data_length);

        crc_item = proto_tree_add_item(main_tree, hf_data_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc);
        crc32 = tvb_get_letohl(tvb, offset);
        offset += 4;

        magic_item = proto_tree_add_item(main_tree, hf_magic, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        if ((tvb_get_letohl(tvb, offset) ^ 0xFFFFFFFF) != command) {
            proto_tree  *expert_tree;

            expert_tree = proto_item_add_subtree(magic_item, ett_adb_magic);
            proto_tree_add_expert(expert_tree, pinfo, &ei_invalid_magic, tvb, offset, 4);
        }

        if (!pinfo->fd->flags.visited)
            save_command(command, arg0, arg1, data_length, crc32, service_data, proto, data, pinfo, &service_data, &command_data);
        offset += 4;
    }

    if (!pinfo->fd->flags.visited && command_data) {
            if (command_data->command_in_frame != frame_number) {
                is_command = FALSE;
                is_next_fragment = TRUE;
            }

            data_length = command_data->data_length;
            crc32 = command_data->crc32;

            if ((command_data->command_in_frame != frame_number && tvb_captured_length(tvb) == data_length) ||
                (command_data->command_in_frame == frame_number && tvb_captured_length(tvb) == data_length + 24)
            ) {
                command_data->reassemble_data_length = command_data->data_length;
                command_data->completed_in_frame = frame_number;
            }
    }

    if (is_next_fragment && command_data) {
        sub_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_in_frame);
        PROTO_ITEM_SET_GENERATED(sub_item);

        sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 0, command_data->command);
        PROTO_ITEM_SET_GENERATED(sub_item);

        sub_item = proto_tree_add_uint(main_tree, hf_data_length, tvb, offset, 0, command_data->data_length);
        PROTO_ITEM_SET_GENERATED(sub_item);

        crc_item = proto_tree_add_uint(main_tree, hf_data_crc32, tvb, offset, 0, command_data->crc32);
        crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc);
        PROTO_ITEM_SET_GENERATED(crc_item);
    }

    if (command_data && command_data->completed_in_frame != frame_number) {
        sub_item = proto_tree_add_uint(main_tree, hf_completed_in_frame, tvb, offset, 0, command_data->completed_in_frame);
        PROTO_ITEM_SET_GENERATED(sub_item);
    }


    if (tvb_captured_length_remaining(tvb, offset) > 0 && (!is_command || data_length > 0)) {
        guint32 crc = 0;
        guint32 i_offset;

        if ((!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) || data_length > (guint32) tvb_captured_length_remaining(tvb, offset)) { /* need reassemble */
            if (!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) {
                tvb_memcpy(tvb, command_data->reassemble_data + command_data->reassemble_data_length, offset, tvb_captured_length_remaining(tvb, offset));
                command_data->reassemble_data_length += tvb_captured_length_remaining(tvb, offset);

                if (command_data->reassemble_data_length >= command_data->data_length)
                    command_data->completed_in_frame = frame_number;
            }

            proto_tree_add_item(main_tree, hf_data_fragment, tvb, offset, -1, ENC_NA);
            col_append_str(pinfo->cinfo, COL_INFO, "Data Fragment");
            offset = tvb_captured_length(tvb);

            if (service_data && command_data && command_data->reassemble_data_length >= command_data->data_length && frame_number == command_data->completed_in_frame) {
                tvbuff_t            *next_tvb;
                adb_service_data_t   adb_service_data;

                next_tvb = tvb_new_child_real_data(tvb, command_data->reassemble_data, command_data->reassemble_data_length, command_data->reassemble_data_length);
                add_new_data_source(pinfo, next_tvb, "ADB Reassembled Data");

                adb_service_data.service = service_data->service;
                adb_service_data.direction = direction;

                adb_service_data.session_key_length = 3;
                adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32));
                adb_service_data.session_key[0] = interface_id;

                if (proto == proto_usb) {
                    adb_service_data.session_key[1] = usb_conv_info->bus_id;
                    adb_service_data.session_key[2] = usb_conv_info->device_address;
                } else { /* tcp */
                    if (direction == P2P_DIR_SENT) {
                        adb_service_data.session_key[1] = pinfo->srcport;
                        adb_service_data.session_key[2] = pinfo->destport;
                    } else {
                        adb_service_data.session_key[1] = pinfo->destport;
                        adb_service_data.session_key[2] = pinfo->srcport;
                    }
                }

                call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data);
            }
        } else { /* full message */
            for (i_offset = 0; i_offset < data_length; ++i_offset)
                crc += tvb_get_guint8(tvb, offset + i_offset);

            if (crc32 > 0 && crc32 != crc)
                proto_tree_add_expert(crc_tree, pinfo, &ei_invalid_crc, tvb, offset, -1);

            if (is_service) {
                proto_tree_add_item(main_tree, hf_service, tvb, offset, -1, ENC_ASCII | ENC_NA);
                if (!pinfo->fd->flags.visited && service_data) {
                    service_data->service = tvb_get_stringz_enc(wmem_file_scope(), tvb, offset, NULL, ENC_ASCII);
                }
                col_append_fstr(pinfo->cinfo, COL_INFO, "Service: %s", tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, NULL, ENC_ASCII));
                offset = tvb_captured_length(tvb);
            } else if (command_data && command_data->command == A_CNXN) {
                    gchar       *info;
                    gint         len;

                info = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Info: %s", info);
                proto_tree_add_item(main_tree, hf_connection_info, tvb, offset, len, ENC_ASCII | ENC_NA);
                offset += len;
            } else {
                col_append_str(pinfo->cinfo, COL_INFO, "Data");

                /* Decode service payload */
                if (service_data) {
                    tvbuff_t           *next_tvb;
                    adb_service_data_t  adb_service_data;

                    adb_service_data.service = service_data->service;
                    adb_service_data.direction = direction;

                    adb_service_data.session_key_length = 3;
                    adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32));
                    adb_service_data.session_key[0] = interface_id;

                    if (proto == proto_usb) {
                        adb_service_data.session_key[1] = usb_conv_info->bus_id;
                        adb_service_data.session_key[2] = usb_conv_info->device_address;
                    } else { /* tcp */
                        if (direction == P2P_DIR_SENT) {
                            adb_service_data.session_key[1] = pinfo->srcport;
                            adb_service_data.session_key[2] = pinfo->destport;
                        } else {
                            adb_service_data.session_key[1] = pinfo->destport;
                            adb_service_data.session_key[2] = pinfo->srcport;
                        }
                    }

                    next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset));
                    call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data);

                } else {
                    proto_item  *data_item;
                    gchar       *data_str;

                    data_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, data_length, ENC_NA);
                    data_str = tvb_format_text(tvb, offset, data_length);
                    proto_item_append_text(data_item, ": %s", data_str);
                    col_append_fstr(pinfo->cinfo, COL_INFO, " Raw: %s", data_str);
                }

                offset = tvb_captured_length(tvb);
            }
        }
    }

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

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

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

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

        length_remaining = tvb_captured_length_remaining(tvb, offset);

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

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

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

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

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

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

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

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

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

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

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

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

        /*
         * Skip the payload.
         */
        offset += length;
    }
}
Esempio n. 8
0
/*
 * Dissect ASCII TPKT-encapsulated data in a TCP stream.
 */
void
dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
          dissector_handle_t subdissector_handle)
{
    proto_item *ti = NULL;
    proto_tree *tpkt_tree = NULL;
    volatile int offset = 0;
    int length_remaining;
    int data_len;
    volatile int mgcp_packet_len = 0;
    int mgcp_version = 0;
    int mgcp_reserved = 0;
    volatile int length;
    tvbuff_t *volatile next_tvb;
    const char *saved_proto;
    guint8 string[4];

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

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

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

        length_remaining = tvb_captured_length_remaining(tvb, offset);

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

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

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

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

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

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

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

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

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

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

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

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

        /*
         * Skip the payload.
         */
        offset += data_len;
    }
}
Esempio n. 9
0
static void
dissect_rpl_container(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint16 len, type, sublen, subtyp;
	proto_tree *rpl_container_tree;
	guint16 offset;
	gint ett_type;
	gint length, reported_length;

	len = tvb_get_ntohs(tvb, 0);
	proto_tree_add_item(tree, hf_rpl_len, tvb, 0, 2, ENC_BIG_ENDIAN);

	type = tvb_get_ntohs(tvb, 2);
	proto_tree_add_item(tree, hf_rpl_type, tvb, 2, 2, ENC_BIG_ENDIAN);
	offset = 4;

	switch (type) {
		case 1:
		case 2:
		case 4:
		case 8:
		case 0x10:
		case 0x20:
			while (len >= offset+4) {
				sublen = tvb_get_ntohs(tvb, offset);
				subtyp = tvb_get_ntohs(tvb, offset+2);
				ett_type = ett_rpl_unkn;
				if(subtyp == 0x0004) ett_type = ett_rpl_0004;
				if(subtyp == 0x0008) ett_type = ett_rpl_0008;
				if(subtyp == 0x4003) ett_type = ett_rpl_4003;
				if(subtyp == 0x4006) ett_type = ett_rpl_4006;
				if(subtyp == 0x4007) ett_type = ett_rpl_4007;
				if(subtyp == 0x4009) ett_type = ett_rpl_4009;
				if(subtyp == 0x400a) ett_type = ett_rpl_400a;
				if(subtyp == 0x400b) ett_type = ett_rpl_400b;
				if(subtyp == 0x400c) ett_type = ett_rpl_400c;
				if(subtyp == 0x4011) ett_type = ett_rpl_4011;
				if(subtyp == 0x4018) ett_type = ett_rpl_4018;
				if(subtyp == 0xc005) ett_type = ett_rpl_c005;
				if(subtyp == 0xc014) ett_type = ett_rpl_c014;
				rpl_container_tree = proto_tree_add_subtree(tree, tvb,
					offset, sublen, ett_type, NULL,
					val_to_str_const(subtyp,
						rpl_type_vals,
						"Unknown Type"));
				length = tvb_captured_length_remaining(tvb, offset);
				if (length > sublen)
					length = sublen;
				reported_length = tvb_reported_length_remaining(tvb, offset);
				if (reported_length > sublen)
					reported_length = sublen;
				if ( length > 0) {
				  dissect_rpl_container(tvb_new_subset_length_caplen(tvb,
					offset, length, reported_length),
					pinfo, rpl_container_tree);
				  offset += reported_length;
				} else {
				  /* no more data, exit the loop */
				  offset += reported_length;
				  break;
				}
			}
			break;

		case 0x4003:
			proto_tree_add_item(tree, hf_rpl_corrval,
				tvb, offset, 4, ENC_BIG_ENDIAN);
			offset += 4;
			break;

		case 0x4006:
			proto_tree_add_item(tree, hf_rpl_lmac,
				tvb, offset, 6, ENC_NA);
			offset += 6;
			break;

		case 0x4007:
			proto_tree_add_item(tree, hf_rpl_sap,
				tvb, offset, 1, ENC_BIG_ENDIAN);
			offset ++;
			break;

		case 0x4009:
			proto_tree_add_item(tree, hf_rpl_maxframe,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			break;

		case 0x400a:
			proto_tree_add_item(tree, hf_rpl_connclass,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			break;

		case 0x400b:
			proto_tree_add_item(tree, hf_rpl_respval,
				tvb, offset, 1, ENC_BIG_ENDIAN);
			offset ++;
			break;

		case 0x400c:
			proto_tree_add_item(tree, hf_rpl_smac,
				tvb, offset, 6, ENC_NA);
			offset += 6;
			break;

		case 0x4011:
			proto_tree_add_item(tree, hf_rpl_sequence,
				tvb, offset, 4, ENC_BIG_ENDIAN);
			offset += 4;
			break;

		case 0x4018:
			proto_tree_add_item(tree, hf_rpl_data,
				tvb, offset, len-4, ENC_NA);
			offset += len - 4;
			break;

		case 0xc005:
			proto_tree_add_item(tree, hf_rpl_config,
				tvb, offset, 8, ENC_NA);
			offset += 8;
			proto_tree_add_item(tree, hf_rpl_equipment,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			proto_tree_add_item(tree, hf_rpl_memsize,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			proto_tree_add_item(tree, hf_rpl_bsmversion,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			proto_tree_add_item(tree, hf_rpl_ec,
				tvb, offset, 6, ENC_NA);
			offset += 6;
			proto_tree_add_item(tree, hf_rpl_adapterid,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			proto_tree_add_item(tree, hf_rpl_shortname,
				tvb, offset, 10, ENC_NA);
			offset += 10;
			break;

		case 0xc014:
			proto_tree_add_item(tree, hf_rpl_laddress,
				tvb, offset, 4, ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(tree, hf_rpl_xaddress,
				tvb, offset, 4, ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(tree, hf_rpl_flags,
				tvb, offset, 1, ENC_BIG_ENDIAN);
			offset ++;
			break;

		default:
			call_data_dissector(tvb_new_subset_remaining(tvb, 4), pinfo,
				tree);
			break;
	}
	if (tvb_reported_length(tvb) > offset)
		call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
}
Esempio n. 10
0
/*
 * Function for AVP dissector.
 */
static void
dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
{

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

        gint32  buffer_length;

        tvbuff_t   *group_tvb;
        tvbuff_t   *eap_tvb;
        tvbuff_t   *encap_tvb;
        proto_tree *single_avp_tree;
        proto_tree *avp_eap_tree;
        proto_tree *avp_encap_tree;

        offset = 0;
        buffer_length = tvb_reported_length(tvb);

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

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

                avp_length = avp_hdr_length + avp_data_length;

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


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

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

                /* AVP Code */
                proto_tree_add_uint_format_value(single_avp_tree, hf_pana_avp_code, tvb,
                                                 offset, 2, avp_code, "%s (%u)",
                                                 val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                 avp_code);
                offset += 2;

                /* AVP Flags */
                dissect_pana_avp_flags(single_avp_tree, tvb, offset, avp_flags);
                offset += 2;

                /* AVP Length */
                proto_tree_add_item(single_avp_tree, hf_pana_avp_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
                offset += 2;

                /* Reserved */
                proto_tree_add_item(single_avp_tree, hf_pana_avp_reserved, tvb, offset, 2, ENC_NA);
                offset += 2;

                if (avp_flags & PANA_AVP_FLAG_V) {
                        /* Vendor ID */
                        proto_tree_add_item(single_avp_tree, hf_pana_avp_vendorid, tvb, offset, 4, ENC_BIG_ENDIAN);
                        offset += 4;
                }
                if (! (avp_flags & PANA_AVP_FLAG_V)) {
                        /* AVP Value */
                        switch(avp_type) {
                                case PANA_GROUPED: {
                                        proto_tree *avp_group_tree;
                                        avp_group_tree = proto_tree_add_subtree(single_avp_tree,
                                                                                tvb, offset, avp_data_length,
                                                                                ett_pana_avp, NULL, "Grouped AVP");
                                        group_tvb = tvb_new_subset_length_caplen(tvb, offset,
                                                                   MIN(avp_data_length, tvb_reported_length(tvb)-offset),
                                                                   avp_data_length);
                                        dissect_avps(group_tvb, pinfo, avp_group_tree);
                                        break;
                                }
                                case PANA_UTF8STRING: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_string, tvb,
                                                                     offset, avp_data_length, ENC_UTF_8|ENC_NA);
                                        break;
                                }
                                case PANA_OCTET_STRING: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_bytes, tvb,
                                                            offset, avp_data_length, ENC_NA);
                                        break;
                                }
                                case PANA_INTEGER32: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int32, tvb,
                                                            offset, 4, ENC_BIG_ENDIAN);
                                        break;
                                }
                                case PANA_UNSIGNED32: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint32, tvb,
                                                            offset, 4, ENC_BIG_ENDIAN);
                                        break;
                                }
                                case PANA_INTEGER64: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int64, tvb,
                                                            offset, 8, ENC_BIG_ENDIAN);
                                        break;
                                }
                                case PANA_UNSIGNED64: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint64, tvb,
                                                            offset, 8, ENC_BIG_ENDIAN);
                                        break;
                                }
                                case PANA_ENUMERATED: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_enumerated, tvb,
                                                            offset, 4, ENC_BIG_ENDIAN);
                                        break;
                                }
                                case PANA_RESULT_CODE: {
                                        result_code = tvb_get_ntohl(tvb, offset);
                                        proto_tree_add_uint_format(single_avp_tree, hf_pana_avp_code, tvb, offset, avp_data_length,
                                                                   result_code, "Value: %d (%s)",
                                                                   result_code,
                                                                   val_to_str(result_code, avp_code_names, "Unknown (%d)"));
                                        break;
                                }
                                case PANA_EAP: {
                                        avp_eap_tree = proto_tree_add_subtree(single_avp_tree,
                                                                              tvb, offset, avp_data_length,
                                                                              ett_pana_avp, NULL, "AVP Value (EAP packet)");
                                        eap_tvb = tvb_new_subset_length(tvb, offset, avp_data_length);
                                        DISSECTOR_ASSERT_HINT(eap_handle, "EAP Dissector not available");
                                        call_dissector(eap_handle, eap_tvb, pinfo, avp_eap_tree);
                                        break;
                                }
                                case PANA_ENCAPSULATED: {
                                        avp_encap_tree = proto_tree_add_subtree(single_avp_tree,
                                                                                tvb, offset, avp_data_length,
                                                                                ett_pana_avp, NULL, "AVP Value (PANA packet)");
                                        encap_tvb = tvb_new_subset_length(tvb, offset, avp_data_length);
                                        dissect_pana_pdu(encap_tvb, pinfo, avp_encap_tree);
                                        break;
                                }
                        }
                }
                offset += avp_data_length + padding;

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

}
Esempio n. 11
0
static void
display_xip_serval(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree *xip_serval_tree;
	proto_item *ti, *hl_ti;
	tvbuff_t *next_tvb;

	vec_t cksum_vec;
	gint offset;
	guint8 xsh_len, protocol, bytes_remaining;

	/* Get XIP Serval header length, stored as number of 32-bit words. */
	xsh_len = tvb_get_guint8(tvb, XSRVL_LEN) << 2;

	/* Create XIP Serval header tree. */
	ti = proto_tree_add_item(tree, proto_xip_serval, tvb,
		0, xsh_len, ENC_NA);
	xip_serval_tree = proto_item_add_subtree(ti, ett_xip_serval_tree);

	/* Add XIP Serval header length. */
	hl_ti = proto_tree_add_item(xip_serval_tree, hf_xip_serval_hl, tvb,
		XSRVL_LEN, 1, ENC_BIG_ENDIAN);
	if (tvb_captured_length(tvb) < xsh_len)
		expert_add_info_format(pinfo, hl_ti, &ei_xip_serval_bad_len,
			"Header Length field (%d bytes) cannot be greater than actual number of bytes left in packet (%d bytes)",
			xsh_len, tvb_captured_length(tvb));

	/* Add XIP Serval protocol. If it's not data, TCP, or UDP, the
	 * packet is malformed.
	 */
	proto_tree_add_item(xip_serval_tree, hf_xip_serval_proto, tvb,
		XSRVL_PRO, 1, ENC_BIG_ENDIAN);
	protocol = tvb_get_guint8(tvb, XSRVL_PRO);
	if (!try_val_to_str(protocol, xip_serval_proto_vals))
		expert_add_info_format(pinfo, ti, &ei_xip_serval_bad_proto,
			"Unrecognized protocol type: %d", protocol);

	/* Compute checksum. */
	SET_CKSUM_VEC_TVB(cksum_vec, tvb, 0, xsh_len);

	proto_tree_add_checksum(xip_serval_tree, tvb, XSRVL_CHK, hf_xip_serval_check, hf_xip_serval_check_status, &ei_xip_serval_bad_checksum, pinfo, in_cksum(&cksum_vec, 1),
							ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
	offset = XSRVL_EXT;

	/* If there's still more room, check for extension headers. */
	bytes_remaining = xsh_len - offset;
	while (bytes_remaining >= XIP_SERVAL_EXT_MIN_LEN) {
		gint8 bytes_displayed = display_xip_serval_ext(tvb, pinfo, ti,
			xip_serval_tree, offset);

		/* Extension headers are malformed, so we can't say
		 * what the rest of the packet holds. Stop dissecting.
		 */
		if (bytes_displayed <= 0)
			return;

		offset += bytes_displayed;
		bytes_remaining -= bytes_displayed;
	}

	switch (protocol) {
	case XIP_SERVAL_PROTO_DATA:
		next_tvb = tvb_new_subset_remaining(tvb, offset);
		call_data_dissector(next_tvb, pinfo, tree);
		break;
	case IP_PROTO_TCP: {
		/* Get the Data Offset field of the TCP header, which is
		 * the high nibble of the 12th octet and represents the
		 * size of the TCP header of 32-bit words.
		 */
		guint8 tcp_len = hi_nibble(tvb_get_guint8(tvb, offset + 12))*4;
		next_tvb = tvb_new_subset_length_caplen(tvb, offset, tcp_len, tcp_len);
		call_dissector(tcp_handle, next_tvb, pinfo, tree);
		break;
	}
	case IP_PROTO_UDP:
		/* The UDP header is always 8 bytes. */
		next_tvb = tvb_new_subset_length_caplen(tvb, offset, 8, 8);
		call_dissector(udp_handle, next_tvb, pinfo, tree);
		break;
	default:
		break;
	}
}