Example #1
0
static void
dissect_forces(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
{
    /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti, *tlv_item;
    proto_tree *forces_tree, *forces_flags_tree;
    proto_tree *forces_main_header_tree, *forces_tlv_tree, *tlv_tree;
    gint        length_count;

    guint8      message_type;
    guint16     tlv_type;

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

    ti = proto_tree_add_item(tree, proto_forces, tvb, 0, -1, ENC_NA);
    forces_tree = proto_item_add_subtree(ti, ett_forces);

    ti = proto_tree_add_text(forces_tree, tvb, 0, ForCES_HEADER_LENGTH, "Common Header");
    forces_main_header_tree = proto_item_add_subtree(ti, ett_forces_main_header);

    proto_tree_add_item(forces_main_header_tree, hf_forces_version, tvb, 0, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_main_header_tree, hf_forces_rsvd,    tvb, 0, 1, ENC_BIG_ENDIAN);

    message_type = tvb_get_guint8(tvb, offset+1);
    proto_tree_add_item( forces_main_header_tree, hf_forces_messagetype, tvb, offset+1, 1, ENC_BIG_ENDIAN);

    length_count = tvb_get_ntohs(tvb, offset+2) * 4;  /*multiply 4 DWORD*/
    ti = proto_tree_add_uint_format( forces_main_header_tree, hf_forces_length,
                                     tvb, offset+2, 2, length_count, "Length: %u Bytes", length_count);
    if (length_count != tvb_reported_length_remaining(tvb, offset))
        expert_add_info_format(pinfo, ti, &ei_forces_length, "Bogus: ForCES Header length (%u bytes) is wrong),should be (%u bytes)",
            length_count, tvb_reported_length_remaining(tvb, offset));
    if (length_count < 24)
        expert_add_info_format(pinfo, ti, &ei_forces_length, "Bogus: ForCES Header length (%u bytes) is less than 24bytes)", length_count);

    col_add_fstr(pinfo->cinfo, COL_INFO, "Message Type: %s, Total Length:  %u Bytes",
            val_to_str(message_type, message_type_vals, "Unknown messagetype 0x%x"), length_count);

    proto_tree_add_item( forces_main_header_tree, hf_forces_sid,        tvb, offset+4,  4, ENC_BIG_ENDIAN);
    proto_tree_add_item( forces_main_header_tree, hf_forces_did,        tvb, offset+8,  4, ENC_BIG_ENDIAN);
    proto_tree_add_item( forces_main_header_tree, hf_forces_correlator, tvb, offset+12, 8, ENC_BIG_ENDIAN);

    /*Add flags tree*/
    ti = proto_tree_add_item(forces_main_header_tree, hf_forces_flags, tvb, offset+20, 4, ENC_BIG_ENDIAN);
    forces_flags_tree = proto_item_add_subtree(ti, ett_forces_flags);

    proto_tree_add_item(forces_flags_tree, hf_forces_flags_ack,      tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_at,       tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_em,       tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_pri,      tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_reserved, tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_rsrvd,    tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_tp,       tvb, offset+20, 4, ENC_BIG_ENDIAN);

    offset += 24;
    while (tvb_reported_length_remaining(tvb, offset) >= TLV_TL_LENGTH)
    {
        ti = proto_tree_add_text(forces_tree, tvb, offset, TLV_TL_LENGTH, "TLV");
        forces_tlv_tree = proto_item_add_subtree(ti, ett_forces_tlv);

        tlv_type = tvb_get_ntohs(tvb, offset);
        tlv_item = proto_tree_add_item(forces_tlv_tree, hf_forces_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN);
        length_count = tvb_get_ntohs(tvb, offset+2) * 4;
        proto_item_set_len(ti, length_count);
        ti = proto_tree_add_uint_format_value(forces_tlv_tree, hf_forces_tlv_length,
                                        tvb, offset+2, 2, length_count, "%u Bytes", length_count);
        if (tvb_reported_length_remaining(tvb, offset) < length_count)
            expert_add_info_format(pinfo, ti, &ei_forces_tlv_length, "Bogus: Main TLV length (%u bytes) is wrong", length_count);

        if (length_count < TLV_TL_LENGTH)
        {
            expert_add_info_format(pinfo, ti, &ei_forces_tlv_length, "Bogus TLV length: %u", length_count);
            break;
        }

        offset       += TLV_TL_LENGTH;
        length_count -= TLV_TL_LENGTH;

        switch(tlv_type)
        {
        case LFBselect_TLV:
            ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "LFB select TLV");
            tlv_tree = proto_item_add_subtree(ti, ett_forces_lfbselect_tlv_type);
            dissect_lfbselecttlv(tvb, pinfo, tlv_tree, offset, length_count);
            break;

        case REDIRECT_TLV:
            ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "Redirect TLV");
            tlv_tree = proto_item_add_subtree(ti, ett_forces_redirect_tlv_type);
            dissect_redirecttlv(tvb, pinfo, tlv_tree, offset);
            break;

        case ASResult_TLV:
            ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "ASResult TLV");
            tlv_tree = proto_item_add_subtree(ti, ett_forces_asresult_tlv);
            proto_tree_add_item(tlv_tree, hf_forces_asresult_association_setup_result, tvb, offset, 4, ENC_BIG_ENDIAN);
            break;

        case ASTreason_TLV:
            ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "ASTreason TLV");
            tlv_tree = proto_item_add_subtree(ti, ett_forces_astreason_tlv);
            proto_tree_add_item(tlv_tree, hf_forces_astreason_tlv_teardown_reason, tvb, offset, 4, ENC_BIG_ENDIAN);
            break;

        default:
            expert_add_info(pinfo, tlv_item, &ei_forces_tlv_type);
            ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "Unknown TLV");
            tlv_tree = proto_item_add_subtree(ti, ett_forces_unknown_tlv);
            proto_tree_add_item(tlv_tree, hf_forces_unknown_tlv, tvb, offset, length_count, ENC_NA);
            break;
        }

        offset += length_count;
    }
}
static void
dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
	proto_tree *tree, int direction)
{
	proto_tree	*cl_tree;
	proto_tree	*text_tree = NULL;
	proto_item	*pi = NULL;
	guint8		*text;
	int		len;
	int		offset;
	guint32		marker;
	int		command_len;
	const char	*command = "";
	gboolean	command_finished = FALSE;

	marker = tvb_get_ntohl(tvb, 0);
	cl_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_quakeworld_connectionless, NULL, "Connectionless");

	proto_tree_add_uint(cl_tree, hf_quakeworld_connectionless_marker,
				tvb, 0, 4, marker);

	/* all the rest of the packet is just text */
	offset = 4;

	text = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII|ENC_NA);
	/* actually, we should look for a eol char and stop already there */

	if (cl_tree) {
		proto_item *text_item;
		text_item = proto_tree_add_string(cl_tree, hf_quakeworld_connectionless_text,
						  tvb, offset, len, text);
		text_tree = proto_item_add_subtree(text_item, ett_quakeworld_connectionless_text);
	}

	if (direction == DIR_C2S) {
		/* client to server commands */
		const char *c;

		Cmd_TokenizeString(text, len);
		c = Cmd_Argv(0);

		/* client to sever commands */
		if (strcmp(c,"ping") == 0) {
			command = "Ping";
			command_len = 4;
		} else if (strcmp(c,"status") == 0) {
			command = "Status";
			command_len = 6;
		} else if (strcmp(c,"log") == 0) {
			command = "Log";
			command_len = 3;
		} else if (strcmp(c,"connect") == 0) {
			guint32 version = 0;
			guint16 qport = 0;
			guint32 challenge = 0;
			gboolean version_valid = TRUE;
			gboolean qport_valid = TRUE;
			gboolean challenge_valid = TRUE;
			const char *infostring;
			proto_tree *argument_tree = NULL;
			command = "Connect";
			command_len = Cmd_Argv_length(0);
			if (text_tree) {
				proto_item *argument_item;
				pi = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command,
					tvb, offset, command_len, command);
				argument_item = proto_tree_add_string(text_tree,
					hf_quakeworld_connectionless_arguments,
					tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1),
					text + Cmd_Argv_start(1));
				argument_tree = proto_item_add_subtree(argument_item,
								       ett_quakeworld_connectionless_arguments);
				command_finished=TRUE;
			}
			version_valid = ws_strtou32(Cmd_Argv(1), NULL, &version);
			qport_valid = ws_strtou16(Cmd_Argv(2), NULL, &qport);
			challenge_valid = ws_strtou32(Cmd_Argv(3), NULL, &challenge);
			infostring = Cmd_Argv(4);

			if (text_tree && (!version_valid || !qport_valid || !challenge_valid))
				expert_add_info(pinfo, pi, &ei_quakeworld_connectionless_command_invalid);

			if (argument_tree) {
				proto_item *info_item;
				proto_tree *info_tree;
				proto_tree_add_uint(argument_tree,
					hf_quakeworld_connectionless_connect_version,
					tvb,
					offset + Cmd_Argv_start(1),
					Cmd_Argv_length(1), version);
				proto_tree_add_uint(argument_tree,
					hf_quakeworld_connectionless_connect_qport,
					tvb,
					offset + Cmd_Argv_start(2),
					Cmd_Argv_length(2), qport);
				proto_tree_add_int(argument_tree,
					hf_quakeworld_connectionless_connect_challenge,
					tvb,
					offset + Cmd_Argv_start(3),
					Cmd_Argv_length(3), challenge);
				info_item = proto_tree_add_string(argument_tree,
					hf_quakeworld_connectionless_connect_infostring,
					tvb,
					offset + Cmd_Argv_start(4),
					Cmd_Argv_length(4), infostring);
				info_tree = proto_item_add_subtree(
					info_item, ett_quakeworld_connectionless_connect_infostring);
				dissect_id_infostring(tvb, info_tree, offset + Cmd_Argv_start(4),
					wmem_strdup(wmem_packet_scope(), infostring),
					ett_quakeworld_connectionless_connect_infostring_key_value,
					hf_quakeworld_connectionless_connect_infostring_key_value,
					hf_quakeworld_connectionless_connect_infostring_key,
					hf_quakeworld_connectionless_connect_infostring_value);
			}
		} else if (strcmp(c,"getchallenge") == 0) {
			command = "Get Challenge";
			command_len = Cmd_Argv_length(0);
		} else if (strcmp(c,"rcon") == 0) {
			const char* password;
			int i;
			char remaining[MAX_TEXT_SIZE+1];
			proto_tree *argument_tree = NULL;
			command = "Remote Command";
			command_len = Cmd_Argv_length(0);
			if (text_tree) {
				proto_item *argument_item;
				proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command,
					tvb, offset, command_len, command);
				argument_item = proto_tree_add_string(text_tree,
					hf_quakeworld_connectionless_arguments,
					tvb, offset + Cmd_Argv_start(1), len - Cmd_Argv_start(1),
					text + Cmd_Argv_start(1));
				argument_tree =	proto_item_add_subtree(argument_item,
								       ett_quakeworld_connectionless_arguments);
				command_finished=TRUE;
			}
			password = Cmd_Argv(1);
			if (argument_tree) {
				proto_tree_add_string(argument_tree,
					hf_quakeworld_connectionless_rcon_password,
					tvb,
					offset + Cmd_Argv_start(1),
					Cmd_Argv_length(1), password);
			}
			remaining[0] = '\0';
			for (i=2; i<Cmd_Argc() ; i++) {
				g_strlcat (remaining, Cmd_Argv(i), MAX_TEXT_SIZE+1);
				g_strlcat (remaining, " ", MAX_TEXT_SIZE+1);
			}
			if (text_tree) {
				proto_tree_add_string(argument_tree,
					hf_quakeworld_connectionless_rcon_command,
					tvb, offset + Cmd_Argv_start(2),
					Cmd_Argv_start(Cmd_Argc()-1) + Cmd_Argv_length(Cmd_Argc()-1) -
					Cmd_Argv_start(2),
					remaining);
			}
		} else if (c[0]==A2A_PING && ( c[1]=='\0' || c[1]=='\n')) {
			command = "Ping";
			command_len = 1;
		} else if (c[0]==A2A_ACK && ( c[1]=='\0' || c[1]=='\n')) {
			command = "Ack";
			command_len = 1;
		} else {
			command = "Unknown";
			command_len = len - 1;
		}
	}
	else {
		/* server to client commands */
		if (text[0] == S2C_CONNECTION) {
			command = "Connected";
			command_len = 1;
		} else if (text[0] == A2C_CLIENT_COMMAND) {
			command = "Client Command";
			command_len = 1;
			/* stringz (command), stringz (localid) */
		} else if (text[0] == A2C_PRINT) {
			command = "Print";
			command_len = 1;
			/* string */
		} else if (text[0] == A2A_PING) {
			command = "Ping";
			command_len = 1;
		} else if (text[0] == S2C_CHALLENGE) {
			command = "Challenge";
			command_len = 1;
			/* string, conversion */
		} else {
			command = "Unknown";
			command_len = len - 1;
		}
	}

	col_append_fstr(pinfo->cinfo, COL_INFO, " %s", command);

	if (!command_finished) {
		proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command,
			tvb, offset, command_len, command);
	}
	/*offset += len;*/
}
Example #3
0
static void
dissect_eiss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint       offset = 0, packet_length, sect_len;
	proto_item *ti;
	proto_item *pi;
	proto_tree *eiss_tree;
	proto_item *items[PACKET_MPEG_SECT_PI__SIZE];
	gboolean    ssi;
	guint       reserved;
	guint8      reserved2;
	guint8      sect_num, last_sect_num;

	guint16 eiss_application_type;
	guint8 platform_id_length;

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

	ti = proto_tree_add_item(tree, proto_eiss, tvb, offset, -1, ENC_NA);
	eiss_tree = proto_item_add_subtree(ti, ett_eiss);

	offset += packet_mpeg_sect_header_extra(tvb, offset, eiss_tree, &sect_len,
						&reserved, &ssi, items);

	packet_length = sect_len + 3 - 4; /* + for the header, - for the crc */

	if (FALSE != ssi) {
		proto_item *msg_error;
		msg_error = items[PACKET_MPEG_SECT_PI__SSI];

		PROTO_ITEM_SET_GENERATED(msg_error);
		expert_add_info(pinfo, msg_error, &ei_eiss_invalid_section_syntax_indicator);
	}

	if (0 != reserved) {
		proto_item *msg_error;
		msg_error = items[PACKET_MPEG_SECT_PI__RESERVED];

		PROTO_ITEM_SET_GENERATED(msg_error);
		expert_add_info_format(pinfo, msg_error, &ei_eiss_invalid_reserved_bits, "Invalid reserved1 bits (should all be 0)");
	}

	if (1021 < sect_len) {
		proto_item *msg_error;
		msg_error = items[PACKET_MPEG_SECT_PI__LENGTH];

		PROTO_ITEM_SET_GENERATED(msg_error);
		expert_add_info(pinfo, msg_error, &ei_eiss_invalid_section_length);
	}

	reserved2 = tvb_get_guint8(tvb, offset);
	pi = proto_tree_add_item(eiss_tree, hf_eiss_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN);
	if (0 != reserved2) {
		expert_add_info_format(pinfo, pi, &ei_eiss_invalid_reserved_bits, "Invalid reserved2 bits (should all be 0)");
	}
	offset++;

	sect_num = tvb_get_guint8(tvb, offset);
	last_sect_num = tvb_get_guint8(tvb, offset + 1);
	pi = proto_tree_add_item(eiss_tree, hf_eiss_section_number, tvb, offset, 1, ENC_BIG_ENDIAN);
	if (last_sect_num < sect_num) {
		expert_add_info(pinfo, pi, &ei_eiss_section_number);
	}
	offset++;
	proto_tree_add_item(eiss_tree, hf_eiss_last_section_number,     tvb, offset, 1, ENC_BIG_ENDIAN);
	offset++;
	proto_tree_add_item(eiss_tree, hf_eiss_protocol_version_major,  tvb, offset, 1, ENC_BIG_ENDIAN);
	offset++;
	proto_tree_add_item(eiss_tree, hf_eiss_protocol_version_minor,  tvb, offset, 1, ENC_BIG_ENDIAN);
	offset++;

	eiss_application_type = tvb_get_ntohs(tvb, offset);
	pi = proto_tree_add_item(eiss_tree, hf_eiss_application_type,   tvb, offset, 2, ENC_BIG_ENDIAN);
	if (8 != eiss_application_type) {
		expert_add_info(pinfo, pi, &ei_eiss_application_type);
	}
	offset += 2;
	proto_tree_add_item(eiss_tree, hf_eiss_organisation_id,         tvb, offset, 4, ENC_BIG_ENDIAN);
	offset += 4;
	proto_tree_add_item(eiss_tree, hf_eiss_application_id,          tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	platform_id_length = tvb_get_guint8(tvb, offset);
	pi = proto_tree_add_item(eiss_tree, hf_eiss_platform_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
	if (0 != platform_id_length % 15) {
		expert_add_info(pinfo, pi, &ei_eiss_platform_id_length);
	}
	offset++;

	while (0 < platform_id_length) {
		guint tmp;

		tmp = dissect_etv_bif_platform_ids(tvb, eiss_tree, offset);
		offset += tmp;
		if (platform_id_length < tmp) {
			platform_id_length = 0;
			/* error */
		} else {
			platform_id_length -= tmp;
		}
	}

	if (0 < packet_length) {
		proto_tree *eiss_desc_tree;
		pi = proto_tree_add_text(eiss_tree, tvb, offset,
					packet_length-offset,
					"%s", "EISS Descriptor(s)");
		eiss_desc_tree = proto_item_add_subtree(pi, ett_eiss_desc);
		while (offset < packet_length) {
			offset += dissect_eiss_descriptors(tvb, pinfo,
							eiss_desc_tree, offset);
		}
	}

	packet_mpeg_sect_crc(tvb, pinfo, eiss_tree, 0, sect_len - 1);
}
Example #4
0
static void dissect_igrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint8 ver_and_opcode,version,opcode,network;
  gint offset=IGRP_HEADER_LENGTH;
  guint16 ninterior,nsystem,nexterior;
  const guint8 *ipsrc;
  proto_item *ti;
  proto_tree *igrp_tree, *igrp_vektor_tree;
  tvbuff_t   *next_tvb;

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

  ver_and_opcode = tvb_get_guint8(tvb,0);


  switch (ver_and_opcode) {
  case 0x11:
    col_set_str(pinfo->cinfo, COL_INFO, "Response" );
    break;
  case 0x12:
    col_set_str(pinfo->cinfo, COL_INFO, "Request" );
    break;
  default:
    col_set_str(pinfo->cinfo, COL_INFO, "Unknown version or opcode");
  }




  if (tree) {
    ti = proto_tree_add_protocol_format(tree, proto_igrp, tvb, 0, -1,
                                        "Cisco IGRP");

    igrp_tree = proto_item_add_subtree(ti, ett_igrp);

    version = (ver_and_opcode&0xf0)>>4 ; /* version is the fist half of the byte */
    opcode = ver_and_opcode&0x0f ;       /* opcode is the last half of the byte */

    ti = proto_tree_add_item(igrp_tree, hf_igrp_version, tvb, 0, 1, ENC_BIG_ENDIAN);
    if (version != 1)
        expert_add_info(pinfo, ti, &ei_igrp_version);
    ti = proto_tree_add_item(igrp_tree, hf_igrp_command, tvb, 0, 1, ENC_BIG_ENDIAN);
    if (opcode==1)
        proto_item_append_text(ti, " (Response)");
    else
        proto_item_append_text(ti, " (Request)");
    proto_tree_add_item(igrp_tree, hf_igrp_update, tvb, 1,1, ENC_BIG_ENDIAN);
    proto_tree_add_item(igrp_tree, hf_igrp_as, tvb, 2,2, ENC_BIG_ENDIAN);

    ninterior = tvb_get_ntohs(tvb,4);
    nsystem = tvb_get_ntohs(tvb,6);
    nexterior = tvb_get_ntohs(tvb,8);

    /* this is a ugly hack to find the first byte of the IP source address */
    if (pinfo->net_src.type == AT_IPv4) {
      ipsrc = (const guint8 *)pinfo->net_src.data;
      network = ipsrc[0];
    } else
      network = 0; /* XXX - shouldn't happen */

    ti = proto_tree_add_item(igrp_tree, hf_igrp_interior_routes, tvb, 4, 2, ENC_BIG_ENDIAN);
    for( ; ninterior>0 ; ninterior-- ) {
      igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
      next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
      dissect_vektor_igrp (next_tvb,igrp_vektor_tree,network);
      offset+=IGRP_ENTRY_LENGTH;
    }

    ti = proto_tree_add_item(igrp_tree, hf_igrp_system_routes, tvb, 6, 2, ENC_BIG_ENDIAN);
    for( ; nsystem>0 ; nsystem-- ) {
      igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
      next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
      dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
      offset+=IGRP_ENTRY_LENGTH;
    }

    ti = proto_tree_add_item(igrp_tree, hf_igrp_exterior_routes, tvb, 8, 2, ENC_BIG_ENDIAN);
    for( ; nexterior>0 ; nexterior-- ) {
      igrp_vektor_tree =  proto_item_add_subtree(ti,ett_igrp_vektor);
      next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
      dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
      offset+=IGRP_ENTRY_LENGTH;
    }

    proto_tree_add_item(igrp_tree, hf_igrp_checksum, tvb, 10, 2, ENC_BIG_ENDIAN);
  }
}
/*
* Dissect RTSE PDUs inside a PPDU.
*/
static int
dissect_rtse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
{
	int offset = 0;
	int old_offset;
	proto_item *item;
	proto_tree *tree;
	proto_tree *next_tree=NULL;
	tvbuff_t *next_tvb = NULL;
	tvbuff_t *data_tvb = NULL;
	fragment_head *frag_msg = NULL;
	guint32 fragment_length;
	guint32 rtse_id = 0;
	gboolean data_handled = FALSE;
	struct SESSION_DATA_STRUCTURE* session;
	conversation_t *conversation = NULL;
	asn1_ctx_t asn1_ctx;
	asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);

	/* do we have application context from the acse dissector? */
	if (data == NULL)
		return 0;
	session  = (struct SESSION_DATA_STRUCTURE*)data;

	/* save parent_tree so subdissectors can create new top nodes */
	top_tree=parent_tree;

	asn1_ctx.private_data = session;

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

	if (rtse_reassemble &&
	    ((session->spdu_type == SES_DATA_TRANSFER) ||
	     (session->spdu_type == SES_MAJOR_SYNC_POINT))) {
		/* Use conversation index as fragment id */
		conversation  = find_conversation (pinfo->fd->num,
						   &pinfo->src, &pinfo->dst, pinfo->ptype,
						   pinfo->srcport, pinfo->destport, 0);
		if (conversation != NULL) {
			rtse_id = conversation->index;
		}
		session->rtse_reassemble = TRUE;
	}
	if (rtse_reassemble && session->spdu_type == SES_MAJOR_SYNC_POINT) {
		frag_msg = fragment_end_seq_next (&rtse_reassembly_table,
						  pinfo, rtse_id, NULL);
		next_tvb = process_reassembled_data (tvb, offset, pinfo, "Reassembled RTSE",
						     frag_msg, &rtse_frag_items, NULL, parent_tree);
	}

	item = proto_tree_add_item(parent_tree, proto_rtse, next_tvb ? next_tvb : tvb, 0, -1, ENC_NA);
	tree = proto_item_add_subtree(item, ett_rtse);

	if (rtse_reassemble && session->spdu_type == SES_DATA_TRANSFER) {
		/* strip off the OCTET STRING encoding - including any CONSTRUCTED OCTET STRING */
		dissect_ber_octet_string(FALSE, &asn1_ctx, tree, tvb, offset, hf_rtse_segment_data, &data_tvb);

		if (data_tvb) {
			fragment_length = tvb_captured_length_remaining (data_tvb, 0);
			proto_item_append_text(asn1_ctx.created_item, " (%u byte%s)", fragment_length,
      	                              plurality(fragment_length, "", "s"));
			frag_msg = fragment_add_seq_next (&rtse_reassembly_table,
							  data_tvb, 0, pinfo,
							  rtse_id, NULL,
							  fragment_length, TRUE);
			if (frag_msg && pinfo->fd->num != frag_msg->reassembled_in) {
				/* Add a "Reassembled in" link if not reassembled in this frame */
				proto_tree_add_uint (tree, *(rtse_frag_items.hf_reassembled_in),
						     data_tvb, 0, 0, frag_msg->reassembled_in);
			}
			pinfo->fragmented = TRUE;
			data_handled = TRUE;
		} else {
			fragment_length = tvb_captured_length_remaining (tvb, offset);
		}

		col_append_fstr(pinfo->cinfo, COL_INFO, "[RTSE fragment, %u byte%s]",
					fragment_length, plurality(fragment_length, "", "s"));
	} else if (rtse_reassemble && session->spdu_type == SES_MAJOR_SYNC_POINT) {
		if (next_tvb) {
			/* ROS won't do this for us */
			session->ros_op = (ROS_OP_INVOKE | ROS_OP_ARGUMENT);
			/*offset=*/dissect_ber_external_type(FALSE, tree, next_tvb, 0, &asn1_ctx, -1, call_rtse_external_type_callback);
			top_tree = NULL;
			/* Return other than 0 to indicate that we handled this packet */
			return 1;
		} else {
			offset = tvb_captured_length (tvb);
		}
		pinfo->fragmented = FALSE;
		data_handled = TRUE;
	}

	if (!data_handled) {
		while (tvb_reported_length_remaining(tvb, offset) > 0){
			old_offset=offset;
			offset=dissect_rtse_RTSE_apdus(TRUE, tvb, offset, &asn1_ctx, tree, -1);
			if(offset == old_offset){
				next_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
								ett_rtse_unknown, &item, "Unknown RTSE PDU");
				expert_add_info (pinfo, item, &ei_rtse_unknown_rtse_pdu);
				dissect_unknown_ber(pinfo, tvb, offset, next_tree);
				break;
			}
		}
	}

	top_tree = NULL;
	return tvb_captured_length(tvb);
}
Example #6
0
/* Process an APP1 block.
 *
 * XXX - This code only works on US-ASCII systems!!!
 */
static int
process_app1_segment(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, guint32 len,
        guint16 marker, const char *marker_name, gboolean show_first_identifier_not_jfif)
{
    proto_item *ti;
    proto_tree *subtree;
    char *str;
    gint str_size;
    int offset = 0;
    int tiff_start;

    ti = proto_tree_add_item(tree, hf_marker_segment,
            tvb, 0, -1, ENC_NA);
    subtree = proto_item_add_subtree(ti, ett_marker_segment);

    proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
    proto_tree_add_item(subtree, hf_marker, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    proto_tree_add_item(subtree, hf_len, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    str = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &str_size, ENC_ASCII);
    ti = proto_tree_add_item(subtree, hf_identifier, tvb, offset, str_size, ENC_ASCII|ENC_NA);
    offset += str_size;

    if (show_first_identifier_not_jfif && strcmp(str, "JFIF") != 0) {
        expert_add_info(pinfo, ti, &ei_file_jpeg_first_identifier_not_jfif);
    }

    if (strcmp(str, "Exif") == 0) {
        /*
         * Endianness
         */
        int encoding;
        guint16 val_16;
        guint32 val_32, num_fields;
        proto_item* tiff_item;

        offset++; /* Skip a byte supposed to be 0x00 */

        tiff_start = offset;
        val_16 = tvb_get_ntohs(tvb, offset);
        if (val_16 == 0x4949) {
            encoding = ENC_LITTLE_ENDIAN;
            proto_tree_add_uint_format_value(subtree, hf_endianness, tvb, offset, 2, val_16, "little endian");
        } else if (val_16 == 0x4D4D) {
            encoding = ENC_BIG_ENDIAN;
            proto_tree_add_uint_format_value(subtree, hf_endianness, tvb, offset, 2, val_16, "big endian");
        } else {
            /* Error: invalid endianness encoding */
            proto_tree_add_uint_format_value(subtree, hf_endianness, tvb, offset, 2, val_16,
                    "Incorrect encoding 0x%04x- skipping the remainder of this application marker", val_16);
            return offset;
        }
        offset += 2;
        /*
         * Fixed value 42 = 0x002a
         */
        offset += 2;
        /*
         * Offset to IFD
         */
        val_32 = tvb_get_guint32(tvb, offset, encoding);
        tiff_item = proto_tree_add_uint_format_value(subtree, hf_start_ifd_offset, tvb, offset, 4, val_32, "%u bytes",
            val_32);
        offset += 4;
        /*
         * Check for a bogus val_32 value.
         * XXX - bogus value message should also deal with a
         * value that's too large and causes an overflow.
         * Or should it just check against the segment length,
         * which is 16 bits?
         */
        if (val_32 + tiff_start < (guint32)offset) {
            expert_add_info_format(pinfo, tiff_item, &ei_start_ifd_offset, " (bogus, should be >= %u)",
                offset- tiff_start);
            return offset;
        }
        /*
         * Skip the following portion
         */
        if (val_32 + tiff_start > (guint32)offset) {
            proto_tree_add_bytes_format_value(subtree, hf_skipped_tiff_data, tvb, offset, val_32 + tiff_start - offset, NULL, "%u bytes",
                val_32 + tiff_start - offset);
        }
        for (;;) {
            offset = val_32 + tiff_start;
            /*
             * Process the IFD
             */
            proto_tree_add_item_ret_uint(subtree, hf_ifd_num_fields, tvb, offset, 2, encoding, &num_fields);
            offset += 2;
            while (num_fields-- > 0) {
                proto_tree_add_item(subtree, hf_idf_tag, tvb, offset, 2, encoding);
                offset += 2;
                proto_tree_add_item(subtree, hf_idf_type, tvb, offset, 2, encoding);
                offset += 2;
                proto_tree_add_item(subtree, hf_idf_count, tvb, offset, 4, encoding);
                offset += 4;
                proto_tree_add_item(subtree, hf_idf_offset, tvb, offset, 4, encoding);
                offset += 4;
            }
            /*
             * Offset to the next IFD
             */
            val_32 = tvb_get_guint32(tvb, offset, encoding);
            tiff_item = proto_tree_add_uint_format_value(subtree, hf_next_ifd_offset, tvb, offset, 4, val_32, "%u bytes",
                val_32);
            offset += 4;
            if (val_32 != 0 &&
                val_32 + tiff_start < (guint32)offset) {
                expert_add_info_format(pinfo, tiff_item, &ei_next_ifd_offset, " (bogus, should be >= %u)", offset + tiff_start);
                return offset;
            }
            if (val_32 == 0)
                break;
        }
    } else {
        proto_tree_add_bytes_format_value(subtree, hf_remain_seg_data, tvb, offset, -1, NULL, "%u bytes", len - 2 - str_size);
        proto_item_append_text(ti, " (Unknown identifier)");
    }
    return offset;
}
Example #7
0
static void
dissect_pgmopts(ptvcursor_t* cursor, packet_info *pinfo, const char *pktname)
{
	proto_item *tf, *ti, *ti_len;
	proto_tree *opts_tree = NULL;
	proto_tree *opt_tree  = NULL;
	tvbuff_t   *tvb       = ptvcursor_tvbuff(cursor);

	gboolean theend = FALSE;

	guint16 opts_total_len;
	guint8  genopts_type;
	guint8  genopts_len;
	guint8  opts_type;

	opts_tree = proto_tree_add_subtree_format(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), -1,
		ett_pgm_opts, &tf, "%s Options", pktname);
	ptvcursor_set_tree(cursor, opts_tree);
	opts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
	ti = ptvcursor_add(cursor, hf_pgm_opt_type, 1, ENC_BIG_ENDIAN);
	if (opts_type != PGM_OPT_LENGTH) {
		expert_add_info_format(pinfo, ti, &ei_pgm_opt_type,
		    "%s Options - initial option is %s, should be %s",
		    pktname,
		    val_to_str(opts_type, opt_vals, "Unknown (0x%02x)"),
		    val_to_str(PGM_OPT_LENGTH, opt_vals, "Unknown (0x%02x)"));
		return;
	}
	ptvcursor_add(cursor, hf_pgm_opt_len, 1, ENC_BIG_ENDIAN);
	opts_total_len = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
	proto_item_append_text(tf, " (Total Length %d)", opts_total_len);
	proto_item_set_len(tf, opts_total_len);
	ti_len = ptvcursor_add(cursor, hf_pgm_opt_tlen, 2, ENC_BIG_ENDIAN);
	if (opts_total_len < 4) {
		expert_add_info_format(pinfo, ti_len, &ei_pgm_opt_tlen,
			"%s Options (Total Length %u - invalid, must be >= 4)",
			pktname, opts_total_len);
		return;
	}

	for (opts_total_len -= 4; !theend && opts_total_len != 0;){
		if (opts_total_len < 4) {
			expert_add_info_format(pinfo, ti_len, &ei_pgm_opt_tlen,
				"Remaining total options length doesn't have enough for an options header");
			break;
		}

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

		if (genopts_type & PGM_OPT_END)  {
			genopts_type &= ~PGM_OPT_END;
			theend = TRUE;
		}

		switch(genopts_type) {
		case PGM_OPT_JOIN:{
			TLV_CHECK(ett_pgm_opts_join);
			ptvcursor_set_tree(cursor, opt_tree);

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

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

			break;
		}
		case PGM_OPT_PARITY_PRM:{
			guint8 optdata_po;

			TLV_CHECK(ett_pgm_opts_parityprm);
			ptvcursor_set_tree(cursor, opt_tree);

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


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

			ptvcursor_add(cursor, hf_pgm_opt_parity_prm_prmtgsz, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_PARITY_GRP:{
			TLV_CHECK(ett_pgm_opts_paritygrp);
			ptvcursor_set_tree(cursor, opt_tree);

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

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

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

			TLV_CHECK(ett_pgm_opts_naklist);
			ptvcursor_set_tree(cursor, opt_tree);

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

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

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

			TLV_CHECK(ett_pgm_opts_ccdata);
			ptvcursor_set_tree(cursor, opt_tree);

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

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

			switch (optdata_afi) {

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

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

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

			break;
		}
		case PGM_OPT_PGMCC_FEEDBACK:{
			guint16 optdata_afi;

			TLV_CHECK(ett_pgm_opts_ccdata);
			ptvcursor_set_tree(cursor, opt_tree);

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

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

			switch (optdata_afi) {

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

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

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

			break;
		}
		case PGM_OPT_NAK_BO_IVL:{
			TLV_CHECK(ett_pgm_opts_nak_bo_ivl);
			ptvcursor_set_tree(cursor, opt_tree);

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

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

			break;
		}
		case PGM_OPT_NAK_BO_RNG:{
			TLV_CHECK(ett_pgm_opts_nak_bo_rng);
			ptvcursor_set_tree(cursor, opt_tree);

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

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

			break;
		}
		case PGM_OPT_REDIRECT:{
			guint16 optdata_afi;

			TLV_CHECK(ett_pgm_opts_redirect);
			ptvcursor_set_tree(cursor, opt_tree);

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

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

			switch (optdata_afi) {

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

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

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

			break;
		}
		case PGM_OPT_FRAGMENT:{
			TLV_CHECK(ett_pgm_opts_fragment);
			ptvcursor_set_tree(cursor, opt_tree);

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

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

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

		opts_total_len -= genopts_len;
	}
	return;
}
Example #8
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) ) {

        expert_add_info_format(pinfo, item, &ei_icep_context_missing, "context missing");
        col_append_str(pinfo->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) ) {

            expert_add_info_format(pinfo, item, &ei_icep_context_missing, "second field of Size missing");
            col_append_str(pinfo->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 ) {

        /* display the XX Size byte when click here */
        expert_add_info(pinfo, item, &ei_icep_context_too_long);

        col_append_str(pinfo->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 */
        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;
        proto_tree *context_tree;

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

        dissect_ice_string(pinfo, context_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, context_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);
    }
}
Example #9
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) ) {

        expert_add_info(pinfo, item, &ei_icep_params_missing);
        col_append_str(pinfo->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 ) {

        expert_add_info(pinfo, item, &ei_icep_params_size);
        col_append_str(pinfo->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 ) ) {

        expert_add_info_format(pinfo, item, &ei_icep_params_encapsulated, "missing encapsulated data (%d bytes)", size - ICEP_MIN_PARAMS_SIZE - tvb_data_remained);

        col_append_fstr(pinfo->cinfo, COL_INFO,
                    " (missing encapsulated data (%d bytes))",
                    size - ICEP_MIN_PARAMS_SIZE - tvb_data_remained);

        (*consumed) = -1;
        return;
    }

    /* encapsulated params */
    proto_tree_add_item(tree, hf_icep_params_encapsulated, tvb, offset, (size - ICEP_MIN_PARAMS_SIZE), ENC_NA);

    (*consumed) += (size - ICEP_MIN_PARAMS_SIZE);
}
Example #10
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) ) {

        expert_add_info_format(pinfo, item, &ei_icep_string_malformed, "1st byte of Size missing");
        col_append_str(pinfo->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) ) {

            expert_add_info_format(pinfo, item, &ei_icep_string_malformed, "second field of Size missing");
            col_append_str(pinfo->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) ) {

        expert_add_info_format(pinfo, item, &ei_icep_string_malformed, "missing or truncated string");
        col_append_str(pinfo->cinfo, COL_INFO, " (missing or truncated string)");

        (*consumed) = -1;
        return;
    }

    if ( Size > icep_max_ice_string_len ) {

        expert_add_info(pinfo, item, &ei_icep_string_too_long);
        col_append_str(pinfo->cinfo, COL_INFO, " (string too long)");

        (*consumed) = -1;
        return;
    }


    if ( Size != 0 ) {
        s = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, Size, ENC_ASCII);
        proto_tree_add_string(tree, hf_icep, tvb, offset, Size, s);
    } else {
        s = wmem_strdup(wmem_packet_scope(), "(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);
    }

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

    /*offset += Size;*/
    (*consumed) += Size;
    return;
}
Example #11
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) ) {

        expert_add_info(pinfo, item, &ei_icep_facet_missing);
        col_append_str(pinfo->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 ) {
        /* 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 */

    /* display the XX Size byte when click here */
    expert_add_info(pinfo, item, &ei_icep_facet_max_one_element);

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

    (*consumed) = -1;
    return;
}
Example #12
0
static void dissect_tftp_message(tftp_conv_info_t *tftp_info,
                                 tvbuff_t *tvb, packet_info *pinfo,
                                 proto_tree *tree)
{
  proto_tree *tftp_tree;
  proto_item *ti;
  gint        offset    = 0;
  guint16     opcode;
  guint16     bytes;
  guint16     blocknum;
  guint       i1;
  guint16     error;
  tvbuff_t    *data_tvb = NULL;

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

  /* Protocol root */
  ti = proto_tree_add_item(tree, proto_tftp, tvb, offset, -1, ENC_NA);
  tftp_tree = proto_item_add_subtree(ti, ett_tftp);

  /* Opcode */
  opcode = tvb_get_ntohs(tvb, offset);
  proto_tree_add_uint(tftp_tree, hf_tftp_opcode, tvb, offset, 2, opcode);
  col_add_str(pinfo->cinfo, COL_INFO,
              val_to_str(opcode, tftp_opcode_vals, "Unknown (0x%04x)"));
  offset += 2;

  /* read and write requests contain file names
     for other messages, we add the filenames from the conversation */
  if (opcode!=TFTP_RRQ && opcode!=TFTP_WRQ) {
    if (tftp_info->source_file) {
      ti = proto_tree_add_string(tftp_tree, hf_tftp_source_file, tvb,
          0, 0, tftp_info->source_file);
      PROTO_ITEM_SET_GENERATED(ti);
    }

    if (tftp_info->destination_file) {
      ti = proto_tree_add_string(tftp_tree, hf_tftp_destination_file, tvb,
          0, 0, tftp_info->destination_file);
      PROTO_ITEM_SET_GENERATED(ti);
    }
  }

  switch (opcode) {

  case TFTP_RRQ:
    i1 = tvb_strsize(tvb, offset);
    proto_tree_add_item_ret_string(tftp_tree, hf_tftp_source_file,
                        tvb, offset, i1, ENC_ASCII|ENC_NA, wmem_file_scope(), &tftp_info->source_file);

    /* we either have a source file name (for read requests) or a
       destination file name (for write requests) 
       when we set one of the names, we clear the other */
    tftp_info->destination_file = NULL;

    col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
                    tvb_format_stringzpad(tvb, offset, i1));

    offset += i1;

    i1 = tvb_strsize(tvb, offset);
    proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
                        tvb, offset, i1, ENC_ASCII|ENC_NA);

    col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
                    tvb_format_stringzpad(tvb, offset, i1));

    offset += i1;

    tftp_dissect_options(tvb, pinfo,  offset, tftp_tree,
                         opcode, tftp_info);
    break;

  case TFTP_WRQ:
    i1 = tvb_strsize(tvb, offset);
    proto_tree_add_item_ret_string(tftp_tree, hf_tftp_destination_file,
                        tvb, offset, i1, ENC_ASCII|ENC_NA, wmem_file_scope(), &tftp_info->destination_file);

    tftp_info->source_file = NULL; /* see above */

    col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
                    tvb_format_stringzpad(tvb, offset, i1));

    offset += i1;

    i1 = tvb_strsize(tvb, offset);
    proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
                        tvb, offset, i1, ENC_ASCII|ENC_NA);

    col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
                    tvb_format_stringzpad(tvb, offset, i1));

    offset += i1;

    tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                         opcode,  tftp_info);
    break;

  case TFTP_INFO:
    tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                         opcode,  tftp_info);
    break;

  case TFTP_DATA:
    blocknum = tvb_get_ntohs(tvb, offset);
    proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
                        blocknum);

    /* Sequence analysis on blocknums (first pass only) */
    if (!pinfo->fd->flags.visited) {
      if (blocknum > tftp_info->next_block_num) {
        /* There is a gap.  Don't try to recover from this. */
        tftp_info->next_block_num = blocknum + 1;
        tftp_info->blocks_missing = TRUE;
        /* TODO: add info to a result table for showing expert info in later passes */
      }
      else if (blocknum == tftp_info->next_block_num) {
        /* OK, inc what we expect next */
        tftp_info->next_block_num++;
      }
    }
    offset += 2;

    /* Show number of bytes in this block, and whether it is the end of the file */
    bytes = tvb_reported_length_remaining(tvb, offset);
    col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i%s",
                    blocknum,
                    (bytes < tftp_info->blocksize)?" (last)":"" );

    /* Show data in tree */
    if (bytes > 0) {
      data_tvb = tvb_new_subset(tvb, offset, -1, bytes);
      call_data_dissector(data_tvb, pinfo, tree);
    }

    /* If Export Object tap is listening, need to accumulate blocks info list
       to send to tap. But if already know there are blocks missing, there is no
       point in trying. */
    if (have_tap_listener(tftp_eo_tap) && !tftp_info->blocks_missing) {
      file_block_t *block;

      if (blocknum == 1) {
        /* Reset data for this conversation, freeing any accumulated blocks! */
        cleanup_tftp_blocks(tftp_info);
        tftp_info->next_tap_block_num = 1;
      }

      if (blocknum != tftp_info->next_tap_block_num) {
        /* Ignore.  Could be missing frames, or just clicking previous frame */
        return;
      }

      if (bytes > 0) {
        /* Create a block for this block */
        block = (file_block_t*)g_malloc(sizeof(file_block_t));
        block->length = bytes;
        block->data = tvb_memdup(NULL, data_tvb, 0, bytes);

        /* Add to the end of the list (does involve traversing whole list..) */
        tftp_info->block_list = g_slist_append(tftp_info->block_list, block);
        tftp_info->file_length += bytes;

        /* Look for next blocknum next time */
        tftp_info->next_tap_block_num++;
      }

      /* Tap export object only when reach end of file */
      if (bytes < tftp_info->blocksize) {
        tftp_eo_t        *eo_info;

        /* If don't have a filename, won't tap file info */
        if ((tftp_info->source_file == NULL) && (tftp_info->destination_file == NULL)) {
            cleanup_tftp_blocks(tftp_info);
            return;
        }

        /* Create the eo_info to pass to the listener */
        eo_info = wmem_new(wmem_packet_scope(), tftp_eo_t);

        /* Set filename */
        if (tftp_info->source_file) {
          eo_info->filename = g_strdup(tftp_info->source_file);
        }
        else if (tftp_info->destination_file) {
          eo_info->filename = g_strdup(tftp_info->destination_file);
        }

        /* Send block list, which will be combined and freed at tap. */
        eo_info->payload_len = tftp_info->file_length;
        eo_info->pkt_num = blocknum;
        eo_info->block_list = tftp_info->block_list;

        /* Send to tap */
        tap_queue_packet(tftp_eo_tap, pinfo, eo_info);

        /* Have sent, so forget list of blocks, and only pay attention if we
           get back to the first block again. */
        tftp_info->block_list = NULL;
        tftp_info->next_tap_block_num = 1;
      }
    }
    break;

  case TFTP_ACK:
    blocknum = tvb_get_ntohs(tvb, offset);
    proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
                        blocknum);

    col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i",
                    blocknum);
    break;

  case TFTP_ERROR:
    error = tvb_get_ntohs(tvb, offset);
    proto_tree_add_uint(tftp_tree, hf_tftp_error_code, tvb, offset, 2,
                        error);

    col_append_fstr(pinfo->cinfo, COL_INFO, ", Code: %s",
                    val_to_str(error, tftp_error_code_vals, "Unknown (%u)"));

    offset += 2;

    i1 = tvb_strsize(tvb, offset);
    proto_tree_add_item(tftp_tree, hf_tftp_error_string, tvb, offset,
                        i1, ENC_ASCII|ENC_NA);

    col_append_fstr(pinfo->cinfo, COL_INFO, ", Message: %s",
                    tvb_format_stringzpad(tvb, offset, i1));

    expert_add_info(pinfo, NULL, &ei_tftp_blocksize_range);
    break;

  case TFTP_OACK:
    tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                         opcode, tftp_info);
    break;

  default:
    proto_tree_add_item(tftp_tree, hf_tftp_data, tvb, offset, -1, ENC_NA);
    break;

  }
}
Example #13
0
static void
dissect_isis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti, *version_item;
    proto_tree *isis_tree = NULL;
    int offset = 0;
    guint8 isis_version;
    guint8 isis_type;
    tvbuff_t *next_tvb;
    isis_data_t subdissector_data;

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

    ti = proto_tree_add_item(tree, proto_isis, tvb, 0, -1, ENC_NA);
    isis_tree = proto_item_add_subtree(ti, ett_isis);

    proto_tree_add_item(isis_tree, hf_isis_irpd, tvb, offset, 1, ENC_BIG_ENDIAN );
    offset += 1;

    subdissector_data.header_length = tvb_get_guint8(tvb, offset);
    proto_tree_add_uint(isis_tree, hf_isis_header_length, tvb,
            offset, 1, subdissector_data.header_length );
    offset += 1;

    isis_version = tvb_get_guint8(tvb, offset);
    version_item = proto_tree_add_uint(isis_tree, hf_isis_version, tvb,
            offset, 1, isis_version );
    if (isis_version != ISIS_REQUIRED_VERSION){
        col_add_fstr(pinfo->cinfo, COL_INFO,
                "Unknown ISIS version (%u vs %u)",
                isis_version, ISIS_REQUIRED_VERSION );
        expert_add_info(pinfo, version_item, &ei_isis_version);
        return;
    }
    offset += 1;

    subdissector_data.system_id_len = tvb_get_guint8(tvb, offset);
    proto_tree_add_uint(isis_tree, hf_isis_system_id_length, tvb,
            offset, 1, subdissector_data.system_id_len );
    offset += 1;

    isis_type = tvb_get_guint8(tvb, offset) & ISIS_TYPE_MASK;
    col_add_str(pinfo->cinfo, COL_INFO,
            val_to_str ( isis_type, isis_vals, "Unknown (0x%x)" ) );

    proto_tree_add_item(isis_tree, hf_isis_type, tvb, offset, 1, ENC_BIG_ENDIAN );
    proto_tree_add_item(isis_tree, hf_isis_type_reserved, tvb, offset, 1, ENC_BIG_ENDIAN );
    offset += 1;

    proto_tree_add_item(isis_tree, hf_isis_version2, tvb, offset, 1, ENC_BIG_ENDIAN );
    offset += 1;

    proto_tree_add_item(isis_tree, hf_isis_reserved, tvb, offset, 1, ENC_BIG_ENDIAN );
    offset += 1;

    proto_tree_add_item(isis_tree, hf_isis_max_area_adr, tvb, offset, 1, ENC_BIG_ENDIAN );
    offset += 1;

    /*
     * Interpret the system ID length.
     */
    if (subdissector_data.system_id_len == 0)
        subdissector_data.system_id_len = 6;    /* zero means 6-octet ID field length */
    else if (subdissector_data.system_id_len == 255) {
        subdissector_data.system_id_len = 0;    /* 255 means null ID field */
        /* XXX - what about the LAN ID? */
    }
    /* XXX - otherwise, must be in the range 1 through 8 */

    next_tvb = tvb_new_subset_remaining(tvb, offset);
    if (!dissector_try_uint_new(isis_dissector_table, isis_type, next_tvb,
                                pinfo, tree, TRUE, &subdissector_data))
    {
        proto_tree_add_expert(tree, pinfo, &ei_isis_type, tvb, offset, -1);
    }
} /* dissect_isis */
void
dissect_802_3(volatile int length, gboolean is_802_2, tvbuff_t *tvb,
              int offset_after_length, packet_info *pinfo, proto_tree *tree,
              proto_tree *fh_tree, int length_id, int trailer_id, expert_field* ei_len,
              int fcs_len)
{
    proto_item		*length_it;
    tvbuff_t		*volatile next_tvb = NULL;
    tvbuff_t		*trailer_tvb = NULL;
    const char		*saved_proto;
    gint			captured_length, reported_length;
    void			*pd_save;

    length_it = proto_tree_add_uint(fh_tree, length_id, tvb,
                                    offset_after_length - 2, 2, length);

    /* Get the length of the payload.
       If the FCS length is positive, remove the FCS.
       (If it's zero, there's no FCS; if it's negative, we don't know whether
       there's an FCS, so we'll guess based on the length of the trailer.) */
    reported_length = tvb_reported_length_remaining(tvb, offset_after_length);
    if (fcs_len > 0) {
        if (reported_length >= fcs_len)
            reported_length -= fcs_len;
    }

    /* Make sure the length in the 802.3 header doesn't go past the end of
       the payload. */
    if (length > reported_length) {
        length = reported_length;
        expert_add_info(pinfo, length_it, ei_len);
    }

    /* Give the next dissector only 'length' number of bytes. */
    captured_length = tvb_length_remaining(tvb, offset_after_length);
    if (captured_length > length)
        captured_length = length;
    next_tvb = tvb_new_subset(tvb, offset_after_length, captured_length, length);

    /* Dissect the payload either as IPX or as an LLC frame.
       Catch non-fatal exceptions, so that if the reported length
       of "next_tvb" was reduced by some dissector before an
       exception was thrown, we can still put in an item for
       the trailer. */
    saved_proto = pinfo->current_proto;
    pd_save = pinfo->private_data;
    TRY {
        if (is_802_2)
            call_dissector(llc_handle, next_tvb, pinfo, tree);
        else {
            /* Check if first three bits of payload are 0x7.
               If so, then payload is IPX.  If not, then it's CCSDS.
               Refer to packet-eth.c for setting of is_802_2 variable. */
            if (tvb_get_bits8(next_tvb, 0, 3) == 7)
                call_dissector(ipx_handle, next_tvb, pinfo, tree);
            else
                call_dissector(ccsds_handle, next_tvb, pinfo, tree);
        }
    }
    CATCH_NONFATAL_ERRORS {
        /* Somebody threw an exception that means that there was a problem
           dissecting the payload; that means that a dissector was found,
           so we don't need to dissect the payload as data or update the
           protocol or info columns.

           Just show the exception and then drive on to show the trailer,
           after noting that a dissector was found and restoring the
           protocol value that was in effect before we called the subdissector. */
        pinfo->private_data = pd_save;

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

    /* Restore the protocol value, so that any exception thrown by
       tvb_new_subset_remaining() refers to the protocol for which
       this is a trailer, and restore the private_data structure in
       case one of the called dissectors modified it. */
    pinfo->private_data = pd_save;
    pinfo->current_proto = saved_proto;

    /* Construct a tvbuff for the trailer; if the trailer is past the
       end of the captured data, this will throw a BoundsError, which
       is what we want, as it'll report that the packet was cut short. */
    trailer_tvb = tvb_new_subset_remaining(tvb, offset_after_length + length);

    add_ethernet_trailer(pinfo, tree, fh_tree, trailer_id, tvb, trailer_tvb, fcs_len);
}
Example #15
0
static void dissect_mqpcf_parm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mq_tree,
                               guint offset, guint32 uCount, guint bLittleEndian, gboolean bParse)
{
    guint32 u    = 0;
    guint32 tOfs = 0;
    guint32 uLenF;
    char    strPrm[256];
    guint32 uTyp;
    guint32 uLen = 0;
    guint32 uPrm;
    guint32 uCnt;
    guint32 uCCS;
    guint32 uSLn;
    guint32 uVal;
    guint64 uVal64;
    guint32 uDig;

    const char sMaxLst[] = " Max # of List reached. DECODE interrupted   (actual %u of %u)";
    const char sPrmLn0[] = " MQPrm[%3u] has a zero length. DECODE Failed (MQPrm Count: %u)";
    const char sMaxPrm[] = " Max # of Parm reached. DECODE interrupted   (actual %u of %u)";
    const char sPrmCnt[] = " Cnt=-1 and Length(%u) < 16. DECODE interrupted for elem %u";

    proto_item *ti   = NULL;
    proto_tree *tree = NULL;

    if (uCount == (guint32)-1)
    {
        guint32 xOfs = offset;

        uCnt = 0;
        while (tvb_length_remaining(tvb, xOfs) >= 16)
        {
            uLen = tvb_get_guint32_endian(tvb, xOfs + 4, bLittleEndian);
            if (uLen < 16)
            {
                ti = proto_tree_add_text(mq_tree, tvb, xOfs, 16, sPrmCnt, uLen, uCnt);
                expert_add_info(pinfo, ti, &ei_mq_pcf_PrmCnt);
                break;
            }
            uCnt++;
            xOfs += uLen;
        }
        uCount = uCnt;
    }

    uDig = dissect_mqpcf_getDigits(uCount);

    for (u = 0; u < uCount && u < mq_pcf_maxprm; u++)
    {
        tOfs = offset;
        uTyp = tvb_get_guint32_endian(tvb, offset    , bLittleEndian);
        uLen = tvb_get_guint32_endian(tvb, offset + 4, bLittleEndian);
        if (uLen == 0)
        {
            ti = proto_tree_add_text(mq_tree, tvb, offset, 12, sPrmLn0, u+1, uCount);
            expert_add_info(pinfo, ti, &ei_mq_pcf_prmln0);
            u = uCount;
            break;
        }
        uPrm = tvb_get_guint32_endian(tvb, offset + 8, bLittleEndian);
        uLenF = 12;

        if (bParse)
            g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d-%-30.30s",
                "MQPrm", uDig, u+1,
                uTyp, val_to_str_const(uTyp, GET_VALSV(PrmTyp), "      Unknown") + 6,
                uPrm, uPrm, val_to_str_const(uPrm, GET_VALSV(PrmId), "Unknown"));
        else
            g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d",
                "XtraD", uDig, u+1,
                uTyp, val_to_str_const(uTyp, GET_VALSV(PrmTyp), "      Unknown") + 6,
                uPrm, uPrm);

        switch (uTyp)
        {
        case MQ_MQCFT_NONE:
            break;
        case MQ_MQCFT_COMMAND:
            break;
        case MQ_MQCFT_RESPONSE:
            break;
        case MQ_MQCFT_INTEGER:
            {
                guint8 *pVal = NULL;
                uVal = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
                if (bParse)
                    pVal = dissect_mqpcf_parm_getintval(uPrm, uVal);
                if (pVal)
                {
                    ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %d-%s",
                        strPrm, uVal, pVal);
                }
                else
                {
                    ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %8x-%d",
                        strPrm, uVal, uVal);
                }
                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);
                proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset    , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian);
                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);

                dissect_mqpcf_parm_int(tvb, tree, offset+uLenF, uPrm, uVal, hf_mq_pcf_int, 0, 0, 0, bParse);
            }
            break;
        case MQ_MQCFT_STRING:
            {
                guint8 *sStr;

                uCCS = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
                uSLn = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian);
                sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8,
                    uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
                if (*sStr)
                    strip_trailing_blanks(sStr, uSLn);
                if (*sStr)
                    format_text_chr(sStr, strlen(sStr), '.');

                ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s", strPrm, sStr);
                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);

                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian);

                proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 8, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
            }
            break;
        case MQ_MQCFT_INTEGER_LIST:
            {
                guint32 u2;
                guint32 uDigit = 0;

                uCnt = tvb_get_guint32_endian(tvb, offset+uLenF, bLittleEndian);
                uDigit = dissect_mqpcf_getDigits(uCnt);

                ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s Cnt(%d)", strPrm, uCnt);
                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);

                proto_tree_add_item(tree, hf_mq_pcf_prmtyp  , tvb, offset     , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen  , tvb, offset +  4, 4, bLittleEndian);
                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian);

                offset += uLenF+4;
                for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
                {
                    uVal = tvb_get_guint32_endian(tvb, offset, bLittleEndian);
                    dissect_mqpcf_parm_int(tvb, tree, offset, uPrm, uVal, hf_mq_pcf_intlist, u2+1, uCnt, uDigit, bParse);
                    offset += 4;
                }
                if (u2 != uCnt)
                {
                    ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt);
                    expert_add_info(pinfo, ti, &ei_mq_pcf_MaxInt);
                }
            }
            break;
        case MQ_MQCFT_STRING_LIST:
            {
                guint32  u2;
                guint32  uDigit;
                guint8  *sStr;
                header_field_info *hfinfo;

                hfinfo = proto_registrar_get_nth(hf_mq_pcf_stringlist);

                uCCS = tvb_get_guint32_endian(tvb, offset + uLenF    , bLittleEndian);
                uCnt = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian);
                uSLn = tvb_get_guint32_endian(tvb, offset + uLenF + 8, bLittleEndian);

                ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s Cnt(%d)", strPrm, uCnt);

                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);
                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmcount , tvb, offset + 16, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian);

                uDigit = dissect_mqpcf_getDigits(uCnt);

                offset += uLenF+12;
                for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
                {
                    sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset,
                        uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
                    if (*sStr)
                        strip_trailing_blanks(sStr, uSLn);
                    if (*sStr)
                        format_text_chr(sStr, strlen(sStr),  '.');

                    proto_tree_add_string_format(tree, hf_mq_pcf_stringlist, tvb, offset, uSLn, sStr,
                        "%s[%*d]: %s", hfinfo->name, uDigit, u2+1, sStr);
                    offset += uSLn;
                }
                if (u2 != uCnt)
                {
                    ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt);
                    expert_add_info(pinfo, ti, &ei_mq_pcf_MaxStr);
                }
            }
            break;
        case MQ_MQCFT_EVENT:
            break;
        case MQ_MQCFT_USER:
            {
                ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s", strPrm);
                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);

                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);

                proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + 8, uLen - 8, bLittleEndian);
            }
            break;
        case MQ_MQCFT_BYTE_STRING:
            {
                uSLn = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
                if (uSLn)
                {
                    guint8 *sStrA = format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_ASCII) , uSLn, '.');
                    guint8 *sStrE = format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_EBCDIC), uSLn, '.');
                    if (uSLn > 35)
                    {
                        ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s [Truncated] A(%-.35s) E(%-.35s)", strPrm, sStrA, sStrE);
                    }
                    else
                    {
                        ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s A(%s) E(%s)", strPrm, sStrA, sStrE);
                    }
                }
                else
                {
                    ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s <MISSING>", strPrm);
                }
                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);

                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 12, 4, bLittleEndian);

                proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 4 , uSLn, bLittleEndian);
            }
            break;
        case MQ_MQCFT_TRACE_ROUTE:
            break;
        case MQ_MQCFT_REPORT:
            break;
        case MQ_MQCFT_INTEGER_FILTER:
            {
                guint32 uOpe;

                uOpe = tvb_get_guint32_endian(tvb, offset + uLenF    , bLittleEndian);
                uVal = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian);

                ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s %d",
                    strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), "       Unknown (0x%02x)")+7, uVal);
                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);

                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);

                proto_tree_add_item(tree, hf_mq_pcf_int, tvb, offset + uLenF + 4, 4, bLittleEndian);
            }
            break;
        case MQ_MQCFT_STRING_FILTER:
            {
                guint8 *sStr;
                guint32 uOpe;

                uOpe = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
                uCCS = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian);
                uSLn = tvb_get_guint32_endian(tvb, offset + uLenF + 8, bLittleEndian);
                sStr = format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC), uSLn, '.');
                strip_trailing_blanks(sStr, uSLn);

                ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s %s",
                    strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), "       Unknown (0x%02x)")+7, sStr);
                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);

                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 16, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian);

                proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
            }
            break;
        case MQ_MQCFT_BYTE_STRING_FILTER:
            {
                guint32 uOpe;
                uOpe = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
                uSLn = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian);
                if (uSLn)
                {
                    guint8 *sStrA = format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_ASCII), uSLn, '.');
                    guint8 *sStrE = format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_EBCDIC), uSLn, '.');
                    ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s A(%s) E(%s)",
                        strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), "       Unknown (0x%02x)")+7, sStrA, sStrE);
                }
                else
                {
                    ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s <MISSING>",
                        strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), "       Unknown (0x%02x)")+7);
                }
                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);

                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian);

                proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 8 , uSLn, bLittleEndian);
            }
            break;
        case MQ_MQCFT_COMMAND_XR:
            break;
        case MQ_MQCFT_XR_MSG:
            break;
        case MQ_MQCFT_XR_ITEM:
            break;
        case MQ_MQCFT_XR_SUMMARY:
            break;
        case MQ_MQCFT_GROUP:
            break;
        case MQ_MQCFT_STATISTICS:
            break;
        case MQ_MQCFT_ACCOUNTING:
            break;
        case MQ_MQCFT_INTEGER64:
            {
                uVal64 = tvb_get_guint64_endian(tvb, offset + uLenF + 4, bLittleEndian);
                ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)",
                    strPrm, uVal64, uVal64);
                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);

                proto_tree_add_item(tree, hf_mq_pcf_prmtyp   , tvb, offset     , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen   , tvb, offset +  4, 4, bLittleEndian);
                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmunused, tvb, offset + 12, 4, bLittleEndian);

                proto_tree_add_item(tree, hf_mq_pcf_int64, tvb, offset + uLenF + 4, 8, bLittleEndian);
            }
            break;
        case MQ_MQCFT_INTEGER64_LIST:
            {
                guint32 u2;
                guint32 uDigit;
                header_field_info *hfinfo;

                hfinfo = proto_registrar_get_nth(hf_mq_pcf_int64list);

                uCnt = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
                ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s Cnt(%d)", strPrm, uCnt);
                tree = proto_item_add_subtree(ti, ett_mqpcf_prm);
                uDigit = dissect_mqpcf_getDigits(uCnt);

                proto_tree_add_item(tree, hf_mq_pcf_prmtyp  , tvb, offset     , 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmlen  , tvb, offset +  4, 4, bLittleEndian);
                proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset +  8, 4, bLittleEndian);
                proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian);

                offset += uLenF + 4;
                for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
                {
                    uVal64 = tvb_get_guint64_endian(tvb, offset, bLittleEndian);
                    proto_tree_add_int64_format(tree, hf_mq_pcf_int64list, tvb, offset, 8, uVal64,
                        "%s[%*d]: %" G_GINT64_MODIFIER "d", hfinfo->name, uDigit, u2+1, uVal64);
                    offset += 8;
                }
                if (u2 != uCnt)
                {
                    ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt);
                    expert_add_info(pinfo, ti, &ei_mq_pcf_MaxI64);
                }
            }
            break;
        }
        offset = tOfs+uLen;
    }
    if (u != uCount)
    {
        ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, sMaxPrm, u, uCount);
        expert_add_info(pinfo, ti, &ei_mq_pcf_MaxPrm);
    }
}
Example #16
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) ) {

        expert_add_info_format(pinfo, icep_sub_item, &ei_icep_length, "too short header");
        col_append_str(pinfo->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);
            col_append_fstr(pinfo->cinfo, COL_INFO, " %s.%s()",
                        namestr, opstr);
            opstr = NULL;
            namestr = NULL;
        }
    }

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

        expert_add_info(pinfo, icep_sub_item, &ei_icep_mode_missing);

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

    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;
}
Example #17
0
static
void dissect_pw_cesopsn( tvbuff_t * tvb_original
						,packet_info * pinfo
						,proto_tree * tree
						,pwc_demux_type_t demux)
{
	const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/
	gint      packet_size;
	gint      payload_size;
	gint      padding_size;
	int properties;

	packet_size = tvb_reported_length_remaining(tvb_original, 0);

	/*
	 * FIXME
	 * "4" below should be replaced by something like "min_packet_size_this_dissector"
	 * Also call to dissect_try_cw_first_nibble() should be moved before this block
	 */
	if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
	{
		proto_item  *item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		expert_add_info_format(pinfo, item, &ei_packet_size_too_small,
				       "PW packet size (%d) is too small to carry sensible information"
				       ,(int)packet_size);
		col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
		col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
		return;
	}

	switch (demux)
	{
	case PWC_DEMUX_MPLS:
		if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree))
		{
			return;
		}
		break;
	case PWC_DEMUX_UDP:
		break;
	default:
		DISSECTOR_ASSERT_NOT_REACHED();
		return;
	}

	/* check how "good" is this packet */
	/* also decide payload length from packet size and CW */
	properties = PWC_PACKET_PROPERTIES_T_INITIALIZER;
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/))
	{
		properties |= PWC_CW_BAD_BITS03;
	}
	if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/))
	{
		properties |= PWC_CW_BAD_FRAG;
	}
	{
		/* RFC5086:
		 * [LEN (bits (10 to 15) MAY be used to carry the length of the CESoPSN
		 * packet (defined as the size of the CESoPSN header + the payload size)
		 * if it is less than 64 bytes, and MUST be set to zero otherwise.
		 * Note:  If fixed RTP header is used in the encapsulation, it is
		 * considered part of the CESoPSN header.]
		 *
		 * Note that this differs from RFC4385's definition of length:
		 * [ If the MPLS payload is less than 64 bytes, the length field
		 * MUST be set to the length of the PW payload...]
		 *
		 * We will use RFC5086's definition here.
		 */
		int  cw_len;
		gint payload_size_from_packet;

		cw_len = tvb_get_guint8(tvb_original, 1) & 0x3f;
		payload_size_from_packet = packet_size - encaps_size;
		if (cw_len != 0)
		{
			gint payload_size_from_cw;
			payload_size_from_cw = cw_len - encaps_size;
			/*
			 * Assumptions for error case,
			 * will be overwritten if no errors found:
			 */
			payload_size = payload_size_from_packet;
			padding_size = 0;

			if (payload_size_from_cw < 0)
			{
				properties |= PWC_CW_BAD_PAYLEN_LT_0;
			}
			else if (payload_size_from_cw > payload_size_from_packet)
			{
				properties |= PWC_CW_BAD_PAYLEN_GT_PACKET;
			}
			else if (payload_size_from_packet >= 64)
			{
				properties |= PWC_CW_BAD_LEN_MUST_BE_0;
			}
			else /* ok */
			{
				payload_size = payload_size_from_cw;
				padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
			}
		}
		else
		{
			payload_size = payload_size_from_packet;
			padding_size = 0;
		}
	}

	{
		guint8 cw_lm;
		cw_lm = tvb_get_guint8(tvb_original, 0) & 0x0b /*l+mod*/;
		if (NULL == try_val_to_str(cw_lm, vals_cw_lm))
		{
			properties |= PWC_CW_SUSPECT_LM;
		}

		{
			guint8 l_bit, m_bits;
			l_bit  = (cw_lm & 0x08) >> 3;
			m_bits = (cw_lm & 0x03) >> 0;
			if ((l_bit == 0 && m_bits == 0x0) /*CESoPSN data packet - normal situation*/
			    ||(l_bit == 0 && m_bits == 0x2) /*CESoPSN data packet - RDI on the AC*/ )
			{
				if ((payload_size == 0) || ((payload_size % 8) != 0))
				{
					properties |= PWC_PAY_SIZE_BAD;
				}
			}
			else if (l_bit == 1 && m_bits == 0x0) /*TDM data is invalid; payload MAY be omitted*/
			{
				/*allow any size of payload*/
			}
			else /*reserved combinations*/
			{
				/*allow any size of payload*/
			}
		}
	}

	/* fill up columns*/
	col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
	col_clear(pinfo->cinfo, COL_INFO);
	if (properties & PWC_ANYOF_CW_BAD)
	{
		col_set_str(pinfo->cinfo, COL_INFO, "CW:Bad, ");
	}
	else if (properties & PWC_ANYOF_CW_SUSPECT)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "CW:Suspect, ");
	}

	if (properties & PWC_PAY_SIZE_BAD)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, ");
	}

	col_append_fstr(pinfo->cinfo, COL_INFO, "TDM octets:%d", (int)payload_size);

	if (padding_size != 0)
	{
		col_append_fstr(pinfo->cinfo, COL_INFO, ", Padding:%d", (int)padding_size);
	}

	{
		proto_item* item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE);
		pwc_item_append_text_n_items(item,(int)payload_size,"octet");
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				proto_item* item2;
				tvb = tvb_new_subset_length(tvb_original, 0, PWC_SIZEOF_CW);
				item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA);
				pwc_item_append_cw(item2,tvb_get_ntohl(tvb, 0),FALSE);
				{
					proto_tree* tree3;
					tree3 = proto_item_add_subtree(item, ett);
					{
						proto_item* item3;
						if (properties & PWC_CW_BAD_BITS03) /*display only if value is wrong*/
						{
							item3 = proto_tree_add_item(tree3, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN);
							expert_add_info(pinfo, item3, &ei_cw_bits03);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_lm,  tvb, 0, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_SUSPECT_LM)
						{
							expert_add_info(pinfo, item3, &ei_cw_lm);
						}

						proto_tree_add_item(tree3, hf_cw_r, tvb, 0, 1, ENC_BIG_ENDIAN);

						item3 = proto_tree_add_item(tree3, hf_cw_frg, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_FRAG)
						{
							expert_add_info(pinfo, item3, &ei_cw_frg);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_len, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_PAYLEN_LT_0)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: too small, must be > %d",
								(int)encaps_size);
						}
						if (properties & PWC_CW_BAD_PAYLEN_GT_PACKET)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: must be <= than PSN packet size (%d)",
								(int)packet_size);
						}
						if (properties & PWC_CW_BAD_LEN_MUST_BE_0)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: must be 0 if CESoPSN packet size (%d) is > 64",
								(int)packet_size);
						}

						proto_tree_add_item(tree3, hf_cw_seq, tvb, 2, 2, ENC_BIG_ENDIAN);

					}
				}
			}
		}

		/* payload */
		if (payload_size == 0)
		{
			if (properties & PWC_PAY_SIZE_BAD)
			{
				expert_add_info_format(pinfo, item, &ei_payload_size_invalid_error,
					"CESoPSN payload: none found. Size of payload must be <> 0");
			}
			else
			{
				expert_add_info_format(pinfo, item, &ei_payload_size_invalid_undecoded,
					"CESoPSN payload: omitted to conserve bandwidth");
			}
		}
		else
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				proto_item* item2;
				tvbuff_t* tvb;
				tvb = tvb_new_subset_length(tvb_original, PWC_SIZEOF_CW, payload_size);
				item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA);
				pwc_item_append_text_n_items(item2,(int)payload_size,"octet");
				if (properties & PWC_PAY_SIZE_BAD)
				{
					expert_add_info_format(pinfo, item2, &ei_payload_size_invalid_error,
						"CESoPSN packet payload size must be multiple of 8");
				}
				tree2 = proto_item_add_subtree(item2, ett);
				call_dissector(data_handle, tvb, pinfo, tree2);
				item2 = proto_tree_add_int(tree2, hf_payload_l, tvb, 0, 0
					,(int)payload_size); /* allow filtering */
				PROTO_ITEM_SET_HIDDEN(item2);
			}
		}

		/* padding */
		if (padding_size > 0)
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1);
				call_dissector(pw_padding_handle, tvb, pinfo, tree2);
			}
		}
	}
	return;
}
Example #18
0
/* Decode an EXT_FTI extension and fill FEC array */
void fec_decode_ext_fti(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint8 encoding_id)
{
	guint64 transfer_length;
	fec_packet_data_t* fec_data;
	guint8 instance_id = 0;
	proto_item* ti;

	if (encoding_id == 6){
		/* Raptor Q uses 40-bit transfer length */
		transfer_length = tvb_get_ntoh40(tvb, offset+2);
	}
	else {
		/* Decode 48-bit length field */
		transfer_length = tvb_get_ntoh48(tvb, offset+2);
	}

	if (encoding_id >= 128)
	{
		instance_id = (guint8) tvb_get_ntohs(tvb, offset+8);

		/* Decode FEC Instance ID */
		fec_data = wmem_new0(wmem_file_scope(), fec_packet_data_t);
		fec_data->instance_id = instance_id;

		p_add_proto_data(pinfo->fd, proto_rmt_fec, 0, fec_data);
	}

	if (encoding_id == 6){
		/* Raptor Q uses 40-bit transfer length */
		proto_tree_add_uint64(tree, hf_fti_transfer_length, tvb, offset+2, 5, transfer_length);
	}
	else {
		proto_tree_add_uint64(tree, hf_fti_transfer_length, tvb, offset+2, 6, transfer_length);
		ti = proto_tree_add_item(tree, hf_instance_id, tvb,  offset+8, 2, ENC_BIG_ENDIAN);
		if ((encoding_id < 128) && (instance_id != 0)) {
			expert_add_info(pinfo, ti, &ei_fec_encoding_id);
		}
	}

	switch (encoding_id)
	{
	case 1:
		proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_num_blocks, tvb, offset+12, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_num_subblocks, tvb, offset+14, 1, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_alignment, tvb, offset+15, 1, ENC_BIG_ENDIAN);
		break;

	case 6:
		proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+8, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_num_blocks, tvb, offset+10, 1, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_num_subblocks, tvb, offset+11, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_alignment, tvb, offset+13, 1, ENC_BIG_ENDIAN);
		break;

	case 0:
	case 2:
	case 128:
	case 130:
		proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_max_source_block_length, tvb, offset+12, 4, ENC_BIG_ENDIAN);
		break;

	case 129:
		proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_max_source_block_length, tvb, offset+12, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_max_number_encoding_symbols, tvb, offset+14, 2, ENC_BIG_ENDIAN);
		break;

	case 132:
		proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_max_source_block_length, tvb, offset+12, 4, ENC_BIG_ENDIAN);
		proto_tree_add_item(tree, hf_fti_max_number_encoding_symbols, tvb, offset+16, 4, ENC_BIG_ENDIAN);
		break;
	}
}
static gint
dissect_adb_service(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item          *main_item;
    proto_tree          *main_tree;
    proto_item          *sub_item;
    proto_tree          *sub_tree;
    gint                 offset = 0;
    adb_service_data_t  *adb_service_data = (adb_service_data_t *) data;
    const guint8        *service;
    wmem_tree_key_t      key[5];
    wmem_tree_t         *subtree;
    guint32              i_key;

    main_item = proto_tree_add_item(tree, proto_adb_service, tvb, offset, -1, ENC_NA);
    main_tree = proto_item_add_subtree(main_item, ett_adb_service);

    DISSECTOR_ASSERT(adb_service_data);

    service = adb_service_data->service;

    sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service);
    PROTO_ITEM_SET_GENERATED(sub_item);

        if (g_strcmp0(service, "host:version") == 0) {
            guint32               version;
            guint32               data_length;
            continuation_data_t  *continuation_data;

            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                key[i_key].length = 1;
                key[i_key].key = &adb_service_data->session_key[i_key];
            }
            key[i_key].length = 0;
            key[i_key].key = NULL;

            subtree = (wmem_tree_t *) wmem_tree_lookup32_array(continuation_infos, key);
            continuation_data = (subtree) ? (continuation_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
            if (continuation_data && continuation_data->completed_in_frame < pinfo->num)
                continuation_data = NULL;

            if (!continuation_data || (continuation_data && continuation_data->length_in_frame == pinfo->num))
                offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            if (!pinfo->fd->flags.visited && !continuation_data && tvb_reported_length_remaining(tvb, offset) < 4) {
                key[i_key].length = 1;
                key[i_key++].key = &pinfo->num;
                key[i_key].length = 0;
                key[i_key].key = NULL;

                continuation_data = wmem_new(wmem_file_scope(), continuation_data_t);
                continuation_data->length_in_frame = pinfo->num;
                continuation_data->completed_in_frame = G_MAXUINT32;
                continuation_data->length = data_length;

                wmem_tree_insert32_array(continuation_infos, key, continuation_data);
                continuation_data = NULL;
            }

            if (tvb_reported_length_remaining(tvb, offset) >= 4 ||
                        (continuation_data && continuation_data->completed_in_frame == pinfo->num)) {
                if (!pinfo->fd->flags.visited && continuation_data) {
                    continuation_data->completed_in_frame = pinfo->num;
                }
                offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_version, ett_version, hf_version, tvb, offset, &version);

                col_append_fstr(pinfo->cinfo, COL_INFO, " Version=%u", version);
            }

        } else if (g_strcmp0(service, "host:devices") == 0 ||
                g_strcmp0(service, "host:devices-l") == 0 ||
                g_strcmp0(service, "host:track-devices") == 0) {
            guint32  data_length;

            offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            sub_item = proto_tree_add_item(main_tree, hf_devices, tvb, offset, -1, ENC_NA | ENC_ASCII);
            if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
                expert_add_info(pinfo, sub_item, &ei_incomplete_message);
            }
        } else if (g_strcmp0(service, "host:get-state") == 0 ||
                g_strcmp0(service, "host:get-serialno") == 0 ||
                g_strcmp0(service, "host:get-devpath") == 0 ||
                g_str_has_prefix(service, "connect:") ||
                g_str_has_prefix(service, "disconnect:")) {
            guint32  data_length;

            offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            sub_item = proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII);
            if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
                expert_add_info(pinfo, sub_item, &ei_incomplete_message);
            }
        } else if (g_str_has_prefix(service, "framebuffer:")) {
            framebuffer_data_t  *framebuffer_data = NULL;

            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                key[i_key].length = 1;
                key[i_key].key = &adb_service_data->session_key[i_key];
            }
            key[i_key].length = 0;
            key[i_key].key = NULL;

            subtree = (wmem_tree_t *) wmem_tree_lookup32_array(framebuffer_infos, key);
            framebuffer_data = (subtree) ? (framebuffer_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
            if (framebuffer_data && framebuffer_data->completed_in_frame < pinfo->num)
                framebuffer_data = NULL;

            if (!pinfo->fd->flags.visited && !framebuffer_data) {
                key[i_key].length = 1;
                key[i_key++].key = &pinfo->num;
                key[i_key].length = 0;
                key[i_key].key = NULL;

                framebuffer_data = wmem_new(wmem_file_scope(), framebuffer_data_t);
                framebuffer_data->data_in      = pinfo->num;
                framebuffer_data->current_size = 0;
                framebuffer_data->completed_in_frame = G_MAXUINT32;
                framebuffer_data->size         = tvb_get_letohl(tvb, offset + 4 * 2);
                framebuffer_data->red_offset   = tvb_get_letohl(tvb, offset + 4 * 5);
                framebuffer_data->red_length   = tvb_get_letohl(tvb, offset + 4 * 6);
                framebuffer_data->green_offset = tvb_get_letohl(tvb, offset + 4 * 7);
                framebuffer_data->green_length = tvb_get_letohl(tvb, offset + 4 * 8);
                framebuffer_data->blue_offset  = tvb_get_letohl(tvb, offset + 4 * 9);
                framebuffer_data->blue_length  = tvb_get_letohl(tvb, offset + 4 * 10);
                framebuffer_data->alpha_offset = tvb_get_letohl(tvb, offset + 4 * 11);
                framebuffer_data->alpha_length = tvb_get_letohl(tvb, offset + 4 * 12);

                wmem_tree_insert32_array(framebuffer_infos, key, framebuffer_data);
            }

            if (framebuffer_data && framebuffer_data->data_in == pinfo->num) {
                proto_tree_add_item(main_tree, hf_framebuffer_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

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

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

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

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

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

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

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

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

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

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

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

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

            if (tvb_reported_length_remaining(tvb, offset) > 0) {
                sub_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
                sub_tree = proto_item_add_subtree(sub_item, ett_data);

                if (!pinfo->fd->flags.visited && framebuffer_data) {
                    framebuffer_data->current_size += tvb_captured_length_remaining(tvb, offset);
                    if (framebuffer_data->current_size >= framebuffer_data->size)
                        framebuffer_data->completed_in_frame = pinfo->num;
                }

                if (pref_dissect_more_detail_framebuffer) {
                    proto_item  *pixel_item;
                    proto_tree  *pixel_tree;

                    if (framebuffer_data &&
                        framebuffer_data->red_length == 5 &&
                        framebuffer_data->green_length == 6 &&
                        framebuffer_data->blue_length == 5 &&
                        framebuffer_data->red_offset == 11 &&
                        framebuffer_data->green_offset == 5 &&
                        framebuffer_data->blue_offset == 0) {
                        while (tvb_reported_length_remaining(tvb, offset) > 0) {
                            if (tvb_reported_length_remaining(tvb, offset) < 2) {
                                proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA);
                                offset += 1;
                            }

                            pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 2, ENC_NA);
                            pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel);

                            proto_tree_add_item(pixel_tree, hf_framebuffer_blue_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_green_6, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_red_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                            offset += 2;
                        }
                    } else if (framebuffer_data &&
                            framebuffer_data->red_length == 8 &&
                            framebuffer_data->green_length == 8 &&
                            framebuffer_data->blue_length == 8 &&
                            (framebuffer_data->alpha_length == 0 ||
                            framebuffer_data->alpha_length == 8)) {
                        while (tvb_reported_length_remaining(tvb, offset) > 0) {
                            if (tvb_reported_length_remaining(tvb, offset) < 3 || (tvb_reported_length_remaining(tvb, offset) < 4 && framebuffer_data->alpha_offset > 0)) {
                                proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA);
                                offset = tvb_captured_length(tvb);
                                break;
                            }

                            pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 3, ENC_NA);
                            pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel);

                            proto_tree_add_item(pixel_tree, hf_framebuffer_red, tvb, offset + framebuffer_data->red_offset / 8, 1, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_green, tvb, offset + framebuffer_data->green_offset / 8, 1, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_blue, tvb, offset + framebuffer_data->blue_offset / 8, 1, ENC_LITTLE_ENDIAN);

                            if (framebuffer_data->alpha_offset > 0) {
                                if (framebuffer_data->alpha_length == 0)
                                    proto_tree_add_item(pixel_tree, hf_framebuffer_unused, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_LITTLE_ENDIAN);
                                else
                                    proto_tree_add_item(pixel_tree, hf_framebuffer_alpha, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_LITTLE_ENDIAN);
                                offset += 1;
                                proto_item_set_len(pixel_item, 4);
                            }
                            offset += 3;
                        }
                    } else {
                        offset = tvb_captured_length(tvb);
                    }
                } else {
                    offset = tvb_captured_length(tvb);
                }
            }
        } else if (g_strcmp0(service, "track-jdwp") == 0) {
            guint32  data_length;

            offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            if (tvb_reported_length_remaining(tvb, offset) > 0) {
                sub_item = proto_tree_add_item(main_tree, hf_pids, tvb, offset, -1, ENC_NA | ENC_ASCII);
                if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
                    expert_add_info(pinfo, sub_item, &ei_incomplete_message);
                }
            }
            offset = tvb_captured_length(tvb);
        } else if ((g_strcmp0(service, "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -B") == 0) ||
                (g_strcmp0(service, "shell:logcat -B") == 0)) {
            tvbuff_t    *next_tvb;
            tvbuff_t    *new_tvb;
            guint8      *buffer = NULL;
            gint         size = 0;
            gint         i_offset = offset;
            gint         old_offset;
            gint         i_char = 0;
            guint8       c1;
            guint8       c2 = '\0';
            guint16      payload_length;
            guint16      try_header_size;
            gint         logcat_length = 0;
            fragment_t  *fragment;

            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                key[i_key].length = 1;
                key[i_key].key = &adb_service_data->session_key[i_key];
            }
            key[i_key].length = 0;
            key[i_key].key = NULL;

            subtree = (wmem_tree_t *) wmem_tree_lookup32_array(fragments, key);
            fragment = (subtree) ? (fragment_t *) wmem_tree_lookup32_le(subtree, pinfo->num - 1) : NULL;
            if (fragment) {
                if (!pinfo->fd->flags.visited && fragment->reassembled_in_frame == -1)
                    fragment->reassembled_in_frame = pinfo->num;

                if (fragment->reassembled_in_frame == pinfo->num) {
                    size += fragment->length;
                    i_char += fragment->length;
                }
            }

            size += tvb_reported_length_remaining(tvb, i_offset);
            if (size > 0) {
                buffer = (guint8 *) wmem_alloc(pinfo->pool, size);
                if (fragment && i_char > 0)
                    memcpy(buffer, fragment->data, i_char);

                if (i_char >= 1 && buffer[i_char - 1] == '\r' && tvb_get_guint8(tvb, i_offset) == '\n') {
                    buffer[i_char - 1] = '\n';
                    i_offset += 1;
                }

                c1 = tvb_get_guint8(tvb, i_offset);
                i_offset += 1;
                old_offset = i_offset;

                while (tvb_reported_length_remaining(tvb, i_offset) > 0) {
                    c2 = tvb_get_guint8(tvb, i_offset);

                    if (c1 == '\r' && c2 == '\n') {
                        buffer[i_char] = c2;
                        if (tvb_reported_length_remaining(tvb, i_offset) > 1) {
                            c1 = tvb_get_guint8(tvb, i_offset + 1);
                            i_offset += 2;
                            i_char += 1;
                        } else {
                            i_offset += 1;
                        }

                        continue;
                    }

                    buffer[i_char] = c1;
                    c1 = c2;
                    i_char += 1;
                    i_offset += 1;
                }

                if (tvb_reported_length_remaining(tvb, old_offset) == 0) {
                    buffer[i_char] = c1;
                    i_char += 1;
                } else if (tvb_reported_length_remaining(tvb, old_offset) > 0) {
                    buffer[i_char] = c2;
                    i_char += 1;
                }

                next_tvb = tvb_new_child_real_data(tvb, buffer, i_char, i_char);
                add_new_data_source(pinfo, next_tvb, "Logcat");

                i_offset = 0;
                while (tvb_reported_length_remaining(next_tvb, i_offset) > 0) {
                    if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4) {
                        payload_length = tvb_get_letohs(next_tvb, i_offset);
                        try_header_size = tvb_get_letohs(next_tvb, i_offset + 2);

                        if (try_header_size != 24)
                            logcat_length = payload_length + 20;
                        else
                            logcat_length = payload_length + 24;
                    }

                    if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4 && tvb_reported_length_remaining(next_tvb, i_offset) >= logcat_length) {
                        new_tvb = tvb_new_subset_length(next_tvb, i_offset, logcat_length);

                        call_dissector(logcat_handle, new_tvb, pinfo, main_tree);
                        i_offset += logcat_length;
                    } else {

                        if (!pinfo->fd->flags.visited) {
                            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 2 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
                            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                                key[i_key].length = 1;
                                key[i_key].key = &adb_service_data->session_key[i_key];
                            }
                            key[i_key].length = 1;
                            key[i_key++].key = &pinfo->num;
                            key[i_key].length = 0;
                            key[i_key].key = NULL;

                            fragment = wmem_new(wmem_file_scope(), fragment_t);

                            fragment->length = tvb_captured_length_remaining(next_tvb, i_offset);
                            fragment->data = (guint8 *) wmem_alloc(wmem_file_scope(), fragment->length);
                            tvb_memcpy(next_tvb, fragment->data, i_offset, fragment->length);
                            fragment->reassembled_in_frame = -1;

                            wmem_tree_insert32_array(fragments, key, fragment);
                        }

                        proto_tree_add_item(main_tree, hf_fragment, next_tvb, i_offset, -1, ENC_NA);
                        i_offset = tvb_captured_length(next_tvb);
                    }
                }
            }

            offset = tvb_captured_length(tvb);
        } else if (g_str_has_prefix(service, "shell:")) {
            if (adb_service_data->direction == P2P_DIR_SENT) {
                proto_tree_add_item(main_tree, hf_stdin, tvb, offset, -1, ENC_NA | ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, " Stdin=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset)));

            } else {
                proto_tree_add_item(main_tree, hf_stdout, tvb, offset, -1, ENC_NA | ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, " Stdout=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset)));
            }
            offset = tvb_captured_length(tvb);
        } else if (g_str_has_prefix(service, "jdwp:")) {
/* TODO */
            proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
            offset = tvb_captured_length(tvb);
        } else if (g_str_has_prefix(service, "sync:")) {
/* TODO */
            proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
            offset = tvb_captured_length(tvb);
        } else if (g_strcmp0(service, "host:list-forward") == 0 ||
                g_str_has_prefix(service, "root:") ||
                g_str_has_prefix(service, "remount:")  ||
                g_str_has_prefix(service, "tcpip:")  ||
                g_str_has_prefix(service, "usb:")) {
            if (tvb_reported_length_remaining(tvb, offset)) {
                proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, " Result=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset)));

                offset = tvb_captured_length(tvb);
            }
        } else {
            proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
            offset = tvb_captured_length(tvb);
        }

    return offset;
}
Example #20
0
static int
dissect_banana_element(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) {
    proto_item *ti;
    proto_tree *list_tree;
    guint8 byte = 0;
    gint64 val = 0;
    gint val_len = 0;
    int start_offset = offset;
    int old_offset;
    int i;

    /* Accumulate our value/length 'til we hit a valid type */
    while (tvb_length_remaining(tvb, offset) > 0) {
        byte = tvb_get_guint8(tvb, offset);
        offset++;

        if (byte & 0x80) {
            if (is_element(byte)) {
                break;
            } else {
                expert_add_info_format(pinfo, NULL, &ei_banana_unknown_type, "Unknown type %u", byte);
            }
        } else {
            val_len++;
            if (val_len > MAX_ELEMENT_VAL_LEN) {
                expert_add_info(pinfo, NULL, &ei_banana_too_many_value_bytes);
            }
            val += byte + (val << 7);
        }
    }

    /* Type */
    switch (byte) {
        case BE_LIST:
            if (val > MAX_ELEMENT_VAL) {
                expert_add_info_format(pinfo, NULL, &ei_banana_length_too_long, "List length %" G_GINT64_MODIFIER "d longer than we can handle", val);
            }
            ti = proto_tree_add_uint_format_value(tree, hf_banana_list, tvb, start_offset, offset - start_offset - 1, (guint32) val, "(%d items)", (gint) val);
            list_tree = proto_item_add_subtree(ti, ett_list);
            for (i = 0; i < val; i++) {
                old_offset = offset;
                offset += dissect_banana_element(tvb, pinfo, list_tree, offset);
                if (offset <= old_offset) {
                    return offset - start_offset;
                }
            }
            break;
        case BE_INT:
            if (val > MAX_ELEMENT_VAL) {
                expert_add_info_format(pinfo, NULL, &ei_banana_value_too_large, "Integer value %" G_GINT64_MODIFIER "d too large", val);
            }
            proto_tree_add_uint(tree, hf_banana_int, tvb, start_offset, offset - start_offset, (guint32) val);
            break;
        case BE_STRING:
            if (val > MAX_ELEMENT_VAL) {
                expert_add_info_format(pinfo, NULL, &ei_banana_length_too_long, "String length %" G_GINT64_MODIFIER "d longer than we can handle", val);
            }
            proto_tree_add_item(tree, hf_banana_string, tvb, offset, (guint32) val, ENC_ASCII|ENC_NA);
            offset += (gint) val;
            break;
        case BE_NEG_INT:
            if (val > MAX_ELEMENT_VAL) {
                expert_add_info_format(pinfo, NULL, &ei_banana_value_too_large, "Integer value -%" G_GINT64_MODIFIER "d too large", val);
            }
            proto_tree_add_int(tree, hf_banana_neg_int, tvb, start_offset, offset - start_offset, (gint32) val * -1);
            break;
        case BE_FLOAT:
            proto_tree_add_item(tree, hf_banana_float, tvb, offset, 8, ENC_BIG_ENDIAN);
            offset += 8;
            break;
        case BE_LG_INT:
            proto_tree_add_item(tree, hf_banana_lg_int, tvb, start_offset, offset - start_offset, ENC_NA);
            break;
        case BE_LG_NEG_INT:
            proto_tree_add_item(tree, hf_banana_lg_neg_int, tvb, start_offset, offset - start_offset, ENC_NA);
            break;
        case BE_PB:
            if (val_len > 1) {
                expert_add_info(pinfo, NULL, &ei_banana_pb_error);
            }
            /*
             * The spec says the pb dictionary value comes after the tag.
             * In real-world captures it comes before.
             */
            proto_tree_add_item(tree, hf_banana_pb, tvb, offset - 2, 1, ENC_BIG_ENDIAN);
            break;
        default:
            return 0;
            break;
    }
    return offset - start_offset;
}
Example #21
0
/*
 * dissect_pgm - The dissector for Pragmatic General Multicast
 */
static void
dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint16 pgmhdr_sport;
	guint16 pgmhdr_dport;
	guint8  pgmhdr_type;
	guint8  pgmhdr_opts;
	guint16 pgmhdr_cksum;
	guint16 pgmhdr_tsdulen;
	guint32 sqn;
	guint16 afi;

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

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

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

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

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

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

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

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

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

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

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

		pgm_tree = proto_item_add_subtree(ti, ett_pgm);

		cursor = ptvcursor_new(pgm_tree, tvb, 0);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		ptvcursor_free(cursor);
	}
}
Example #22
0
/*
* Dissect ROS PDUs inside a PPDU.
*/
static int
dissect_ros(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
{
	int offset = 0;
	int old_offset;
	proto_item *item;
	proto_tree *tree;
	proto_tree *next_tree=NULL;
	conversation_t *conversation;
	ros_conv_info_t *ros_info = NULL;
	asn1_ctx_t asn1_ctx;
	asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);

	/* do we have application context from the acse dissector? */
	if (data == NULL)
		return 0;
	asn1_ctx.private_data = data;

	/* save parent_tree so subdissectors can create new top nodes */
	top_tree=parent_tree;

	conversation = find_or_create_conversation(pinfo);

	/*
	 * Do we already have our info
	 */
	ros_info = (ros_conv_info_t *)conversation_get_proto_data(conversation, proto_ros);
	if (ros_info == NULL) {

	  /* No.  Attach that information to the conversation. */

	  ros_info = (ros_conv_info_t *)g_malloc(sizeof(ros_conv_info_t));
	  ros_info->matched=g_hash_table_new(ros_info_hash_matched, ros_info_equal_matched);
	  ros_info->unmatched=g_hash_table_new(ros_info_hash_unmatched, ros_info_equal_unmatched);

	  conversation_add_proto_data(conversation, proto_ros, ros_info);

	  ros_info->next = ros_info_items;
	  ros_info_items = ros_info;
	}

	item = proto_tree_add_item(parent_tree, proto_ros, tvb, 0, -1, ENC_NA);
	tree = proto_item_add_subtree(item, ett_ros);

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

	while (tvb_reported_length_remaining(tvb, offset) > 0){
		old_offset=offset;
		offset=dissect_ros_ROS(FALSE, tvb, offset, &asn1_ctx , tree, -1);
		if(offset == old_offset){
			next_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ros_unknown, &item, "Unknown ROS PDU");

			expert_add_info(pinfo, item, &ei_ros_unknown_ros_pdu);
			dissect_unknown_ber(pinfo, tvb, offset, next_tree);
			break;
		}
	}

	return tvb_captured_length(tvb);
}
Example #23
0
static
void dissect_pw_satop(tvbuff_t * tvb_original
					,packet_info * pinfo
					,proto_tree * tree
					,pwc_demux_type_t demux)
{
	const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/
	gint      packet_size;
	gint      payload_size;
	gint      padding_size;
	int properties;

	enum {
		PAY_NO_IDEA = 0
		,PAY_LIKE_E1
		,PAY_LIKE_T1
		,PAY_LIKE_E3_T3
		,PAY_LIKE_OCTET_ALIGNED_T1
	} payload_properties;

	packet_size = tvb_reported_length_remaining(tvb_original, 0);
	/*
	 * FIXME
	 * "4" below should be replaced by something like "min_packet_size_this_dissector"
	 * Also call to dissect_try_cw_first_nibble() should be moved before this block
	 */
	if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
	{
		proto_item  *item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		expert_add_info_format(pinfo, item, &ei_cw_packet_size_too_small,
				       "PW packet size (%d) is too small to carry sensible information"
				       ,(int)packet_size);
		col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
		col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
		return;
	}

	switch (demux)
	{
	case PWC_DEMUX_MPLS:
		if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree))
		{
			return;
		}
		break;
	case PWC_DEMUX_UDP:
		break;
	default:
		DISSECTOR_ASSERT_NOT_REACHED();
		return;
	}

	/* check how "good" is this packet */
	/* also decide payload length from packet size and CW */
	properties = 0;
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/))
	{
		properties |= PWC_CW_BAD_BITS03;
	}
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0x03 /*rsv*/))
	{
		properties |= PWC_CW_BAD_RSV;
	}
	if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/))
	{
		properties |= PWC_CW_BAD_FRAG;
	}
	{
		/* RFC4553:
		 * [...MAY be used to carry the length of the SAToP
		 * packet (defined as the size of the SAToP header + the payload
		 * size) if it is less than 64 bytes, and MUST be set to zero
		 * otherwise... ]
		 *
		 * Note that this differs from RFC4385's definition of length:
		 * [ If the MPLS payload is less than 64 bytes, the length field
		 * MUST be set to the length of the PW payload...]
		 *
		 * We will use RFC4553's definition here.
		 */
		int  cw_len;
		gint payload_size_from_packet;

		cw_len = tvb_get_guint8(tvb_original, 1) & 0x3f;
		payload_size_from_packet = packet_size - encaps_size;
		if (cw_len != 0)
		{
			gint payload_size_from_cw;
			payload_size_from_cw = cw_len - encaps_size;
			/*
			 * Assumptions for error case,
			 * will be overwritten if no errors found:
			 */
			payload_size = payload_size_from_packet;
			padding_size = 0;

			if (payload_size_from_cw < 0)
			{
				properties |= PWC_CW_BAD_PAYLEN_LT_0;
			}
			else if (payload_size_from_cw > payload_size_from_packet)
			{
				properties |= PWC_CW_BAD_PAYLEN_GT_PACKET;
			}
			else if (payload_size_from_packet >= 64)
			{
				properties |= PWC_CW_BAD_LEN_MUST_BE_0;
			}
			else /* ok */
			{
				payload_size = payload_size_from_cw;
				padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
			}
		}
		else
		{
			payload_size = payload_size_from_packet;
			padding_size = 0;
		}
	}
	if (payload_size == 0)
	{
		/*
		 * As CW.L it indicates that PW payload is invalid, dissector should
		 * not blame packets with bad payload (including "bad" or "strange" SIZE of
		 * payload) when L bit is set.
		 */
		if (0 == (tvb_get_guint8(tvb_original, 0) & 0x08 /*L bit*/))
		{
			properties |= PWC_PAY_SIZE_BAD;
		}
	}

	/* guess about payload type */
	if (payload_size == 256)
	{
		payload_properties = PAY_LIKE_E1;
	}
	else if (payload_size == 192)
	{
		payload_properties = PAY_LIKE_T1;
	}
	else if (payload_size == 1024)
	{
		payload_properties = PAY_LIKE_E3_T3;
	}
	else if ((payload_size != 0) && (payload_size % 25 == 0))
	{
		payload_properties = PAY_LIKE_OCTET_ALIGNED_T1;
	}
	else
	{
		payload_properties = PAY_NO_IDEA; /*we do not have any ideas about payload type*/
	}

	/* fill up columns*/
	col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
	col_clear(pinfo->cinfo, COL_INFO);
	if (properties & PWC_ANYOF_CW_BAD)
	{
		col_set_str(pinfo->cinfo, COL_INFO, "CW:Bad, ");
	}

	if (properties & PWC_PAY_SIZE_BAD)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "Payload size:0 (Bad)");
	}
	else
	{
		col_append_fstr(pinfo->cinfo, COL_INFO, "TDM octets:%d", (int)payload_size);
	}

	if (padding_size != 0)
	{
		col_append_fstr(pinfo->cinfo, COL_INFO, ", Padding:%d", (int)padding_size);
	}


	{
		proto_item* item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE);
		pwc_item_append_text_n_items(item,(int)payload_size,"octet");
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				proto_item* item2;
				tvb = tvb_new_subset(tvb_original, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
				item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA);
				pwc_item_append_cw(item2, tvb_get_ntohl(tvb, 0),FALSE);
				{
					proto_tree* tree3;
					tree3 = proto_item_add_subtree(item2, ett);
					{
						proto_item* item3;
						if (properties & PWC_CW_BAD_BITS03) /*display only if value is wrong*/
						{
							item3 = proto_tree_add_item(tree3, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN);
							expert_add_info(pinfo, item3, &ei_cw_bits03);
						}

						proto_tree_add_item(tree3, hf_cw_l  , tvb, 0, 1, ENC_BIG_ENDIAN);
						proto_tree_add_item(tree3, hf_cw_r  , tvb, 0, 1, ENC_BIG_ENDIAN);

						item3 = proto_tree_add_item(tree3, hf_cw_rsv, tvb, 0, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_RSV)
						{
							expert_add_info(pinfo, item3, &ei_cw_rsv);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_frg, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_FRAG)
						{
							expert_add_info(pinfo, item3, &ei_cw_frg);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_len, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_PAYLEN_LT_0)
						{
							expert_add_info_format(pinfo, item3, &ei_payload_size_invalid,
								"Bad Length: too small, must be > %d",
								(int)encaps_size);
						}
						if (properties & PWC_CW_BAD_PAYLEN_GT_PACKET)
						{
							expert_add_info_format(pinfo, item3, &ei_payload_size_invalid,
								"Bad Length: must be <= than PSN packet size (%d)",
								(int)packet_size);
						}
						if (properties & PWC_CW_BAD_LEN_MUST_BE_0)
						{
							expert_add_info_format(pinfo, item3, &ei_payload_size_invalid,
								"Bad Length: must be 0 if SAToP packet size (%d) is > 64",
								(int)packet_size);
						}

						proto_tree_add_item(tree3, hf_cw_seq, tvb, 2, 2, ENC_BIG_ENDIAN);
					}
				}
			}
		}

		/* payload */
		if (properties & PWC_PAY_SIZE_BAD)
		{
			expert_add_info_format(pinfo, item, &ei_payload_size_invalid,
				"SAToP payload: none found. Size of payload must be <> 0");
		}
		else if (payload_size == 0)
		{
			expert_add_info(pinfo, item, &ei_payload_size_invalid_undecoded);
		}
		else
		{

			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				proto_item* item2;
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW, payload_size, payload_size);
				item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA);
				pwc_item_append_text_n_items(item2,(int)payload_size,"octet");
				{
					proto_tree* tree3;
					const char* s;
					switch(payload_properties)
					{
					case PAY_LIKE_E1:
						s = " (looks like E1)";
						break;
					case PAY_LIKE_T1:
						s = " (looks like T1)";
						break;
					case PAY_LIKE_E3_T3:
						s = " (looks like E3/T3)";
						break;
					case PAY_LIKE_OCTET_ALIGNED_T1:
						s = " (looks like octet-aligned T1)";
						break;
					case PAY_NO_IDEA:
					default:
						s = "";
						break;
					}
					proto_item_append_text(item2, "%s", s);
					tree3 = proto_item_add_subtree(item2, ett);
					call_dissector(data_handle, tvb, pinfo, tree3);
					item2 = proto_tree_add_int(tree3, hf_payload_l, tvb, 0, 0
						,(int)payload_size); /* allow filtering */
					PROTO_ITEM_SET_HIDDEN(item2);
				}
			}
		}

		/* padding */
		if (padding_size > 0)
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1);
				call_dissector(pw_padding_handle, tvb, pinfo, tree2);
			}
		}
	}
	return;
}
/*FUNCTION:------------------------------------------------------
 *  NAME
 *      dissect_zbee_secure
 *  DESCRIPTION
 *      Dissects and decrypts secured ZigBee frames.
 *
 *      Will return a valid tvbuff only if security processing was
 *      successful. If processing fails, then this function will
 *      handle internally and return NULL.
 *  PARAMETERS
 *      tvbuff_t    *tvb    - pointer to buffer containing raw packet.
 *      packet_info *pinfo  - pointer to packet information fields
 *      proto_tree  *tree   - pointer to data tree Wireshark uses to display packet.
 *      guint       offset  - pointer to the start of the auxilliary security header.
 *      guint64     src64   - extended source address, or 0 if unknown.
 *  RETURNS
 *      tvbuff_t *
 *---------------------------------------------------------------
 */
tvbuff_t *
dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset)
{
    proto_tree     *sec_tree = NULL;
    proto_item     *sec_root;
    proto_tree     *field_tree;
    proto_item     *ti;

    zbee_security_packet    packet;
    guint           mic_len;
    gint            payload_len;
    tvbuff_t       *payload_tvb;

#ifdef HAVE_LIBGCRYPT
    guint8             *enc_buffer;
    guint8             *dec_buffer;
    gboolean            decrypted;
    GSList            **nwk_keyring;
    GSList             *GSList_i;
    key_record_t       *key_rec = NULL;
#endif
    zbee_nwk_hints_t   *nwk_hints;
    ieee802154_hints_t *ieee_hints;
    ieee802154_map_rec *map_rec = NULL;

    /* Init */
    memset(&packet, 0, sizeof(zbee_security_packet));

    /* Get pointers to any useful frame data from lower layers */
    nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
        proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK), 0);
    ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
        proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);

    /* Create a subtree for the security information. */
    if (tree) {
        sec_root = proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "ZigBee Security Header");
        sec_tree = proto_item_add_subtree(sec_root, ett_zbee_sec);
    }

    /*  Get and display the Security control field */
    packet.control  = tvb_get_guint8(tvb, offset);

    /* Patch the security level. */
    packet.control &= ~ZBEE_SEC_CONTROL_LEVEL;
    packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level);

    /*
     * Eww, I think I just threw up a little...  ZigBee requires this field
     * to be patched before computing the MIC, but we don't have write-access
     * to the tvbuff. So we need to allocate a copy of the whole thing just
     * so we can fix these 3 bits. Memory allocated by tvb_memdup(wmem_packet_scope(),...)
     * is automatically freed before the next packet is processed.
     */
#ifdef HAVE_LIBGCRYPT
    enc_buffer = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_length(tvb));
    /*
     * Override the const qualifiers and patch the security level field, we
     * know it is safe to overide the const qualifiers because we just
     * allocated this memory via tvb_memdup(wmem_packet_scope(),...).
     */
    enc_buffer[offset] = packet.control;
#endif /* HAVE_LIBGCRYPT */
    packet.level    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL);
    packet.key_id   = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY);
    packet.nonce    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE);
    if (tree) {
        ti = proto_tree_add_text(sec_tree, tvb, offset, 1, "Security Control Field");
        field_tree = proto_item_add_subtree(ti, ett_zbee_sec_control);

        proto_tree_add_uint(field_tree, hf_zbee_sec_key_id, tvb, offset, 1,
                                packet.control & ZBEE_SEC_CONTROL_KEY);
        proto_tree_add_boolean(field_tree, hf_zbee_sec_nonce, tvb, offset, 1,
                                packet.control & ZBEE_SEC_CONTROL_NONCE);
    }
    offset += 1;

    /* Get and display the frame counter field. */
    packet.counter = tvb_get_letohl(tvb, offset);
    if (tree) {
        proto_tree_add_uint(sec_tree, hf_zbee_sec_counter, tvb, offset, 4, packet.counter);
    }
    offset += 4;

    if (packet.nonce) {
        /* Get and display the source address of the device that secured this payload. */
        packet.src64 = tvb_get_letoh64(tvb, offset);
        if (tree) {
            proto_tree_add_item(sec_tree, hf_zbee_sec_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
        }
#if 1
        if (!pinfo->fd->flags.visited) {
            switch ( packet.key_id ) {
                case ZBEE_SEC_KEY_LINK:
                if (nwk_hints && ieee_hints) {
                    /* Map this long address with the nwk layer short address. */
                    nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, nwk_hints->src,
                            ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->fd->num);
                }
                break;

                case ZBEE_SEC_KEY_NWK:
                if (ieee_hints) {
                    /* Map this long address with the ieee short address. */
                    ieee_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, ieee_hints->src16,
                        ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->fd->num);
                }
                break;

                /* We ignore the extended source addresses used to encrypt payloads with these
                 * types of keys, because they can emerge from APS tunnels created by nodes whose
                 * short address is not recorded in the packet. */
                case ZBEE_SEC_KEY_TRANSPORT:
                case ZBEE_SEC_KEY_LOAD:
                break;
            }
        }
#endif
        offset += 8;
    }
    else {
        /* Look for a source address in hints */
        switch ( packet.key_id ) {
            case ZBEE_SEC_KEY_NWK:
                /* use the ieee extended source address for NWK decryption */
                if ( ieee_hints && (map_rec = ieee_hints->map_rec) )
                    packet.src64 = map_rec->addr64;
                else if (tree)
                    proto_tree_add_text(sec_tree, tvb, 0, 0, "[Extended Source: Unknown]");
                break;

            default:
                /* use the nwk extended source address for APS decryption */
                if ( nwk_hints && (map_rec = nwk_hints->map_rec) )
                    packet.src64 = map_rec->addr64;
                else if (tree)
                    proto_tree_add_text(sec_tree, tvb, 0, 0, "[Extended Source: Unknown]");
                break;
        }
    }

    if (packet.key_id == ZBEE_SEC_KEY_NWK) {
        /* Get and display the key sequence number. */
        packet.key_seqno = tvb_get_guint8(tvb, offset);
        if (tree) {
            proto_tree_add_uint(sec_tree, hf_zbee_sec_key_seqno, tvb, offset, 1, packet.key_seqno);
        }
        offset += 1;
    }

    /* Determine the length of the MIC. */
    switch (packet.level) {
        case ZBEE_SEC_ENC:
        case ZBEE_SEC_NONE:
        default:
            mic_len=0;
            break;

        case ZBEE_SEC_ENC_MIC32:
        case ZBEE_SEC_MIC32:
            mic_len=4;
            break;

        case ZBEE_SEC_ENC_MIC64:
        case ZBEE_SEC_MIC64:
            mic_len=8;
            break;

        case ZBEE_SEC_ENC_MIC128:
        case ZBEE_SEC_MIC128:
            mic_len=16;
            break;
    } /* switch */

    /* Get and display the MIC. */
    if (mic_len) {
        /* Display the MIC. */
        if (tree) {
            proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, (gint)(tvb_length(tvb)-mic_len),
                   mic_len, ENC_NA);
        }
    }

    /* Check for null payload. */
    if ( !(payload_len = tvb_reported_length_remaining(tvb, offset+mic_len)) ) {
        return NULL;
    } else if ( payload_len < 0 ) {
        THROW(ReportedBoundsError);
    }

    /**********************************************
     *  Perform Security Operations on the Frame  *
     **********************************************
     */
    if ((packet.level == ZBEE_SEC_NONE) ||
        (packet.level == ZBEE_SEC_MIC32) ||
        (packet.level == ZBEE_SEC_MIC64) ||
        (packet.level == ZBEE_SEC_MIC128)) {

        /* Payload is only integrity protected. Just return the sub-tvbuff. */
        return tvb_new_subset(tvb, offset, payload_len, payload_len);
    }

#ifdef HAVE_LIBGCRYPT
    /* Allocate memory to decrypt the payload into. */
    dec_buffer = (guint8 *)g_malloc(payload_len);

    decrypted = FALSE;
    if ( packet.src64 ) {
        if (pinfo->fd->flags.visited) {
            if ( nwk_hints ) {
                /* Use previously found key */
                switch ( packet.key_id ) {
                    case ZBEE_SEC_KEY_NWK:
                        if ( (key_rec = nwk_hints->nwk) ) {
                            decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, nwk_hints->nwk->key);
                        }
                        break;

                    default:
                        if ( (key_rec = nwk_hints->link) ) {
                            decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, nwk_hints->link->key);
                        }
                        break;
                }
            }
        } /* ( !pinfo->fd->flags.visited ) */
        else {
            /* We only search for sniffed keys in the first pass,
             * to save time, and because decrypting with keys
             * transported in future packets is cheating */

            /* Lookup NWK and link key in hash for this pan. */
            /* This overkill approach is a placeholder for a hash that looks up
             * a key ring for a link key associated with a pair of devices.
             */
            if ( nwk_hints ) {
                nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan);

                if ( nwk_keyring ) {
                    GSList_i = *nwk_keyring;
                    while ( GSList_i && !decrypted ) {
                        decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);

                        if (decrypted) {
                            /* save pointer to the successful key record */
                            switch (packet.key_id) {
                                case ZBEE_SEC_KEY_NWK:
                                    key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
                                    break;

                                default:
                                    key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
                                    break;
                            }
                        } else {
                            GSList_i = g_slist_next(GSList_i);
                        }
                    }
                }

                /* Loop through user's password table for preconfigured keys, our last resort */
                GSList_i = zbee_pc_keyring;
                while ( GSList_i && !decrypted ) {
                    decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                            payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);

                    if (decrypted) {
                        /* save pointer to the successful key record */
                        switch (packet.key_id) {
                            case ZBEE_SEC_KEY_NWK:
                                key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
                                break;

                            default:
                                key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
                                break;
                        }
                    } else {
                        GSList_i = g_slist_next(GSList_i);
                    }
                }
            }
        } /* ( ! pinfo->fd->flags.visited ) */
    } /* ( packet.src64 ) */

    if ( decrypted ) {
        if ( tree && key_rec ) {
            if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) {
                ti = proto_tree_add_text(sec_tree, tvb, 0, 0, "Decryption Key: %s", key_rec->label);
            } else {
                ti = proto_tree_add_uint(sec_tree, hf_zbee_sec_key_origin, tvb, 0, 0,
                        key_rec->frame_num);
            }
            PROTO_ITEM_SET_GENERATED(ti);
        }

        /* Found a key that worked, setup the new tvbuff_t and return */
        payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len);
        tvb_set_free_cb(payload_tvb, g_free); /* set up callback to free dec_buffer */
        add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload");

        /* Done! */
        return payload_tvb;
    }

    g_free(dec_buffer);
#endif /* HAVE_LIBGCRYPT */

    /* Add expert info. */
    expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload);
    /* Create a buffer for the undecrypted payload. */
    payload_tvb = tvb_new_subset(tvb, offset, payload_len, -1);
    /* Dump the payload to the data dissector. */
    call_dissector(data_handle, payload_tvb, pinfo, tree);
    /* Couldn't decrypt, so return NULL. */
    return NULL;
} /* dissect_zbee_secure */
Example #25
0
static void dissect_tftp_message(tftp_conv_info_t *tftp_info,
                                 tvbuff_t *tvb, packet_info *pinfo,
                                 proto_tree *tree)
{
    proto_tree	 *tftp_tree = NULL;
    proto_item	 *ti;
    gint		 offset = 0;
    guint16		 opcode;
    guint16		 bytes;
    guint16		 blocknum;
    guint		 i1;
    guint16	         error;

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

    opcode = tvb_get_ntohs(tvb, offset);

    col_add_str(pinfo->cinfo, COL_INFO,
                val_to_str(opcode, tftp_opcode_vals, "Unknown (0x%04x)"));

    if (tree) {
        ti = proto_tree_add_item(tree, proto_tftp, tvb, offset, -1, ENC_NA);
        tftp_tree = proto_item_add_subtree(ti, ett_tftp);

        if (tftp_info->source_file) {
            ti = proto_tree_add_string(tftp_tree, hf_tftp_source_file, tvb,
                                       0, 0, tftp_info->source_file);
            PROTO_ITEM_SET_GENERATED(ti);
        }

        if (tftp_info->destination_file) {
            ti = proto_tree_add_string(tftp_tree, hf_tftp_destination_file, tvb,
                                       0, 0, tftp_info->destination_file);
            PROTO_ITEM_SET_GENERATED(ti);
        }

        proto_tree_add_uint(tftp_tree, hf_tftp_opcode, tvb,
                            offset, 2, opcode);
    }
    offset += 2;

    switch (opcode) {

    case TFTP_RRQ:
        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_source_file,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        tftp_info->source_file = tvb_get_seasonal_string(tvb, offset, i1);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        tftp_dissect_options(tvb, pinfo,  offset, tftp_tree,
                             opcode, tftp_info);
        break;

    case TFTP_WRQ:
        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_destination_file,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        tftp_info->destination_file =
            tvb_get_seasonal_string(tvb, offset, i1);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                             opcode,  tftp_info);
        break;

    case TFTP_INFO:
        tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                             opcode,  tftp_info);
        break;

    case TFTP_DATA:
        blocknum = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
                            blocknum);

        offset += 2;

        bytes = tvb_reported_length_remaining(tvb, offset);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i%s",
                        blocknum,
                        (bytes < tftp_info->blocksize)?" (last)":"" );

        if (bytes != 0) {
            tvbuff_t *data_tvb = tvb_new_subset(tvb, offset, -1, bytes);
            call_dissector(data_handle, data_tvb, pinfo, tree);
        }
        break;

    case TFTP_ACK:
        blocknum = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
                            blocknum);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i",
                        blocknum);
        break;

    case TFTP_ERROR:
        error = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(tftp_tree, hf_tftp_error_code, tvb, offset, 2,
                            error);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Code: %s",
                        val_to_str(error, tftp_error_code_vals, "Unknown (%u)"));

        offset += 2;

        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_error_string, tvb, offset,
                            i1, ENC_ASCII|ENC_NA);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Message: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        expert_add_info(pinfo, NULL, &ei_tftp_blocksize_range);
        break;

    case TFTP_OACK:
        tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                             opcode, tftp_info);
        break;

    default:
        proto_tree_add_text(tftp_tree, tvb, offset, -1,
                            "Data (%d bytes)", tvb_reported_length_remaining(tvb, offset));
        break;

    }

    return;
}
static int elasticsearch_partial_dissect_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) {
    proto_tree *address_tree;
    proto_item *address_item;
    int start_offset;
    guint8 es_address_format;
    guint8 address_length;
    vstring_t address_name;
    guint16 address_type_id;

    /* Store this away for later */
    start_offset = offset;

    /* Address tree */
    address_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_elasticsearch_address, &address_item, "Address" );

    /* Address type */
    proto_tree_add_item(address_tree, hf_elasticsearch_address_type, tvb, offset, 2, ENC_BIG_ENDIAN);
    address_type_id = tvb_get_ntohs(tvb, offset);
    offset += 2;
    /* Only socket address types are supported (and only make sense to be supported) */
    if(address_type_id != ADDRESS_TYPE_SOCKET) {
        expert_add_info(pinfo, tree, &ei_elasticsearch_unsupported_address_type);
        return offset;
    }

    /* Address format */
    es_address_format = tvb_get_guint8(tvb, offset);
    proto_tree_add_item(address_tree, hf_elasticsearch_address_format, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset += 1;

    switch(es_address_format) {
    case ADDRESS_FORMAT_NUEMRIC:
        address_length = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(address_tree, hf_elasticsearch_address_length, tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;
        /* Its either IPv4 or IPv6 depending on the length */
        if (address_length == IPv4_ADDRESS_LENGTH) {
            proto_tree_add_item(address_tree, hf_elasticsearch_address_ipv4, tvb, offset, 4, ENC_NA);
            offset += 4;
        }
        else {
            proto_tree_add_item(address_tree, hf_elasticsearch_address_ipv6, tvb, offset, 16, ENC_NA);
            offset += 16;
            proto_tree_add_item(address_tree, hf_elasticsearch_address_ipv6_scope_id, tvb, offset, 4, ENC_BIG_ENDIAN);
            offset += 4;
        }
        break;

    case ADDRESS_FORMAT_STRING:
        address_name = read_vstring(tvb, offset);
        proto_tree_add_string(address_tree, hf_elasticsearch_address_name, tvb, offset, address_name.length, address_name.value);
        offset += address_name.length;
        break;

    default:
        /* Shouldn't get here, invalid format type */
        expert_add_info(pinfo, tree, &ei_elasticsearch_unsupported_address_format);
        break;
    }

    proto_tree_add_item(address_item, hf_elasticsearch_address_port, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;

    /* Fix up the length of the subtree */
    proto_item_set_len(address_item, offset - start_offset);

    return offset;
}
Example #27
0
static void
dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, int linelen)
{
    proto_tree *response_tree, *command_tree = NULL;
    proto_item *response_item, *command_item, *hidden_item;
    int         start_offset                 = offset;
    int         end_offset                   = start_offset+linelen;
    gint        eop_offset                   = -1,
                eoc_offset                   = -1,
                eocp_offset,
                tag_start_offset, tag_end_offset;
    guint8*     str_command;
    guint16     num_command;
    guchar      found_needle                 = 0,
                found_tag_needle             = 0;
    gboolean    first_command_param          = TRUE;

    response_item = proto_tree_add_item(tree, hf_irc_response, tvb, offset, linelen, ENC_ASCII|ENC_NA);
    if (linelen <= 0)
        return;

    response_tree = proto_item_add_subtree(response_item, ett_irc_response );

    /* Check if message has a prefix */
    if (tvb_get_guint8(tvb, offset) == ':')
    {
        /* find the end of the prefix */
        eop_offset = tvb_pbrk_guint8(tvb, offset+1, linelen-1, " ", &found_needle);
        if (eop_offset == -1)
        {
            expert_add_info(pinfo, response_item, &ei_irc_prefix_missing_ending_space);
            return;
        }

        proto_tree_add_item(response_tree, hf_irc_response_prefix, tvb, offset+1, eop_offset-offset-1, ENC_ASCII|ENC_NA);
        found_needle = 0;
        offset = eop_offset+1;
    }

    /* clear out any whitespace before command */
    while(offset < end_offset && tvb_get_guint8(tvb, offset) == ' ')
    {
        offset++;
    }
    if (offset == end_offset)
    {
        expert_add_info(pinfo, response_item, &ei_irc_response_command);
        return;
    }

    eoc_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, " ", &found_needle);
    if (eoc_offset == -1)
    {
        proto_tree_add_item(response_tree, hf_irc_response_command, tvb, offset, end_offset-offset, ENC_ASCII|ENC_NA);
        col_append_fstr( pinfo->cinfo, COL_INFO, " (%s)", tvb_get_string(wmem_packet_scope(), tvb, offset, end_offset-offset));

        /* if response command is numeric, allow it to be filtered as an integer */
        if ((end_offset-offset == 3) &&
            (isdigit(tvb_get_guint8(tvb, offset))) &&
            (isdigit(tvb_get_guint8(tvb, offset+1))) &&
            (isdigit(tvb_get_guint8(tvb, offset+2))))
        {
            num_command = ((tvb_get_guint8(tvb, offset)-0x30)*100) + ((tvb_get_guint8(tvb, offset+1)-0x30)*10) + (tvb_get_guint8(tvb, offset+2)-0x30);
            hidden_item = proto_tree_add_uint(response_tree, hf_irc_response_num_command, tvb, offset, end_offset-offset, num_command);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
        }
        return;
    }

    proto_tree_add_item(response_tree, hf_irc_response_command, tvb, offset, eoc_offset-offset, ENC_ASCII|ENC_NA);
    str_command = tvb_get_string(wmem_packet_scope(), tvb, offset, eoc_offset-offset);
    col_append_fstr( pinfo->cinfo, COL_INFO, " (%s)", str_command);

    /* if response command is numeric, allow it to be filtered as an integer */
    if ((eoc_offset-offset == 3) &&
       (isdigit(tvb_get_guint8(tvb, offset))) &&
       (isdigit(tvb_get_guint8(tvb, offset+1))) &&
       (isdigit(tvb_get_guint8(tvb, offset+2))))
    {
        num_command = ((tvb_get_guint8(tvb, offset)-0x30)*100) + ((tvb_get_guint8(tvb, offset+1)-0x30)*10) + (tvb_get_guint8(tvb, offset+2)-0x30);
        hidden_item = proto_tree_add_uint(response_tree, hf_irc_response_num_command, tvb, offset, eoc_offset-offset, num_command);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
    }

    found_needle = 0;
    offset = eoc_offset+1;

    /* clear out any whitespace before command parameter */
    while(offset < end_offset && tvb_get_guint8(tvb, offset) == ' ')
    {
        offset++;
    }
    if (offset == end_offset)
    {
        /* No command parameters */
        return;
    }

    /* Check if message has a trailer */
    if (tvb_get_guint8(tvb, offset) == ':')
    {
        proto_tree_add_item(response_tree, hf_irc_response_trailer, tvb, offset+1, end_offset-offset-1, ENC_ASCII|ENC_NA);
        dissect_irc_tag_data(response_tree, response_item, tvb, offset+1, end_offset-offset-1, pinfo, str_command);
        return;
    }

    while(offset < end_offset)
    {
        eocp_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, " ", &found_needle);
        tag_start_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, TAG_DELIMITER, &found_tag_needle);

        /* Create subtree when the first parameter is found */
        if (first_command_param)
        {
            command_item = proto_tree_add_text(response_tree, tvb, offset, end_offset-offset, "Command parameters");
            command_tree = proto_item_add_subtree(command_item, ett_irc_response_command );
            first_command_param = FALSE;
        }

        if ((tag_start_offset == -1) || (eocp_offset < tag_start_offset))
        {
            /* regular message should be dissected */

            found_needle = 0;
            if (eocp_offset == -1)
            {
                proto_tree_add_item(command_tree, hf_irc_response_command_param, tvb, offset, end_offset-offset, ENC_ASCII|ENC_NA);
                return;
            }

            proto_tree_add_item(command_tree, hf_irc_response_command_param, tvb, offset, eocp_offset-offset, ENC_ASCII|ENC_NA);
            offset = eocp_offset+1;

            /* clear out any whitespace before next command parameter */
            while(offset < end_offset && tvb_get_guint8(tvb, offset) == ' ')
            {
                offset++;
            }
            if (offset == end_offset)
            {
                break;
            }

            /* Check if message has a trailer */
            if (tvb_get_guint8(tvb, offset) == ':')
            {
                proto_tree_add_item(response_tree, hf_irc_response_trailer, tvb, offset+1, end_offset-offset-1, ENC_ASCII|ENC_NA);
                dissect_irc_tag_data(response_tree, response_item, tvb, offset+1, end_offset-offset-1, pinfo, str_command);
                return;
            }
        }
        else if ((eocp_offset == -1) || (eocp_offset > tag_start_offset))
        {
            /* tag data dissected */

            found_tag_needle = 0;
            tag_end_offset = tvb_pbrk_guint8(tvb, tag_start_offset+1, end_offset-tag_start_offset-1, TAG_DELIMITER, &found_tag_needle);
            if (tag_end_offset == -1)
            {
                expert_add_info(pinfo, response_item, &ei_irc_missing_end_delimiter);
                return;
            }

            dissect_irc_tag_data(response_tree, response_item, tvb, tag_start_offset, tag_end_offset-tag_start_offset, pinfo, str_command);
            offset = tag_end_offset+1;
        }
    }
}
Example #28
0
static int
dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
{
	proto_item  *volatile ti = NULL, *comment_item;
	guint	     cap_len = 0, frame_len = 0;
	proto_tree  *volatile tree;
	proto_tree  *comments_tree;
	proto_item  *item;
	const gchar *cap_plurality, *frame_plurality;
	int file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;

	tree=parent_tree;
	if (data != NULL) {
		file_type_subtype = GPOINTER_TO_INT(data);
	}

	switch (pinfo->phdr->rec_type) {

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

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

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

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

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

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

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

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

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

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

	default:
		g_assert_not_reached();
		break;
	}

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


	}

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

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

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

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

		fh_tree = proto_item_add_subtree(ti, ett_frame);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

			cp = tvb_get_ptr(tvb, 0, cap_len);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	tap_queue_packet(frame_tap, pinfo, NULL);


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

	return tvb_captured_length(tvb);
}
Example #29
0
/* Code to actually dissect the packets */
static void
dissect_fcfzs_zoneset(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset)
{
    int numzones, nummbrs, i, j, len;
    proto_item* ti;

    /* The zoneset structure has the following format */
    /* zoneset name (len[not including pad], name, pad),
     * number of zones,
     * for each zone,
     *     Zone name (len[not including pad], name, pad), num zone mbrs
     *     for each zone mbr,
     *         zone mbr id type, zone mbr id (len, name, pad)
     */

        /* Zoneset Name */
        len = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
                            1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4,
                            len, ENC_ASCII|ENC_NA);
        offset += 4 + len + (4-(len % 4));


        /* Number of zones */
        numzones = tvb_get_ntohl(tvb, offset);
        proto_tree_add_item(tree, hf_fcfzs_numzones, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        /* For each zone... */
        for (i = 0; i < numzones; i++) {
            len = tvb_get_guint8(tvb, offset);
            proto_tree_add_item(tree, hf_fcfzs_zonenmlen, tvb, offset,
                                1, ENC_BIG_ENDIAN);
            proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+4,
                                len, ENC_ASCII|ENC_NA);
            offset += 4 + len + (4-(len % 4));

            nummbrs = tvb_get_ntohl(tvb, offset);
            proto_tree_add_item(tree, hf_fcfzs_nummbrentries, tvb, offset,
                                4, ENC_BIG_ENDIAN);

            offset += 4;
            for (j = 0; j < nummbrs; j++) {
                ti = proto_tree_add_item(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN);

                switch (tvb_get_guint8(tvb, offset)) {
                case FC_FZS_ZONEMBR_PWWN:
                case FC_FZS_ZONEMBR_NWWN:
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fcwwn, tvb,
                                          offset+4, 8, ENC_NA);
                    break;
                case FC_FZS_ZONEMBR_DP:
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_uint,
                                                 tvb, offset+4, 3, ENC_BIG_ENDIAN);
                    break;
                case FC_FZS_ZONEMBR_FCID:
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fc, tvb,
                                          offset+4, 3, ENC_NA);
                    break;
                case FC_FZS_ZONEMBR_PWWN_LUN:
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fcwwn, tvb,
                                          offset+4, 8, ENC_NA);
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb,
                                        offset+8, 8, ENC_NA);
                    break;
                case FC_FZS_ZONEMBR_DP_LUN:
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_uint,
                                                 tvb, offset+4, 3, ENC_BIG_ENDIAN);
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb,
                                        offset+4, 8, ENC_NA);
                    break;
                case FC_FZS_ZONEMBR_FCID_LUN:
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_fc, tvb,
                                          offset+4, 3, ENC_NA);
                    proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb,
                                        offset+4, 8, ENC_NA);
                    break;
                default:
                    expert_add_info(pinfo, ti, &ei_fcfzs_mbrid);
                }
                offset += 12;
            }
        }
}
Example #30
0
static void
dissect_lltd_qos(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
{
    proto_item *header_item;
    proto_tree *header_tree, *func_tree, *func_subtree;
    guint8     func;
    guint16    seq_num, temp16;
    int loop_offset;

    func = tvb_get_guint8(tvb, offset);
    proto_tree_add_item(tree, hf_lltd_qos_diag_func, tvb, offset, 1, ENC_NA);
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(func, lltd_qos_diag_vals, "Unknown (0x%02x)"));
    offset++;

    header_tree = proto_tree_add_subtree(tree, tvb, offset, 14, ett_base_header, &header_item, "Base header");

    proto_tree_add_item(header_tree, hf_lltd_qos_real_dest_addr, tvb, offset, 6, ENC_NA);
    proto_tree_add_item(header_tree, hf_lltd_qos_real_src_addr, tvb, offset+6, 6, ENC_NA);
    proto_tree_add_item(header_tree, hf_lltd_qos_seq_num, tvb, offset+12, 2, ENC_BIG_ENDIAN);
    seq_num = tvb_get_ntohs(tvb, offset+12);

    switch(func)
    {
    case 0x00: /* QosInitializeSink */
        proto_tree_add_item(tree, hf_lltd_qos_initialize_interrupt_mod, tvb, offset+14, 1, ENC_BIG_ENDIAN);
        break;
    case 0x01: /* QosReady */
        proto_tree_add_item(tree, hf_lltd_qos_ready_sink_link_speed, tvb, offset+14, 4, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_ready_perf_count_freq, tvb, offset+18, 8, ENC_BIG_ENDIAN);
        break;
    case 0x02: /* QosProbe */
        proto_tree_add_item(tree, hf_lltd_qos_probe_controller_transmit_timestamp, tvb, offset+14, 8, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_probe_sink_receive_timestamp, tvb, offset+22, 8, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_probe_sink_transmit_timestamp, tvb, offset+30, 8, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_probe_test_type, tvb, offset+38, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_probe_packet_id, tvb, offset+39, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_probe_t, tvb, offset+40, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_probe_8021p_value, tvb, offset+40, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_probe_payload, tvb, offset+41, 5, ENC_NA);
        break;
    case 0x03: /* QosQuery */
    case 0x07: /* QosAck */
        if (seq_num == 0)
            expert_add_info(pinfo, header_item, &ei_lltd_qos_seq_num);
        /* No Data */
        break;
    case 0x04: /* QosQueryResp */
        proto_tree_add_item(tree, hf_lltd_qos_query_resp_r, tvb, offset+14, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_query_resp_e, tvb, offset+14, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_query_resp_num_events, tvb, offset+14, 2, ENC_BIG_ENDIAN);
        temp16 = tvb_get_ntohs(tvb, offset+14) & LLTD_QUERY_RESP_NUM_DESCS_MASK;
        if (temp16 > 0)
        {
            func_tree = proto_tree_add_subtree(tree, tvb, offset+16, temp16*18, ett_qos_event_descs, NULL, "QosEventDesc");
            for (loop_offset = 0; loop_offset < temp16*18; loop_offset += 18)
            {
                func_subtree = proto_tree_add_subtree(func_tree, tvb, offset+16+loop_offset, 18, ett_qos_event_item, NULL, "Qos Event");

                proto_tree_add_item(func_subtree, hf_lltd_qos_query_resp_controller_timestamp, tvb, offset+16+loop_offset, 8, ENC_BIG_ENDIAN);
                proto_tree_add_item(func_subtree, hf_lltd_qos_query_resp_sink_timestamp, tvb, offset+16+loop_offset+8, 8, ENC_BIG_ENDIAN);
                proto_tree_add_item(func_subtree, hf_lltd_qos_query_resp_packet_id, tvb, offset+16+loop_offset+16, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item(func_subtree, hf_lltd_qos_query_resp_reserved, tvb, offset+16+loop_offset+17, 1, ENC_BIG_ENDIAN);
            }
        }
        break;
    case 0x05: /* QosReset */
        /* No Data */
        break;
    case 0x06: /* QosError */
        proto_tree_add_item(tree, hf_lltd_qos_error_value, tvb, offset+14, 2, ENC_BIG_ENDIAN);
        break;
    case 0x08: /* QosCounterSnapshot */
        if (seq_num == 0)
            expert_add_info(pinfo, header_item, &ei_lltd_qos_seq_num);
        proto_tree_add_item(tree, hf_lltd_qos_count_snapshot_history, tvb, offset+14, 1, ENC_BIG_ENDIAN);
        break;
    case 0x09: /* QosCounterResult */
        proto_tree_add_item(tree, hf_lltd_qos_counter_result_subsec_span, tvb, offset+14, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_counter_result_byte_scale, tvb, offset+15, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_counter_result_packet_scale, tvb, offset+16, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_lltd_qos_counter_result_history_size, tvb, offset+17, 1, ENC_BIG_ENDIAN);
        temp16 = tvb_get_guint8(tvb, offset+17);
        if (temp16 > 0)
        {
            func_tree = proto_tree_add_subtree(tree, tvb, offset+18, temp16*4, ett_qos_snapshot_list, NULL, "Snapshot List");
            for (loop_offset = 0; loop_offset < temp16*4; loop_offset += 4)
            {
                func_subtree = proto_tree_add_subtree(func_tree, tvb, offset+18+loop_offset, 4, ett_qos_snapshot_item, NULL, "Snapshot");

                proto_tree_add_item(func_subtree, hf_lltd_qos_snapshot_bytes_recv, tvb, offset+16+loop_offset, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(func_subtree, hf_lltd_qos_snapshot_packets_recv, tvb, offset+16+loop_offset+2, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(func_subtree, hf_lltd_qos_snapshot_bytes_sent, tvb, offset+16+loop_offset+4, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(func_subtree, hf_lltd_qos_snapshot_packets_sent, tvb, offset+16+loop_offset+6, 2, ENC_BIG_ENDIAN);
            }
        }
        break;
    case 0x0A: /* QosCounterLease */
        /* No Data */
        break;
    default:
        expert_add_info_format(pinfo, header_item, &ei_lltd_qos_diag_func, "Invalid function 0x%02x", func);
        break;
    }
}