Esempio n. 1
0
/* Has storm request rate been exceeded with this request? */
static void check_for_storm_count(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  gboolean report_storm = FALSE;

  if (p_get_proto_data(pinfo->fd, proto_arp) != 0)
  {
    /* Read any previous stored packet setting */
    report_storm = (p_get_proto_data(pinfo->fd, proto_arp) == (void*)STORM);
  }
  else
  {
    /* Seeing packet for first time - check against preference settings */
    gint seconds_delta  = (gint) (pinfo->fd->abs_ts.secs - time_at_start_of_count.secs);
    gint nseconds_delta = pinfo->fd->abs_ts.nsecs - time_at_start_of_count.nsecs;
    gint gap = (seconds_delta*1000) + (nseconds_delta / 1000000);

    /* Reset if gap exceeds period or -ve gap (indicates we're rescanning from start) */
    if ((gap > (gint)global_arp_detect_request_storm_period) ||
        (gap < 0))
    {
      /* Time period elapsed without threshold being exceeded */
      arp_request_count = 1;
      time_at_start_of_count = pinfo->fd->abs_ts;
      p_add_proto_data(pinfo->fd, proto_arp, (void*)NO_STORM);
      return;
    }
    else
      if (arp_request_count > global_arp_detect_request_storm_packets)
      {
        /* Storm detected, record and reset start time. */
        report_storm = TRUE;
        p_add_proto_data(pinfo->fd, proto_arp, (void*)STORM);
        time_at_start_of_count = pinfo->fd->abs_ts;
      }
      else
      {
        /* Threshold not exceeded yet - no storm */
        p_add_proto_data(pinfo->fd, proto_arp, (void*)NO_STORM);
      }
  }

  if (report_storm)
  {
    /* Report storm and reset counter */
    proto_item *ti = proto_tree_add_none_format(tree, hf_arp_packet_storm, tvb, 0, 0,
                                                "Packet storm detected (%u packets in < %u ms)",
                                                global_arp_detect_request_storm_packets,
                                                global_arp_detect_request_storm_period);
    PROTO_ITEM_SET_GENERATED(ti);

    expert_add_info_format(pinfo, ti,
                           PI_SEQUENCE, PI_NOTE,
                           "ARP packet storm detected (%u packets in < %u ms)",
                           global_arp_detect_request_storm_packets,
                           global_arp_detect_request_storm_period);
    arp_request_count = 0;
  }
}
Esempio n. 2
0
/* split out some common FEC handling */
static guint dissect_feccode(proto_tree *tree, tvbuff_t *tvb, guint offset,
                             packet_info *pinfo, gint reserved)
{
    norm_packet_data_t *norm_data;
    guint8              encoding_id = tvb_get_guint8(tvb, offset);

    /* Save encoding ID */
    norm_data = wmem_new0(wmem_file_scope(), norm_packet_data_t);
    norm_data->encoding_id = encoding_id;

    p_add_proto_data(wmem_file_scope(), pinfo, proto_rmt_norm, 0, norm_data);

    proto_tree_add_item(tree, hf_fec_encoding_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1;
    if (reserved) {
        proto_tree_add_item(tree, hf_reserved, tvb, offset, 1, ENC_NA); offset += 1;
    }
    proto_tree_add_item(tree, hf_object_transport_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2;

    if (tvb_reported_length_remaining(tvb, offset) > 0) {
        fec_data_exchange_t  fec;
        tvbuff_t            *new_tvb;
        int                  len;

        new_tvb = tvb_new_subset_remaining(tvb, offset);

        fec.encoding_id = encoding_id;
        len = call_dissector_with_data(rmt_fec_handle, new_tvb, pinfo, tree, &fec);
        if (len > 0)
            offset += len;
    }

    return offset;
}
Esempio n. 3
0
/* code to dissect NORM info packets */
static void dissect_norm_info(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint8 hlen)
{
    proto_item         *ti;
    proto_tree         *flag_tree;
    norm_packet_data_t *norm_data;

    offset = dissect_grrtetc(tree, tvb, offset);

    ti = proto_tree_add_item(tree, hf_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
    flag_tree = proto_item_add_subtree(ti, ett_flags);
    proto_tree_add_item(flag_tree, hf_flag_repair,        tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_norm_explicit, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_info,          tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_unreliable,    tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_file,          tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_stream,        tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_msgstart,      tvb, offset, 1, ENC_BIG_ENDIAN);
    offset += 1;

    /* Save encoding ID */
    norm_data = wmem_new0(wmem_file_scope(), norm_packet_data_t);
    norm_data->encoding_id = tvb_get_guint8(tvb, offset);

    p_add_proto_data(wmem_file_scope(), pinfo, proto_rmt_norm, 0, norm_data);

    proto_tree_add_item(tree, hf_fec_encoding_id,     tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1;
    proto_tree_add_item(tree, hf_object_transport_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;

    if (offset < hdrlen2bytes(hlen)) {
        offset = dissect_norm_hdrext(tree, pinfo, tvb, offset, hlen);
    }
    if (tvb_reported_length_remaining(tvb, offset) > 0)
        proto_tree_add_item(tree, hf_payload, tvb, offset, -1, ENC_NA);
}
Esempio n. 4
0
static void dissect_gwtb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	gwtb_entry_t *data_ptr = dissect_gwtb_get_data(pinfo);
	gwtb_info_t *info_ptr = (gwtb_info_t*) p_get_proto_data(pinfo->fd, proto_gwtb, 0);

	if (!info_ptr) {
		info_ptr = (gwtb_info_t*) se_alloc(sizeof(gwtb_info_t));
		info_ptr->length = 0;
		info_ptr->auth = FALSE;
		info_ptr->data = NULL;
		p_add_proto_data(pinfo->fd, proto_gwtb, 0, info_ptr);
	}

	if (pinfo->match_port == pinfo->destport || TCP_PORT_GWTB == pinfo->destport) {
		if ((!data_ptr->request_rc4 || info_ptr->auth) && (!info_ptr->data)) {
			tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_REQUEST_LEN, get_gwtb_request_len, dissect_gwtb_request);
		} else if (!info_ptr->auth) {
			info_ptr->rc4 = data_ptr->request_rc4;
			tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN, get_gwtb_message_len, dissect_gwtb_message);
		}
	} else {
		if ((!data_ptr->response_rc4 || info_ptr->auth) && (!info_ptr->data)) {
			tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_RESPONSE_LEN, get_gwtb_response_len, dissect_gwtb_response);
		} else if (!info_ptr->auth) {
			info_ptr->rc4 = data_ptr->response_rc4;
			tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN, get_gwtb_message_len, dissect_gwtb_message);
		}
	}
}
Esempio n. 5
0
/* Look for conversation info and display any setup info found */
void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	/* Conversation and current data */
	conversation_t *p_conv = NULL;
	struct _msrp_conversation_info *p_conv_data = NULL;

	/* Use existing packet data if available */
	p_conv_data = p_get_proto_data(pinfo->fd, proto_msrp);

	if (!p_conv_data)
	{
		/* First time, get info from conversation */
		p_conv = find_conversation(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src,
		                           PT_TCP,
		                           pinfo->destport, pinfo->srcport, 0);

		if (p_conv)
		{
			/* Look for data in conversation */
			struct _msrp_conversation_info *p_conv_packet_data;
			p_conv_data = conversation_get_proto_data(p_conv, proto_msrp);

			if (p_conv_data)
			{
				/* Save this conversation info into packet info */
				p_conv_packet_data = se_alloc(sizeof(struct _msrp_conversation_info));
				memcpy(p_conv_packet_data, p_conv_data,
				       sizeof(struct _msrp_conversation_info));

				p_add_proto_data(pinfo->fd, proto_msrp, p_conv_packet_data);
			}
		}
	}

	/* Create setup info subtree with summary info. */
	if (p_conv_data && p_conv_data->setup_method_set)
	{
		proto_tree *msrp_setup_tree;
		proto_item *ti =  proto_tree_add_string_format(tree, hf_msrp_setup, tvb, 0, 0,
		                                               "",
		                                               "Stream setup by %s (frame %u)",
		                                               p_conv_data->setup_method,
		                                               p_conv_data->setup_frame_number);
		PROTO_ITEM_SET_GENERATED(ti);
		msrp_setup_tree = proto_item_add_subtree(ti, ett_msrp_setup);
		if (msrp_setup_tree)
		{
			/* Add details into subtree */
			proto_item* item = proto_tree_add_uint(msrp_setup_tree, hf_msrp_setup_frame,
			                                       tvb, 0, 0, p_conv_data->setup_frame_number);
			PROTO_ITEM_SET_GENERATED(item);
			item = proto_tree_add_string(msrp_setup_tree, hf_msrp_setup_method,
			                             tvb, 0, 0, p_conv_data->setup_method);
			PROTO_ITEM_SET_GENERATED(item);
		}
	}
}
/* Main dissection function. */
static void dissect_mac_lte_framed(tvbuff_t *tvb, packet_info *pinfo,
                                   proto_tree *tree)
{
    gint                 offset = 0;
    struct mac_lte_info  *p_mac_lte_info;
    tvbuff_t             *mac_tvb;
    gboolean             infoAlreadySet = FALSE;

    /* Need to find enabled mac-lte dissector */
    dissector_handle_t   mac_lte_handle = find_dissector("mac-lte");
    if (!mac_lte_handle) {
        return;
    }

    /* Do this again on re-dissection to re-discover offset of actual PDU */

    /* Needs to be at least as long as:
       - fixed header bytes
       - tag for data
       - at least one byte of MAC PDU payload */
    if ((size_t)tvb_length_remaining(tvb, offset) < (3+2)) {
        return;
    }

    /* If redissecting, use previous info struct (if available) */
    p_mac_lte_info = (struct mac_lte_info*)p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0);
    if (p_mac_lte_info == NULL) {
        /* Allocate new info struct for this frame */
        p_mac_lte_info = (struct mac_lte_info*)wmem_alloc0(wmem_file_scope(), sizeof(struct mac_lte_info));
        infoAlreadySet = FALSE;
    }
    else {
        infoAlreadySet = TRUE;
    }

    /* Dissect the fields to populate p_mac_lte */
    if (!dissect_mac_lte_context_fields(p_mac_lte_info, tvb, &offset)) {
        return;
    }

    /* Store info in packet (first time) */
    if (!infoAlreadySet) {
        p_add_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0, p_mac_lte_info);
    }

    /**************************************/
    /* OK, now dissect as MAC LTE         */

    /* Create tvb that starts at actual MAC PDU */
    mac_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector_only(mac_lte_handle, mac_tvb, pinfo, tree, NULL);
}
static guint16 assign_rb_info(tvbuff_t *tvb, packet_info *pinfo, guint16 offset, guint8 rbcnt, proto_tree *tree)
{
	guint8 i = 0, next_byte;
	guint8 rlc_mode, content, rb_id, ctmux, ciphered, deciphered;
	guint32 urnti;
	struct umts_mac_info *macinf;
	struct rlc_info *rlcinf;

	macinf = (umts_mac_info *)p_get_proto_data(pinfo->fd, proto_umts_mac, 0);
	rlcinf = (rlc_info *)p_get_proto_data(pinfo->fd, proto_rlc, 0);
	if (!macinf) {
		macinf = se_new0(struct umts_mac_info);
		p_add_proto_data(pinfo->fd, proto_umts_mac, 0, macinf);
	}
Esempio n. 8
0
/* main dissector function. wireshark calls it for segments in both
 * directions.
 */
static void
dissect_ajp13_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint16 mag;
  /* guint16 len; */
  conversation_t *conv = NULL;
  ajp13_conv_data *cd = NULL;
  proto_tree *ajp13_tree = NULL;
  ajp13_frame_data* fd = NULL;

  /* conversational state really only does us good during the first
   * in-order traversal
   */
  conv = find_or_create_conversation(pinfo);

  cd = (ajp13_conv_data*)conversation_get_proto_data(conv, proto_ajp13);
  if (!cd) {
    cd = se_new(ajp13_conv_data);
    cd->content_length = 0;
    cd->was_get_body_chunk = FALSE;
    conversation_add_proto_data(conv, proto_ajp13, cd);
  }

  /* we use the per segment user data to record the conversational
   * state for use later on when we're called out of order (see
   * comments at top of this file)
   */
  fd = (ajp13_frame_data*)p_get_proto_data(pinfo->fd, proto_ajp13);
  if (!fd) {
    /*printf("ajp13:dissect_ajp13_common():no frame data, adding");*/
    /* since there's no per-packet user data, this must be the first
     * time we've see the packet, and it must be the first "in order"
     * pass through the data.
     */
    fd = se_new(ajp13_frame_data);
    p_add_proto_data(pinfo->fd, proto_ajp13, fd);
    fd->is_request_body = FALSE;
    if (cd->content_length) {
      /* this is screwy, see AJPv13.html. the idea is that if the
       * request has a body (as determined by the content-length
       * header), then there's always an immediate follow-up PDU with
       * no GET_BODY_CHUNK from the container.
       */
      fd->is_request_body = TRUE;
    }
  }

  col_clear(pinfo->cinfo, COL_INFO);

  mag = tvb_get_ntohs(tvb, 0);
  /*  len = tvb_get_ntohs(tvb, 2); */

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

  if (mag == 0x1234 && !fd->is_request_body)
    col_append_fstr(pinfo->cinfo, COL_INFO, "%d:REQ:", conv->index);
  else if (mag == 0x1234 && fd->is_request_body)
    col_append_fstr(pinfo->cinfo, COL_INFO, "%d:REQ:Body", conv->index);
  else if (mag == 0x4142)
    col_append_fstr(pinfo->cinfo, COL_INFO, "%d:RSP:", conv->index);
  else
    col_set_str(pinfo->cinfo, COL_INFO, "AJP13 Error?");

  if (tree) {
    proto_item *ti;
    ti = proto_tree_add_item(tree, proto_ajp13, tvb, 0, -1, ENC_NA);
    ajp13_tree = proto_item_add_subtree(ti, ett_ajp13);
  }

  if (mag == 0x1234) {

    if (fd->is_request_body)
      display_req_body(tvb, ajp13_tree, cd);
    else
      display_req_forward(tvb, pinfo, ajp13_tree, cd);

  } else if (mag == 0x4142) {

    display_rsp(tvb, pinfo, ajp13_tree, cd);

  }
}
Esempio n. 9
0
static void
dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*spx_tree = NULL;
	proto_item	*ti;
	tvbuff_t	*next_tvb;
	guint8		conn_ctrl;
	proto_tree	*cc_tree;
	guint8		datastream_type;
	const char	*datastream_type_string;
	guint16         spx_seq;
	const char	*spx_msg_string;
	guint16		low_socket, high_socket;
	guint32		src;
	conversation_t	*conversation;
	spx_hash_value	*pkt_value;
	spx_rexmit_info	*spx_rexmit_info_p;
	spx_info	spx_infox;

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

	if (tree) {
		ti = proto_tree_add_item(tree, proto_spx, tvb, 0, SPX_HEADER_LEN, ENC_NA);
		spx_tree = proto_item_add_subtree(ti, ett_spx);
	}

	conn_ctrl = tvb_get_guint8(tvb, 0);
	spx_msg_string = spx_conn_ctrl(conn_ctrl);
	if (check_col(pinfo->cinfo, COL_INFO))
		col_append_fstr(pinfo->cinfo, COL_INFO, " %s", spx_msg_string);
	if (tree) {
		ti = proto_tree_add_uint_format(spx_tree, hf_spx_connection_control, tvb,
						0, 1, conn_ctrl,
						"Connection Control: %s (0x%02X)",
						spx_msg_string, conn_ctrl);
		cc_tree = proto_item_add_subtree(ti, ett_spx_connctrl);
		proto_tree_add_boolean(cc_tree, hf_spx_connection_control_sys, tvb,
				       0, 1, conn_ctrl);
		proto_tree_add_boolean(cc_tree, hf_spx_connection_control_send_ack, tvb,
				       0, 1, conn_ctrl);
		proto_tree_add_boolean(cc_tree, hf_spx_connection_control_attn, tvb,
				       0, 1, conn_ctrl);
		proto_tree_add_boolean(cc_tree, hf_spx_connection_control_eom, tvb,
				       0, 1, conn_ctrl);
	}

	datastream_type = tvb_get_guint8(tvb, 1);
	datastream_type_string = spx_datastream(datastream_type);
	if (datastream_type_string != NULL) {
		if (check_col(pinfo->cinfo, COL_INFO))
			col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
			    datastream_type_string);
	}
	if (tree) {
		if (datastream_type_string != NULL) {
			proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
						   1, 1, datastream_type,
						   "Datastream Type: %s (0x%02X)",
						   datastream_type_string,
						   datastream_type);
		} else {
			proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
						   1, 1, datastream_type,
						   "Datastream Type: 0x%02X",
						   datastream_type);
		}
		proto_tree_add_item(spx_tree, hf_spx_src_id, tvb,  2, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(spx_tree, hf_spx_dst_id, tvb,  4, 2, ENC_BIG_ENDIAN);
	}
	spx_seq = tvb_get_ntohs(tvb, 6);
	if (tree) {
		proto_tree_add_uint(spx_tree, hf_spx_seq_nr, tvb,  6, 2, spx_seq);
		proto_tree_add_item(spx_tree, hf_spx_ack_nr, tvb,  8, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(spx_tree, hf_spx_all_nr, tvb, 10, 2, ENC_BIG_ENDIAN);
	}

	/*
	 * SPX is Connection Oriented and Delivery Guaranteed.
	 * On the first pass, we need to flag retransmissions by the SPX
	 * protocol, so that subdissectors know whether a packet was
	 * retransmitted.
	 *
	 * We start out by creating a conversation for this direction of the
	 * IPX session; we use "pinfo->srcport" twice, so that we have
	 * separate conversations for the two directions.
	 *
	 * XXX - that might not work correctly if there's more than one
	 * SPX session using that source port; can that happen?  If so,
	 * we should probably use the direction, as well as the conversation,
	 * as part of the hash key; if we do that, we can probably just
	 * use PT_IPX as the port type, and possibly get rid of PT_NCP.
	 *
	 * According to
	 *
	 *	http://developer.novell.com/research/appnotes/1995/december/03/apv.htm
	 *
	 * the sequence number is not incremented for system packets, so
	 * presumably that means there is no notion of a system packet
	 * being retransmitted; that document also says that system
	 * packets are used as "I'm still here" keepalives and as
	 * acknowledgements (presumably meaning ACK-only packets), which
	 * suggests that they might not be ACKed and thus might not
	 * be retransmitted.
	 */
	if (conn_ctrl & SPX_SYS_PACKET) {
		/*
		 * It's a system packet, so it isn't a retransmission.
		 */
		spx_rexmit_info_p = NULL;
	} else {
		/*
		 * Not a system packet - check for retransmissions.
		 */
		if (!pinfo->fd->flags.visited) {
			conversation = find_conversation(pinfo->fd->num, &pinfo->src,
			    &pinfo->dst, PT_NCP, pinfo->srcport,
			    pinfo->srcport, 0);
			if (conversation == NULL) {
				/*
				 * It's not part of any conversation - create
				 * a new one.
				 */
				conversation = conversation_new(pinfo->fd->num, &pinfo->src,
				    &pinfo->dst, PT_NCP, pinfo->srcport,
				    pinfo->srcport, 0);
			}

			/*
			 * Now we'll hash the SPX header and use the result
			 * of that, plus the conversation, as a hash key to
			 * identify this packet.
			 *
			 * If we don't find it in the hash table, it's not a
			 * retransmission, otherwise it is.  If we don't find
			 * it, we enter it into the hash table, with the
			 * frame number.
			 * If we do, we attach to this frame a structure giving
			 * the frame number of the original transmission, so
			 * that we, and subdissectors, know it's a
			 * retransmission.
			 */
			src = tvb_get_ntohs(tvb, 0)+tvb_get_ntohs(tvb, 2)+tvb_get_ntohs(tvb, 4)+tvb_get_ntohs(tvb, 6)+tvb_get_ntohs(tvb, 8);
			pkt_value = spx_hash_lookup(conversation, src, spx_seq);
			if (pkt_value == NULL) {
				/*
				 * Not found in the hash table.
				 * Enter it into the hash table.
				 */
				pkt_value = spx_hash_insert(conversation, src,
				    spx_seq);
				pkt_value->spx_ack = tvb_get_ntohs(tvb, 8);
				pkt_value->spx_all = tvb_get_ntohs(tvb, 10);
				pkt_value->num = pinfo->fd->num;

				/*
				 * This is not a retransmission, so we shouldn't
				 * have any retransmission indicator.
				 */
				spx_rexmit_info_p = NULL;
			} else {
				/*
				 * Found in the hash table.  Mark this frame as
				 * a retransmission.
				 */
				spx_rexmit_info_p = se_alloc(sizeof(spx_rexmit_info));
				spx_rexmit_info_p->num = pkt_value->num;
				p_add_proto_data(pinfo->fd, proto_spx,
				    spx_rexmit_info_p);
			}
		} else {
			/*
			 * Do we have per-packet SPX data for this frame?
			 * If so, it's a retransmission, and the per-packet
			 * data indicates which frame had the original
			 * transmission.
			 */
			spx_rexmit_info_p = p_get_proto_data(pinfo->fd,
			    proto_spx);
		}
	}

	/*
	 * It's a retransmission if we have a retransmission indicator.
	 * Flag this as a retransmission, but don't pass it to the
	 * subdissector.
	 */
	if (spx_rexmit_info_p != NULL) {
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_fstr(pinfo->cinfo, COL_INFO,
			    "[Retransmission] Original Packet %u",
			    spx_rexmit_info_p->num);
		}
		if (tree) {
			proto_tree_add_uint_format(spx_tree, hf_spx_rexmt_frame,
			    tvb, 0, 0, spx_rexmit_info_p->num,
			    "This is a retransmission of frame %u",
			    spx_rexmit_info_p->num);
			if (tvb_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
				proto_tree_add_text(spx_tree, tvb,
				    SPX_HEADER_LEN, -1,
				    "Retransmitted data");
			}
		}
		return;
	}

	if (tvb_reported_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
		void* pd_save;
		/*
		 * Call subdissectors based on the IPX socket numbers; a
		 * subdissector might have registered with our IPX socket
		 * dissector table rather than the IPX dissector's socket
		 * dissector table.
		 *
		 * Assume the lower-numbered socket number is more likely
		 * to be the right one, along the lines of what we do for
		 * TCP and UDP.  We've seen NCP packets with a type of NCP,
		 * a source socket of IPX_SOCKET_NCP, and a destination
		 * socket of IPX_SOCKET_IPX_MESSAGE, and we've seen NCP
		 * packets with a type of NCP, a source socket of
		 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
		 * IPX_SOCKET_NCP.
		 */
		if (pinfo->srcport > pinfo->destport) {
			low_socket = pinfo->destport;
			high_socket = pinfo->srcport;
		} else {
			low_socket = pinfo->srcport;
			high_socket = pinfo->destport;
		}

		/*
		 * Pass information to subdissectors.
		 */
		spx_infox.eom = conn_ctrl & SPX_EOM;
		spx_infox.datastream_type = datastream_type;
		pd_save = pinfo->private_data;
		pinfo->private_data = &spx_infox;

		next_tvb = tvb_new_subset_remaining(tvb, SPX_HEADER_LEN);
		if (dissector_try_uint(spx_socket_dissector_table, low_socket,
		    next_tvb, pinfo, tree))
		{
			pinfo->private_data = pd_save;
			return;
		}
		if (dissector_try_uint(spx_socket_dissector_table, high_socket,
		    next_tvb, pinfo, tree))
		{
			pinfo->private_data = pd_save;
			return;
		}
		call_dissector(data_handle, next_tvb, pinfo, tree);
		pinfo->private_data = pd_save;
	}
}
Esempio n. 10
0
static void
dissect_smtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  struct smtp_proto_data    *spd_frame_data;
  proto_tree                *smtp_tree = NULL;
  proto_tree                *cmdresp_tree;
  proto_item                *ti, *hidden_item;
  int                       offset = 0;
  int                       request = 0;
  conversation_t            *conversation;
  struct smtp_session_state *session_state;
  const guchar              *line, *linep, *lineend;
  guint32                   code;
  int                       linelen = 0;
  gint                      length_remaining;
  gboolean                  eom_seen = FALSE;
  gint                      next_offset;
  gint                      loffset = 0;
  int                       cmdlen;
  fragment_data             *frag_msg = NULL;
  tvbuff_t                  *next_tvb;

  /* As there is no guarantee that we will only see frames in the
   * the SMTP conversation once, and that we will see them in
   * order - in Wireshark, the user could randomly click on frames
   * in the conversation in any order in which they choose - we
   * have to store information with each frame indicating whether
   * it contains commands or data or an EOM indication.
   *
   * XXX - what about frames that contain *both*?  TCP is a
   * byte-stream protocol, and there are no guarantees that
   * TCP segment boundaries will correspond to SMTP commands
   * or EOM indications.
   *
   * We only need that for the client->server stream; responses
   * are easy to manage.
   *
   * If we have per frame data, use that, else, we must be on the first
   * pass, so we figure it out on the first pass.
   */

  /*
   * Find or create the conversation for this.
   */
  conversation = find_or_create_conversation(pinfo);

  /*
   * Is there a request structure attached to this conversation?
   */
  session_state = conversation_get_proto_data(conversation, proto_smtp);
  if (!session_state) {
    /*
     * No - create one and attach it.
     */
    session_state = se_alloc(sizeof(struct smtp_session_state));
    session_state->smtp_state = SMTP_STATE_READING_CMDS;
    session_state->crlf_seen = FALSE;
    session_state->data_seen = FALSE;
    session_state->msg_read_len = 0;
    session_state->msg_tot_len = 0;
    session_state->msg_last = TRUE;
    session_state->last_nontls_frame = 0;

    conversation_add_proto_data(conversation, proto_smtp, session_state);
  }

  /* Are we doing TLS?
   * FIXME In my understanding of RFC 2487 client and server can send SMTP cmds
   * after a rejected TLS negotiation
   */
  if (session_state->last_nontls_frame != 0 && pinfo->fd->num > session_state->last_nontls_frame) {
    guint16 save_can_desegment;
    guint32 save_last_nontls_frame;

    /* This is TLS, not raw SMTP. TLS can desegment */
    save_can_desegment = pinfo->can_desegment;
    pinfo->can_desegment = pinfo->saved_can_desegment;

    /* Make sure the SSL dissector will not be called again after decryption */
    save_last_nontls_frame = session_state->last_nontls_frame;
    session_state->last_nontls_frame = 0;

    call_dissector(ssl_handle, tvb, pinfo, tree);

    pinfo->can_desegment = save_can_desegment;
    session_state->last_nontls_frame = save_last_nontls_frame;
    return;
  }

  /* Is this a request or a response? */
  request = pinfo->destport == pinfo->match_uint;

  /*
   * Is there any data attached to this frame?
   */
  spd_frame_data = p_get_proto_data(pinfo->fd, proto_smtp);

  if (!spd_frame_data) {

    /*
     * No frame data.
     */
    if(request) {

      /*
       * Create a frame data structure and attach it to the packet.
       */
      spd_frame_data = se_alloc0(sizeof(struct smtp_proto_data));

      spd_frame_data->conversation_id = conversation->index;
      spd_frame_data->more_frags = TRUE;

      p_add_proto_data(pinfo->fd, proto_smtp, spd_frame_data);

    }

    /*
     * Get the first line from the buffer.
     *
     * Note that "tvb_find_line_end()" will, if it doesn't return
     * -1, return a value that is not longer than what's in the buffer,
     * and "tvb_find_line_end()" will always return a value that is not
     * longer than what's in the buffer, so the "tvb_get_ptr()" call
     * won't throw an exception.
     */
    loffset = offset;
    while (tvb_offset_exists(tvb, loffset)) {
      linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset,
                                  smtp_desegment && pinfo->can_desegment);
      if (linelen == -1) {
        if (offset == loffset) {
          /*
           * We didn't find a line ending, and we're doing desegmentation;
           * tell the TCP dissector where the data for this message starts
           * in the data it handed us, and tell it we need more bytes
           */
          pinfo->desegment_offset = loffset;
          pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
          return;
        } else {
          linelen = tvb_length_remaining(tvb, loffset);
          next_offset = loffset + linelen;
        }
      }
      line = tvb_get_ptr(tvb, loffset, linelen);

      /*
       * Check whether or not this packet is an end of message packet
       * We should look for CRLF.CRLF and they may be split.
       * We have to keep in mind that we may see what we want on
       * two passes through here ...
       */
      if (session_state->smtp_state == SMTP_STATE_READING_DATA) {
        /*
         * The order of these is important ... We want to avoid
         * cases where there is a CRLF at the end of a packet and a
         * .CRLF at the begining of the same packet.
         */
        if ((session_state->crlf_seen && tvb_strneql(tvb, loffset, ".\r\n", 3) == 0) ||
            tvb_strneql(tvb, loffset, "\r\n.\r\n", 5) == 0)
          eom_seen = TRUE;

        length_remaining = tvb_length_remaining(tvb, loffset);
        if (length_remaining == tvb_reported_length_remaining(tvb, loffset) &&
            tvb_strneql(tvb, loffset + length_remaining - 2, "\r\n", 2) == 0)
          session_state->crlf_seen = TRUE;
        else
          session_state->crlf_seen = FALSE;
      }

      /*
       * OK, Check if we have seen a DATA request. We do it here for
       * simplicity, but we have to be careful below.
       */
      if (request) {
        if (session_state->smtp_state == SMTP_STATE_READING_DATA) {
          /*
           * This is message data.
           */
          if (eom_seen) { /* Seen the EOM */
            /*
             * EOM.
             * Everything that comes after it is commands.
             */
            spd_frame_data->pdu_type = SMTP_PDU_EOM;
            session_state->smtp_state = SMTP_STATE_READING_CMDS;
            break;
          } else {
            /*
             * Message data with no EOM.
             */
            spd_frame_data->pdu_type = SMTP_PDU_MESSAGE;

            if (session_state->msg_tot_len > 0) {
              /*
               * We are handling a BDAT message.
               * Check if we have reached end of the data chunk.
               */
              session_state->msg_read_len += tvb_length_remaining(tvb, loffset);

              if (session_state->msg_read_len == session_state->msg_tot_len) {
                /*
                 * We have reached end of BDAT data chunk.
                 * Everything that comes after this is commands.
                 */
                session_state->smtp_state = SMTP_STATE_READING_CMDS;

                if (session_state->msg_last) {
                  /*
                   * We have found the LAST data chunk.
                   * The message can now be reassembled.
                   */
                  spd_frame_data->more_frags = FALSE;
                }

                break; /* no need to go through the remaining lines */
              }
            }
          }
        } else {
          /*
           * This is commands - unless the capture started in the
           * middle of a session, and we're in the middle of data.
           *
           * Commands are not necessarily 4 characters; look
           * for a space or the end of the line to see where
           * the putative command ends.
           */
          linep = line;
          lineend = line + linelen;
          while (linep < lineend && *linep != ' ')
            linep++;
          cmdlen = (int)(linep - line);
          if (line_is_smtp_command(line, cmdlen)) {
            if (g_ascii_strncasecmp(line, "DATA", 4) == 0) {
              /*
               * DATA command.
               * This is a command, but everything that comes after it,
               * until an EOM, is data.
               */
              spd_frame_data->pdu_type = SMTP_PDU_CMD;
              session_state->smtp_state = SMTP_STATE_READING_DATA;
              session_state->data_seen = TRUE;
            } else if (g_ascii_strncasecmp(line, "BDAT", 4) == 0) {
              /*
               * BDAT command.
               * This is a command, but everything that comes after it,
               * until given length is received, is data.
               */
              guint32 msg_len;

              msg_len = strtoul (line+5, NULL, 10);

              spd_frame_data->pdu_type = SMTP_PDU_CMD;
              session_state->data_seen = TRUE;
              session_state->msg_tot_len += msg_len;

              if (msg_len == 0) {
                /* No data to read, next will be a command */
                session_state->smtp_state = SMTP_STATE_READING_CMDS;
              } else {
                session_state->smtp_state = SMTP_STATE_READING_DATA;
              }

              if (g_ascii_strncasecmp(line+linelen-4, "LAST", 4) == 0) {
                /*
                 * This is the last data chunk.
                 */
                session_state->msg_last = TRUE;

                if (msg_len == 0) {
                  /*
                   * No more data to expect.
                   * The message can now be reassembled.
                   */
                  spd_frame_data->more_frags = FALSE;
                }
              } else {
                session_state->msg_last = FALSE;
              }
            } else if (g_ascii_strncasecmp(line, "STARTTLS", 8) == 0) {
              /*
               * STARTTLS command.
               * This is a command, but if the response is 220,
               * everything after the response is TLS.
               */
              session_state->smtp_state = SMTP_STATE_AWAITING_STARTTLS_RESPONSE;
              spd_frame_data->pdu_type = SMTP_PDU_CMD;
            } else {
              /*
               * Regular command.
               */
              spd_frame_data->pdu_type = SMTP_PDU_CMD;
            }
          } else {
            /*
             * Assume it's message data.
             */
            spd_frame_data->pdu_type = session_state->data_seen ? SMTP_PDU_MESSAGE : SMTP_PDU_CMD;
          }
        }
      }

      /*
       * Step past this line.
       */
      loffset = next_offset;
    }
  }


  /*
   * From here, we simply add items to the tree and info to the info
   * fields ...
   */

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

  if (check_col(pinfo->cinfo, COL_INFO)) {  /* Add the appropriate type here */
    col_clear(pinfo->cinfo, COL_INFO);

    /*
     * If it is a request, we have to look things up, otherwise, just
     * display the right things
     */

    if (request) {
      /* We must have frame_data here ... */
      switch (spd_frame_data->pdu_type) {
      case SMTP_PDU_MESSAGE:

        length_remaining = tvb_length_remaining(tvb, offset);
        col_set_str(pinfo->cinfo, COL_INFO, smtp_data_desegment ? "C: DATA fragment" : "C: Message Body");
        col_append_fstr(pinfo->cinfo, COL_INFO, ", %d byte%s", length_remaining,
                        plurality (length_remaining, "", "s"));
        break;

      case SMTP_PDU_EOM:
        col_set_str(pinfo->cinfo, COL_INFO, "C: .");
        break;

      case SMTP_PDU_CMD:
        loffset = offset;
        while (tvb_offset_exists(tvb, loffset)) {
          /*
           * Find the end of the line.
           */
          linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);
          line = tvb_get_ptr(tvb, loffset, linelen);

          if(loffset == offset)
            col_append_fstr(pinfo->cinfo, COL_INFO, "C: %s",
                            format_text(line, linelen));
          else {
            col_append_fstr(pinfo->cinfo, COL_INFO, " | %s",
                            format_text(line, linelen));
          }

          loffset = next_offset;
        }
        break;
      }
    } else {
      loffset = offset;
      while (tvb_offset_exists(tvb, loffset)) {
        /*
         * Find the end of the line.
         */
        linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);
        line = tvb_get_ptr(tvb, loffset, linelen);

        if (loffset == offset)
          col_append_fstr(pinfo->cinfo, COL_INFO, "S: %s",
                          format_text(line, linelen));
        else {
          col_append_fstr(pinfo->cinfo, COL_INFO, " | %s",
                          format_text(line, linelen));
        }

        loffset = next_offset;
      }
    }
  }

  if (tree) { /* Build the tree info ... */
    ti = proto_tree_add_item(tree, proto_smtp, tvb, offset, -1, ENC_NA);
    smtp_tree = proto_item_add_subtree(ti, ett_smtp);
  }

  if (request) {
    /*
     * Check out whether or not we can see a command in there ...
     * What we are looking for is not data_seen and the word DATA
     * and not eom_seen.
     *
     * We will see DATA and session_state->data_seen when we process the
     * tree view after we have seen a DATA packet when processing
     * the packet list pane.
     *
     * On the first pass, we will not have any info on the packets
     * On second and subsequent passes, we will.
     */
    switch (spd_frame_data->pdu_type) {

    case SMTP_PDU_MESSAGE:
      if (smtp_data_desegment) {
        frag_msg = fragment_add_seq_next(tvb, 0, pinfo, spd_frame_data->conversation_id,
                                         smtp_data_segment_table, smtp_data_reassembled_table,
                                         tvb_length(tvb), spd_frame_data->more_frags);
      } else {
        /*
         * Message body.
         * Put its lines into the protocol tree, a line at a time.
         */
        dissect_smtp_data(tvb, offset, smtp_tree);
      }
      break;

    case SMTP_PDU_EOM:
      /*
       * End-of-message-body indicator.
       *
       * XXX - what about stuff after the first line?
       * Unlikely, as the client should wait for a response to the
       * DATA command this terminates before sending another
       * request, but we should probably handle it.
       */
      proto_tree_add_text(smtp_tree, tvb, offset, linelen, "C: .");

      if (smtp_data_desegment) {
        /* add final data segment */
        if (loffset)
          fragment_add_seq_next(tvb, 0, pinfo, spd_frame_data->conversation_id,
                                smtp_data_segment_table, smtp_data_reassembled_table,
                                loffset, spd_frame_data->more_frags);

        /* terminate the desegmentation */
        frag_msg = fragment_end_seq_next (pinfo, spd_frame_data->conversation_id, smtp_data_segment_table,
                                          smtp_data_reassembled_table);
      }
      break;

    case SMTP_PDU_CMD:
      /*
       * Command.
       *
       * XXX - what about stuff after the first line?
       * Unlikely, as the client should wait for a response to the
       * previous command before sending another request, but we
       * should probably handle it.
       */

      loffset = offset;
      while (tvb_offset_exists(tvb, loffset)) {
        /*
         * Find the end of the line.
         */
        linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);

        if (linelen >= 4)
          cmdlen = 4;
        else
          cmdlen = linelen;
        hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_req, tvb,
                                             0, 0, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);

        /*
         * Put the command line into the protocol tree.
         */
        ti =  proto_tree_add_item(smtp_tree, hf_smtp_command_line, tvb,
                          loffset, next_offset - loffset, ENC_ASCII|ENC_NA);
        cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);

        proto_tree_add_item(cmdresp_tree, hf_smtp_req_command, tvb,
                            loffset, cmdlen, ENC_ASCII|ENC_NA);
        if (linelen > 5) {
          proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb,
                              loffset + 5, linelen - 5, ENC_ASCII|ENC_NA);
        }

        if (smtp_data_desegment && !spd_frame_data->more_frags) {
          /* terminate the desegmentation */
          frag_msg = fragment_end_seq_next (pinfo, spd_frame_data->conversation_id, smtp_data_segment_table,
                                            smtp_data_reassembled_table);
        }

        /*
         * Step past this line.
         */
        loffset = next_offset;
      }
    }

    if (smtp_data_desegment) {
      next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled SMTP",
                                          frag_msg, &smtp_data_frag_items, NULL, smtp_tree);
      if (next_tvb) {
        /* XXX: this is presumptious - we may have negotiated something else */
        if (imf_handle) {
          call_dissector(imf_handle, next_tvb, pinfo, tree);
        } else {
          /*
           * Message body.
           * Put its lines into the protocol tree, a line at a time.
           */
          dissect_smtp_data(tvb, offset, smtp_tree);
        }

        pinfo->fragmented = FALSE;
      } else {
        pinfo->fragmented = TRUE;
      }
    }
  } else {
    /*
     * Process the response, a line at a time, until we hit a line
     * that doesn't have a continuation indication on it.
     */
    if (tree) {
      hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_rsp, tvb,
                                           0, 0, TRUE);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
    }

    while (tvb_offset_exists(tvb, offset)) {
      /*
       * Find the end of the line.
       */
      linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);

      if (tree) {
        /*
         * Put it into the protocol tree.
         */
        ti =  proto_tree_add_item(smtp_tree, hf_smtp_response, tvb,
                          offset, next_offset - offset, ENC_ASCII|ENC_NA);
        cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);
      } else
        cmdresp_tree = NULL;

      line = tvb_get_ptr(tvb, offset, linelen);
      if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1])
          && isdigit(line[2])) {
        /*
         * We have a 3-digit response code.
         */
        code = (line[0] - '0')*100 + (line[1] - '0')*10 + (line[2] - '0');

        /*
         * If we're awaiting the response to a STARTTLS code, this
         * is it - if it's 220, all subsequent traffic will
         * be TLS, otherwise we're back to boring old SMTP.
         */
        if (session_state->smtp_state == SMTP_STATE_AWAITING_STARTTLS_RESPONSE) {
          if (code == 220) {
            /* This is the last non-TLS frame. */
            session_state->last_nontls_frame = pinfo->fd->num;
          }
          session_state->smtp_state =  SMTP_STATE_READING_CMDS;
        }

        if (tree) {
          /*
           * Put the response code and parameters into the protocol tree.
           */
          proto_tree_add_uint(cmdresp_tree, hf_smtp_rsp_code, tvb, offset, 3,
                              code);

          if (linelen >= 4) {
            proto_tree_add_item(cmdresp_tree, hf_smtp_rsp_parameter, tvb,
                                offset + 4, linelen - 4, ENC_ASCII|ENC_NA);
          }
        }
      }

      /*
       * Step past this line.
       */
      offset = next_offset;

    }
  }
}
Esempio n. 11
0
static void
dissect_rtmpt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*rtmpt_tree = NULL;
	proto_tree	*rtmptroot_tree = NULL;
	proto_item	*ti = NULL;
	gint        offset = 0;

	struct tcpinfo* tcpinfo = pinfo->private_data;

	guint8  iCommand = -1;
	guint32 iLength = 1;
	guint16 iHeaderType = 4;
	guint16 iHeaderLength;
	guint8  iID;
	guint   rtmp_index;

	conversation_t * current_conversation;
	rtmpt_conversation_data_t * conversation_data;
	rtmpt_packet_data_t * packet_data;

	rtmpt_chunk_data_t *current_chunk_data = NULL;
	rtmpt_chunk_data_t *initial_chunk_data = NULL;

	tvbuff_t*   amf_tvb;

	current_conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);

	if (NULL != current_conversation)
	{
		conversation_data = (rtmpt_conversation_data_t*)conversation_get_proto_data(current_conversation, proto_rtmpt);
		if (NULL == conversation_data)
		{
			conversation_data = se_alloc(sizeof(rtmpt_conversation_data_t));
			memset((void*)conversation_data, 0, sizeof(rtmpt_conversation_data_t));
			conversation_add_proto_data(current_conversation, proto_rtmpt, conversation_data);
			conversation_data->current_chunks = g_hash_table_new(g_direct_hash, g_direct_equal);
			conversation_data->previous_frame_number = -1;
			conversation_data->current_chunk_size = RTMPT_DEFAULT_CHUNK_SIZE;
			conversation_data->is_rtmpe = 0;
		}

		packet_data = p_get_proto_data(pinfo->fd, proto_rtmpt);
		if (NULL == packet_data)
		{
			packet_data = se_alloc(sizeof(rtmpt_packet_data_t));
			memset((void*)packet_data, 0, sizeof(rtmpt_packet_data_t));
			p_add_proto_data(pinfo->fd, proto_rtmpt, packet_data);
			packet_data->initial_chunks = g_hash_table_new(g_direct_hash, g_direct_equal);
			packet_data->initial_chunk_size = conversation_data->current_chunk_size;
		}


		if (conversation_data->is_rtmpe == 1)
		{
			col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTMPE");
			return;
		}
		else
		{
			col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTMP");
		}

		if (conversation_data->previous_frame_number != (guint) pinfo->fd->num)
		{
			conversation_data->current_chunk_size = packet_data->initial_chunk_size;
		}

		col_set_writable(pinfo->cinfo, TRUE);
		col_clear(pinfo->cinfo, COL_INFO);

		conversation_data->previous_frame_number = pinfo->fd->num;
		if (tvb_length_remaining(tvb, offset) >= 1)
		{
			if (tcpinfo->lastackseq == RTMPT_HANDSHAKE_OFFSET_1 && tcpinfo->seq == RTMPT_HANDSHAKE_OFFSET_1)
			{
				iCommand =  RTMPT_TYPE_HANDSHAKE_1;
			}
			else if (tcpinfo->lastackseq == RTMPT_HANDSHAKE_OFFSET_2 && tcpinfo->seq == RTMPT_HANDSHAKE_OFFSET_1) iCommand =  RTMPT_TYPE_HANDSHAKE_2;
			else if (tcpinfo->seq == RTMPT_HANDSHAKE_OFFSET_2
			         && tvb_length(tvb) == RTMPT_HANDSHAKE_LENGTH_3) iCommand = RTMPT_TYPE_HANDSHAKE_3;
			else
			{
				iID = tvb_get_guint8(tvb, offset + 0);
				iHeaderType = iID >> 6;
				rtmp_index = iID & 0x3F;

				current_chunk_data = g_hash_table_lookup(conversation_data->current_chunks, GUINT_TO_POINTER(rtmp_index));
				initial_chunk_data = g_hash_table_lookup(packet_data->initial_chunks, GUINT_TO_POINTER(rtmp_index));

				if (iHeaderType <= 2) iLength = tvb_get_ntoh24(tvb, offset + 4);
				if (iHeaderType <= 1)
				{
					iCommand = tvb_get_guint8(tvb, offset + 7);
					if (NULL == current_chunk_data)
					{
						current_chunk_data = se_alloc(sizeof(rtmpt_chunk_data_t));
						memset((void*)current_chunk_data, 0, sizeof(rtmpt_chunk_data_t));
						g_hash_table_insert(conversation_data->current_chunks, GUINT_TO_POINTER(rtmp_index), current_chunk_data);
					}

					current_chunk_data->data_type = iCommand;
					current_chunk_data->last_length = iLength;
					current_chunk_data->frame_modified = pinfo->fd->num;
				}
				else
				{
					/* must get the command type from the previous entries in the hash table */
					/* try to use the current_chunk_data unless it is from a different frame */
					if (NULL != current_chunk_data && NULL != initial_chunk_data)
					{
						/* we have precedent data (we should)*/
						if (current_chunk_data->frame_modified != pinfo->fd->num)
						{
							iCommand = initial_chunk_data->data_type;
							iLength = initial_chunk_data->length_remaining;
							current_chunk_data->frame_modified = pinfo->fd->num;
							current_chunk_data->data_type = iCommand;
							current_chunk_data->last_length = iLength;
							current_chunk_data->dechunk_buffer = initial_chunk_data->dechunk_buffer;
						}
						else
						{
							iCommand = current_chunk_data->data_type;
							iLength = current_chunk_data->length_remaining;
						}

						if (iLength > conversation_data->current_chunk_size)
						{
							iLength = conversation_data->current_chunk_size;
						}
					}
				}
			}

			iHeaderLength = rtmpt_header_length_from_type(iHeaderType);


			if (check_col(pinfo->cinfo, COL_INFO))
			{
				col_append_sep_fstr(pinfo->cinfo, COL_INFO, " | ", "%s", val_to_str(iCommand, rtmpt_opcode_vals, "Unknown (0x%01x)"));
				col_set_fence(pinfo->cinfo, COL_INFO);
			}

			if (tree)
			{
				ti = proto_tree_add_item(tree, proto_rtmpt, tvb, offset, -1, FALSE);
				proto_item_append_text(ti, " (%s)", val_to_str(iCommand, rtmpt_opcode_vals, "Unknown (0x%01x)"));
				rtmptroot_tree = proto_item_add_subtree(ti, ett_rtmpt);

				ti = proto_tree_add_text(rtmptroot_tree, tvb, offset, iHeaderLength, RTMPT_TEXT_RTMP_HEADER);
				proto_item_append_text(ti, " (%s)", val_to_str(iCommand, rtmpt_opcode_vals, "Unknown (0x%01x)"));
				rtmpt_tree = proto_item_add_subtree(ti, ett_rtmpt_header);

				if (iHeaderType <= 3) proto_tree_add_item(rtmpt_tree, hf_rtmpt_header_objid, tvb, offset + 0, 1, FALSE);
				if (iHeaderType <= 2) proto_tree_add_item(rtmpt_tree, hf_rtmpt_header_timestamp, tvb, offset + 1, 3, FALSE);
				if (iHeaderType <= 1) proto_tree_add_item(rtmpt_tree, hf_rtmpt_header_body_size, tvb, offset + 4, 3, FALSE);
				if (iHeaderType <= 1) proto_tree_add_item(rtmpt_tree, hf_rtmpt_header_function, tvb, offset + 7, 1, FALSE);
				if (iHeaderType <= 0) proto_tree_add_item(rtmpt_tree, hf_rtmpt_header_source, tvb, offset + 8, 4, TRUE);

				if (iCommand == RTMPT_TYPE_HANDSHAKE_1)
				{
					proto_tree_add_item(rtmpt_tree, hf_rtmpt_handshake_data, tvb, 1, 1536, FALSE);
				}
				else if (iCommand == RTMPT_TYPE_HANDSHAKE_2)
				{
					proto_tree_add_item(rtmpt_tree, hf_rtmpt_handshake_data, tvb, 1, 1536, FALSE);
					proto_tree_add_item(rtmpt_tree, hf_rtmpt_handshake_data, tvb, 1537, 1536, FALSE);
				}
				else if (iCommand == RTMPT_TYPE_HANDSHAKE_3)
				{
					proto_tree_add_item(rtmpt_tree, hf_rtmpt_handshake_data, tvb, 0, -1, FALSE);
				}
				else if (iCommand == RTMPT_TYPE_CHUNK_SIZE)
				{
					conversation_data->current_chunk_size = tvb_get_ntohl (tvb, offset + iHeaderLength);
				}

				offset = iHeaderLength;
				if (tvb_length_remaining(tvb, offset))
				{
					ti = proto_tree_add_text(rtmptroot_tree, tvb, offset, -1, RTMPT_TEXT_RTMP_BODY);
				}


				if (iCommand == RTMPT_TYPE_INVOKE || iCommand == RTMPT_TYPE_NOTIFY)
				{
					guint iChunkSize = tvb_length_remaining(tvb, iHeaderLength);
					/* we have data which will be AMF */
					/* we should add it to a new tvb */
					if (NULL != current_chunk_data)
					{
						if (NULL == current_chunk_data->dechunk_buffer)
						{
							/* we have to create a new tvbuffer */
							current_chunk_data->dechunk_buffer = tvb_new_composite();
						}
						if (!(current_chunk_data->dechunk_buffer->initialized))
						{
							/* add the existing data to the new buffer */
							tvb_composite_append(current_chunk_data->dechunk_buffer,
							                     tvb_new_real_data(tvb_memdup(tvb, iHeaderLength, iChunkSize), iChunkSize, iChunkSize));

							if (current_chunk_data->length_remaining <= 0)
							{
								guint amf_length;
								guint8* amf_data;

								tvb_composite_finalize(current_chunk_data->dechunk_buffer);

								amf_length = tvb_length(current_chunk_data->dechunk_buffer);

								if (amf_length == 0)
								{
									return;
								}


								amf_data = tvb_memdup(current_chunk_data->dechunk_buffer, 0, amf_length);

								amf_tvb = tvb_new_real_data(amf_data, tvb_length_remaining(current_chunk_data->dechunk_buffer, 0), tvb_length_remaining(current_chunk_data->dechunk_buffer, 0));

								add_new_data_source(pinfo, amf_tvb, "Dechunked AMF data");
								ti = proto_tree_add_item(tree, proto_rtmpt, amf_tvb, 0, -1, FALSE);
								rtmpt_tree = proto_item_add_subtree(ti, ett_rtmpt_body);
								proto_tree_set_appendix(rtmpt_tree, amf_tvb, 0, tvb_length_remaining(amf_tvb, 0));
								proto_item_append_text(rtmpt_tree, " (%s)", "AMF Data");
								dissect_rtmpt_amf(amf_tvb, rtmpt_tree);
								current_chunk_data->dechunk_buffer = NULL;
							}
						}
					}
				}
			}
		}
	}
Esempio n. 12
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(wmem_file_scope(), pinfo, 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) && (encoding_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;
    }
}
Esempio n. 13
0
/*
 * Dissect a standard (reliable) ts2 packet, reassembling if required.
 */
static void ts2_standard_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ts2_tree, ts2_conversation *conversation_data)
{
    guint8 save_fragmented;
    tvbuff_t *new_tvb, *next_tvb;
    fragment_data *frag_msg ;
    guint16 fragment_number;
    ts2_frag *frag;
    gboolean outoforder;

    guint16 type = tvb_get_letohs(tvb, 2);
    /*guint16 class = tvb_get_letohs(tvb, 0);*/
    proto_tree_add_item(ts2_tree, hf_ts2_seqnum, tvb, 12, 4, TRUE);

    /* XXX: Following fragmentation stuff should be separate from the GUI stuff ??    */
    /* Get our stored fragmentation data or create one! */
    if ( ! ( frag = p_get_proto_data(pinfo->fd, proto_ts2) ) ) {
        frag = se_alloc(sizeof(ts2_frag));
        frag->frag_num=0;
    }

    /* decide if the packet is server to client or client to server
     * then check its fragmentation
     */
    if(!(pinfo->fd->flags.visited))
    {
        if(conversation_data->server_port == pinfo->srcport)
        {
            frag->fragmented = ts2_standard_find_fragments(tvb, &conversation_data->last_inorder_server_frame, &conversation_data->server_frag_size, &conversation_data->server_frag_num, &outoforder);
            frag->frag_num=conversation_data->server_frag_num;
            frag->frag_size=conversation_data->server_frag_size;
        }
        else
        {

            frag->fragmented = ts2_standard_find_fragments(tvb, &conversation_data->last_inorder_client_frame, &conversation_data->client_frag_size, &conversation_data->client_frag_num, &outoforder);
            frag->frag_num=conversation_data->client_frag_num;
            frag->frag_size=conversation_data->client_frag_size;
        }
        frag->outoforder=outoforder;
        p_add_proto_data(pinfo->fd, proto_ts2, frag);
    }

    /* Get our stored fragmentation data */
    frag = p_get_proto_data(pinfo->fd, proto_ts2);

    proto_tree_add_item(ts2_tree, hf_ts2_resend_count, tvb, 16, 2, TRUE);
    proto_tree_add_item(ts2_tree, hf_ts2_fragmentnumber, tvb, 18, 2, TRUE);
    ts2_add_checked_crc32(ts2_tree, hf_ts2_crc32, tvb, 20, tvb_get_letohl(tvb, 20));

    /* Reassemble the packet if its fragmented */
    new_tvb = NULL;
    if(frag->fragmented)
    {
        save_fragmented = pinfo->fragmented;
        frag_msg = NULL;
        pinfo->fragmented = TRUE;
        fragment_number = tvb_get_letohs(tvb, 18);
        frag_msg = fragment_add_seq_check(tvb, 24, pinfo, type,	msg_fragment_table, msg_reassembled_table, frag->frag_num, tvb_length_remaining(tvb, 24), fragment_number);
        new_tvb = process_reassembled_data(tvb, 24, pinfo,"Reassembled Message", frag_msg, &msg_frag_items, NULL, ts2_tree);
        if (frag_msg)
        {   /* Reassembled */
            if (check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled)");
        }
        else
        {   /* Not last packet of reassembled Short Message */
            if (check_col(pinfo->cinfo, COL_INFO))col_append_fstr(pinfo->cinfo, COL_INFO," (Message fragment %u)", frag->frag_num);
        }
        if (new_tvb)
            next_tvb = new_tvb;
        else
            next_tvb = tvb_new_subset_remaining(tvb, 24);
        pinfo->fragmented = save_fragmented;
    }
    else
        next_tvb = tvb_new_subset_remaining(tvb, 24);

    /* If we have a full packet now dissect it */
    if((new_tvb || !frag->fragmented) && !frag->outoforder)
    {
        switch(type)
        {
        case TS2T_LOGINPART2:
            ts2_parse_loginpart2(next_tvb, ts2_tree);
            break;
        case TS2T_CHANNELLIST:
            ts2_parse_channellist(next_tvb, ts2_tree);
            break;
        case TS2T_PLAYERLIST:
            ts2_parse_playerlist(next_tvb, ts2_tree);
            break;
        case TS2T_NEWPLAYERJOINED:
            ts2_parse_newplayerjoined(next_tvb, ts2_tree);
            break;
        case TS2T_KNOWNPLAYERUPDATE:
            ts2_parse_knownplayerupdate(next_tvb, ts2_tree);
            break;
        case TS2T_PLAYERLEFT:
            ts2_parse_playerleft(next_tvb, ts2_tree);
            break;
        case TS2T_PLAYERKICKED:
            ts2_parse_playerleft(next_tvb, ts2_tree);
            break;
        case TS2T_LOGINEND:
            ts2_parse_loginend(next_tvb, ts2_tree);
            break;
        case TS2T_CHANGESTATUS:
            ts2_parse_changestatus(next_tvb, ts2_tree);
            break;
        case TS2T_SWITCHCHANNEL:
            ts2_parse_switchchannel(next_tvb, ts2_tree);
            break;
        case TS2T_CHANNELCHANGE:
            ts2_parse_channelchange(next_tvb, ts2_tree);
            break;
        }
    }
    /* The packet is out of order, update the cinfo and ignore the packet */
    if(frag->outoforder)
        if (check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, " (Out Of Order, ignored)");
}
Esempio n. 14
0
/*
 * Dissect an SPDU.
 */
static int
dissect_spdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
    gboolean tokens, gboolean connectionless)
{
	gboolean has_user_information = FALSE;
	guint8 type;
	proto_item *ti = NULL;
	proto_tree *ses_tree = NULL;
	int len_len;
	guint16 parameters_len;
	tvbuff_t *next_tvb;
	void *save_private_data;
	guint32 *pres_ctx_id = NULL;
	struct SESSION_DATA_STRUCTURE session;

	/*
	 * Get SPDU type.
	 */
	type = tvb_get_guint8(tvb, offset);
	session.spdu_type = type;
	session.abort_type = SESSION_NO_ABORT;
	session.ros_op = 0;
	session.rtse_reassemble = FALSE;

	if(connectionless) {
	  	if (check_col(pinfo->cinfo, COL_INFO))
			col_add_str(pinfo->cinfo, COL_INFO,
			    val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
		if (tree) {
			ti = proto_tree_add_item(tree, proto_clses, tvb, offset,
				-1, FALSE);
			ses_tree = proto_item_add_subtree(ti, ett_ses);
			proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
				offset, 1, type);
		}
		has_user_information = TRUE;
	}
	else if (tokens) {
	  	if (check_col(pinfo->cinfo, COL_INFO))
			col_add_str(pinfo->cinfo, COL_INFO,
			    val_to_str(type, ses_category0_vals, "Unknown SPDU type (0x%02x)"));
		if (tree) {
			ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
			    -1, FALSE);
			ses_tree = proto_item_add_subtree(ti, ett_ses);
			proto_tree_add_uint(ses_tree, hf_ses_type_0, tvb,
			    offset, 1, type);
		}
	} else {
	  	if (check_col(pinfo->cinfo, COL_INFO))
			col_add_str(pinfo->cinfo, COL_INFO,
			    val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
		if (tree) {
			ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
				-1, FALSE);
			ses_tree = proto_item_add_subtree(ti, ett_ses);
			proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
				offset, 1, type);
		}

		/*
		 * Might this SPDU have a User Information field?
		 */
		switch (type) {
		case SES_DATA_TRANSFER:
		case SES_EXPEDITED:
		case SES_TYPED_DATA:
			has_user_information = TRUE;
			break;
		case SES_MAJOR_SYNC_POINT:
			pres_ctx_id = p_get_proto_data (pinfo->fd, proto_ses);
			if (ses_rtse_reassemble != 0 && !pres_ctx_id) {
				/* First time visited - save pres_ctx_id */
				pres_ctx_id = se_alloc (sizeof (guint32));
				*pres_ctx_id = ses_pres_ctx_id;
				p_add_proto_data (pinfo->fd, proto_ses, pres_ctx_id);
			}
			if (pres_ctx_id) {
				session.pres_ctx_id = *pres_ctx_id;
				session.rtse_reassemble = TRUE;
				has_user_information = TRUE;
			}
			ses_rtse_reassemble = FALSE;
			break;
		}
	}
	offset++;

	/* get length of SPDU parameter field */
	parameters_len = get_item_len(tvb, offset, &len_len);
	if (tree)
		proto_tree_add_uint(ses_tree, hf_ses_length, tvb, offset,
		    len_len, parameters_len);
	offset += len_len;

	/* Dissect parameters. */
	if (!dissect_parameters(tvb, offset, parameters_len, tree, ses_tree,
	    pinfo, &session))
		has_user_information = FALSE;
	offset += parameters_len;
	
	proto_item_set_end(ti, tvb, offset);

	/* Dissect user information, if present */
	if (has_user_information) {
		if (tvb_reported_length_remaining(tvb, offset) > 0 || type == SES_MAJOR_SYNC_POINT) {
			next_tvb = tvb_new_subset_remaining(tvb, offset);
			if(!pres_handle)
			{
				call_dissector(data_handle, next_tvb, pinfo,
					tree);
			}
			else
			{
				/*   save type of session pdu. We'll need it in the presentation dissector  */
				save_private_data = pinfo->private_data;
				pinfo->private_data = &session;
				call_dissector(pres_handle, next_tvb, pinfo,
					tree);
				pinfo->private_data = save_private_data;
			}

			/*
			 * No more SPDUs to dissect.  Set the offset to the
			 * end of the tvbuff.
			 */
			offset = tvb_length(tvb);
			if (session.rtse_reassemble && type == SES_DATA_TRANSFER) {
				ses_pres_ctx_id = session.pres_ctx_id;
				ses_rtse_reassemble = TRUE;
			}
		}
	}
	return offset;
}
Esempio n. 15
0
/*
 * Dissect an SPDU.
 */
static int
dissect_spdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
	     gboolean tokens, gboolean connectionless)
{
	gboolean has_user_information = FALSE;
	guint8 type;
	proto_item *ti = NULL;
	proto_tree *ses_tree = NULL;
	int len_len;
	guint16 parameters_len;
	tvbuff_t *next_tvb = NULL;
	guint32 *pres_ctx_id = NULL;
	guint8 enclosure_item_flags = BEGINNING_SPDU|END_SPDU;
	struct SESSION_DATA_STRUCTURE session;

	/*
	 * Get SPDU type.
	 */
	type = tvb_get_guint8(tvb, offset);
	session.spdu_type = type;
	session.abort_type = SESSION_NO_ABORT;
	session.pres_ctx_id = 0;
	session.ros_op = 0;
	session.rtse_reassemble = FALSE;

	if(connectionless) {
		col_add_str(pinfo->cinfo, COL_INFO,
			    val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
		if (tree) {
			ti = proto_tree_add_item(tree, proto_clses, tvb, offset,
				-1, ENC_NA);
			ses_tree = proto_item_add_subtree(ti, ett_ses);
			proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
				offset, 1, type);
		}
		has_user_information = TRUE;
	}
	else if (tokens) {
		col_add_str(pinfo->cinfo, COL_INFO,
			    val_to_str(type, ses_category0_vals, "Unknown SPDU type (0x%02x)"));
		if (tree) {
			ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
			    -1, ENC_NA);
			ses_tree = proto_item_add_subtree(ti, ett_ses);
			proto_tree_add_uint(ses_tree, hf_ses_type_0, tvb,
			    offset, 1, type);
		}
	} else {
		col_add_str(pinfo->cinfo, COL_INFO,
			    val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
		if (tree) {
			ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
				-1, ENC_NA);
			ses_tree = proto_item_add_subtree(ti, ett_ses);
			proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
				offset, 1, type);
		}

		/*
		 * Might this SPDU have a User Information field?
		 */
		switch (type) {
		case SES_DATA_TRANSFER:
		case SES_EXPEDITED:
		case SES_TYPED_DATA:
			has_user_information = TRUE;
			break;
		case SES_MAJOR_SYNC_POINT:
			pres_ctx_id = (guint32 *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ses, 0);
			if (ses_rtse_reassemble != 0 && !pres_ctx_id) {
				/* First time visited - save pres_ctx_id */
				pres_ctx_id = wmem_new(wmem_file_scope(), guint32);
				*pres_ctx_id = ses_pres_ctx_id;
				p_add_proto_data(wmem_file_scope(), pinfo, proto_ses, 0, pres_ctx_id);
			}
			if (pres_ctx_id) {
				session.pres_ctx_id = *pres_ctx_id;
				session.rtse_reassemble = TRUE;
				has_user_information = TRUE;
			}
			ses_rtse_reassemble = FALSE;
			break;
		}
	}
	offset++;

	/* get length of SPDU parameter field */
	parameters_len = get_item_len(tvb, offset, &len_len);
	if (tree)
		proto_tree_add_uint(ses_tree, hf_ses_length, tvb, offset,
		    len_len, parameters_len);
	offset += len_len;

	/* Dissect parameters. */
	if (!dissect_parameters(tvb, offset, parameters_len, tree, ses_tree,
				pinfo, &enclosure_item_flags, &session))
		has_user_information = FALSE;
	offset += parameters_len;

	proto_item_set_end(ti, tvb, offset);

	/* Dissect user information, if present */
	if (!ses_desegment || enclosure_item_flags == (BEGINNING_SPDU|END_SPDU)) {
		if (has_user_information) {
			/* Not desegment or only one segment */
			if (tvb_reported_length_remaining(tvb, offset) > 0 || type == SES_MAJOR_SYNC_POINT) {
				next_tvb = tvb_new_subset_remaining(tvb, offset);
			}
		}
	} else {
		conversation_t *conversation = NULL;
		fragment_head *frag_msg = NULL;
		gint fragment_len;
		guint32 ses_id = 0;

		/* Use conversation index as segment id */
		conversation  = find_conversation (pinfo->fd->num,
						   &pinfo->src, &pinfo->dst, pinfo->ptype,
						   pinfo->srcport, pinfo->destport, 0);
		if (conversation != NULL) {
			ses_id = conversation->index;
		}
		fragment_len = tvb_reported_length_remaining (tvb, offset);
		ti = proto_tree_add_item (ses_tree, hf_ses_segment_data, tvb, offset,
					  fragment_len, ENC_NA);
		proto_item_append_text (ti, " (%d byte%s)", fragment_len, plurality (fragment_len, "", "s"));
		frag_msg = fragment_add_seq_next (&ses_reassembly_table,
						  tvb, offset,
						  pinfo, ses_id, NULL,
						  fragment_len,
						  (enclosure_item_flags & END_SPDU) ? FALSE : TRUE);
		next_tvb = process_reassembled_data (tvb, offset, pinfo, "Reassembled SES",
						     frag_msg, &ses_frag_items, NULL,
						     (enclosure_item_flags & END_SPDU) ? tree : ses_tree);

		has_user_information = TRUE;
		offset += fragment_len;
	}

	if (has_user_information && next_tvb) {
		if (!pres_handle) {
			call_dissector(data_handle, next_tvb, pinfo, tree);
		} else {
			/* Pass the session pdu to the presentation dissector */
			call_dissector_with_data(pres_handle, next_tvb, pinfo, tree, &session);
		}

		/*
		 * No more SPDUs to dissect.  Set the offset to the
		 * end of the tvbuff.
		 */
		offset = tvb_captured_length(tvb);
		if (session.rtse_reassemble && type == SES_DATA_TRANSFER) {
			ses_pres_ctx_id = session.pres_ctx_id;
			ses_rtse_reassemble = TRUE;
		}
	}
	return offset;
}
Esempio n. 16
0
/*
void
ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype,
	  packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
	  int etype_id, int trailer_id, int fcs_len)
*/
static int
dissect_ethertype(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
	const char	  *description;
	tvbuff_t	  *volatile next_tvb;
	guint		   length_before;
	gint		   captured_length, reported_length;
	volatile int  dissector_found = 0;
	const char	  *volatile saved_proto;
	ethertype_data_t  *ethertype_data;

	/* Reject the packet if data is NULL */
	if (data == NULL)
		return 0;
	ethertype_data = (ethertype_data_t*)data;

	/* Add the Ethernet type to the protocol tree */
	proto_tree_add_uint(ethertype_data->fh_tree, ethertype_data->etype_id, tvb,
				    ethertype_data->offset_after_ethertype - 2, 2, ethertype_data->etype);

	/* Get the captured length and reported length of the data
	   after the Ethernet type. */
	captured_length = tvb_captured_length_remaining(tvb, ethertype_data->offset_after_ethertype);
	reported_length = tvb_reported_length_remaining(tvb,
							ethertype_data->offset_after_ethertype);

	/* Remember how much data there is after the Ethernet type,
	   including any trailer and FCS. */
	length_before = reported_length;

	/* Construct a tvbuff for the payload after the Ethernet type.
	   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.) */
	if (ethertype_data->fcs_len > 0) {
		if (captured_length >= 0 && reported_length >= 0) {
			if (reported_length >= ethertype_data->fcs_len)
				reported_length -= ethertype_data->fcs_len;
			if (captured_length > reported_length)
				captured_length = reported_length;
		}
	}
	next_tvb = tvb_new_subset(tvb, ethertype_data->offset_after_ethertype, captured_length,
				  reported_length);

	p_add_proto_data(pinfo->pool, pinfo, proto_ethertype, 0, GUINT_TO_POINTER((guint)ethertype_data->etype));

	/* Look for sub-dissector, and call it if found.
	   Catch 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;
	TRY {
		dissector_found = dissector_try_uint(ethertype_dissector_table,
						     ethertype_data->etype, 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. */
		show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);

		dissector_found = 1;
		pinfo->current_proto = saved_proto;
	}
	ENDTRY;

	if (!dissector_found) {
		/* No sub-dissector found.
		   Label rest of packet as "Data" */
		call_data_dissector(next_tvb, pinfo, tree);

		/* Label protocol */
		col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", ethertype_data->etype);

		description = try_val_to_str(ethertype_data->etype, etype_vals);
		if (description) {
			col_add_str(pinfo->cinfo, COL_INFO, description);
		}
	}

	add_dix_trailer(pinfo, tree, ethertype_data->fh_tree, ethertype_data->trailer_id, tvb, next_tvb, ethertype_data->offset_after_ethertype,
			length_before, ethertype_data->fcs_len);

	return tvb_captured_length(tvb);
}
Esempio n. 17
0
static void
dissect_pop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  struct pop_proto_data  *frame_data_p;
  gboolean               is_request;
  gboolean               is_continuation;
  proto_tree             *pop_tree, *reqresp_tree;
  proto_item             *ti;
  gint                   offset = 0;
  const guchar           *line;
  gint                   next_offset;
  int                    linelen;
  int                    tokenlen;
  const guchar           *next_token;
  fragment_data          *frag_msg = NULL;
  tvbuff_t               *next_tvb = NULL;
  conversation_t         *conversation = NULL;
  struct pop_data_val    *data_val = NULL;
  gint                   length_remaining;

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

  /*
   * Find the end of the first line.
   *
   * Note that "tvb_find_line_end()" will return a value that is
   * not longer than what's in the buffer, so the "tvb_get_ptr()"
   * call won't throw an exception.
   */
  linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
  line = tvb_get_ptr(tvb, offset, linelen);

  if (pinfo->match_port == pinfo->destport) {
    is_request = TRUE;
    is_continuation = FALSE;
  } else {
    is_request = FALSE;
    is_continuation = response_is_continuation(line);
  }

  frame_data_p = p_get_proto_data(pinfo->fd, proto_pop);

  if (!frame_data_p) {

    conversation = find_conversation(pinfo->fd->num, 
             &pinfo->src, &pinfo->dst, 
             pinfo->ptype,
             pinfo->srcport, pinfo->destport, 0);

    if (conversation == NULL) { /* No conversation, create one */
      conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
                                      pinfo->ptype, pinfo->srcport,
                                      pinfo->destport, 0);
    }

    data_val = conversation_get_proto_data(conversation, proto_pop);

    if (!data_val) {

      /*
       * No - create one and attach it.
       */
      data_val = se_alloc0(sizeof(struct pop_data_val));
      
      conversation_add_proto_data(conversation, proto_pop, data_val);
    }
  }

  if (check_col(pinfo->cinfo, COL_INFO)) {
    /*
     * Put the first line from the buffer into the summary
     * if it's a POP request or reply (but leave out the
     * line terminator).
     * Otherwise, just call it a continuation.
     */
    if (is_continuation) {
      length_remaining = tvb_length_remaining(tvb, offset);
      col_add_fstr(pinfo->cinfo, COL_INFO, "S: DATA fragment, %d byte%s", 
                   length_remaining, plurality (length_remaining, "", "s"));
    }
    else
      col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "C" : "S",
                   format_text(line, linelen));
  }

  ti = proto_tree_add_item(tree, proto_pop, tvb, offset, -1, FALSE);
  pop_tree = proto_item_add_subtree(ti, ett_pop);

  if (is_continuation) {

    if (pop_data_desegment) {

      if (!frame_data_p) {

        data_val->msg_read_len += tvb_length(tvb);

        frame_data_p = se_alloc(sizeof(struct pop_proto_data));

        frame_data_p->conversation_id = conversation->index;
        frame_data_p->more_frags = data_val->msg_read_len < data_val->msg_tot_len;

        p_add_proto_data(pinfo->fd, proto_pop, frame_data_p);  
      }

      frag_msg = fragment_add_seq_next(tvb, 0, pinfo, 
                                       frame_data_p->conversation_id, 
                                       pop_data_segment_table, 
                                       pop_data_reassembled_table, 
                                       tvb_length(tvb), 
                                       frame_data_p->more_frags);

      next_tvb = process_reassembled_data(tvb, offset, pinfo, 
                                          "Reassembled DATA",
                                          frag_msg, &pop_data_frag_items, 
                                          NULL, pop_tree);

      if (next_tvb) {

        if (imf_handle)
          call_dissector(imf_handle, next_tvb, pinfo, tree);

        if (data_val) {
          /* we have read everything - reset */
          
          data_val->msg_read_len = 0;
          data_val->msg_tot_len = 0; 
        }
        pinfo->fragmented = FALSE;
      } else {
        pinfo->fragmented = TRUE;
      }

    } else {

      /*
       * Put the whole packet into the tree as data.
       */
      call_dissector(data_handle,tvb, pinfo, pop_tree);
    
    }
    return;
  }

  /*
   * Put the line into the protocol tree.
   */
  ti = proto_tree_add_string_format(pop_tree,
                                    (is_request) ?
                                        hf_pop_request :
                                        hf_pop_response,
                                    tvb, offset,
                                    next_offset - offset,
                                    "", "%s",
                                    tvb_format_text(tvb, offset, next_offset - offset));
  reqresp_tree = proto_item_add_subtree(ti, ett_pop_reqresp);

  /*
   * Extract the first token, and, if there is a first
   * token, add it as the request or reply code.
   */
  tokenlen = get_token_len(line, line + linelen, &next_token);
  if (tokenlen != 0) {
    proto_tree_add_item(reqresp_tree,
                        (is_request) ?
                            hf_pop_request_command :
                            hf_pop_response_indicator,
                        tvb, offset, tokenlen, FALSE);

    if (data_val) {
      if (is_request) {
        /* see if this is RETR or TOP command */
        if (g_ascii_strncasecmp(line, "RETR", 4) == 0 ||
           g_ascii_strncasecmp(line, "TOP", 3) == 0)
          /* the next response will tell us how many bytes */
          data_val->msg_request = TRUE;
      } else {
        if (data_val->msg_request) {
          /* this is a response to a RETR or TOP command */

          if (g_ascii_strncasecmp(line, "+OK ", 4) == 0) {
            /* the message will be sent - work out how many bytes */
            data_val->msg_read_len = 0;
            data_val->msg_tot_len = atoi(line + 4);
          }
          data_val->msg_request = FALSE;
        }
      }
    }

    offset += (gint) (next_token - line);
    linelen -= (int) (next_token - line);
  }


  if (tree) { 
    /*
     * Add the rest of the first line as request or
     * reply param/description.
     */
    if (linelen != 0) {
      proto_tree_add_item(reqresp_tree,
                          (is_request) ?
                              hf_pop_request_parameter :
                              hf_pop_response_description,
                          tvb, offset, linelen, FALSE);
    }
    offset = next_offset;

    /*
     * Show the rest of the request or response as text,
     * a line at a time.
     */
    while (tvb_offset_exists(tvb, offset)) {
      /*
       * Find the end of the line.
       */
      tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);

      /*
       * Put this line.
       */
      proto_tree_add_string_format(pop_tree,
                                   (is_request) ?
                                       hf_pop_request_data :
                                       hf_pop_response_data,
                                   tvb, offset,
                                   next_offset - offset,
                                   "", "%s",
                                   tvb_format_text(tvb, offset, next_offset - offset));
      offset = next_offset;
    }
  } 
}
Esempio n. 18
0
static void
dissect_fcp_cmnd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, proto_tree *tree, conversation_t *conversation, fc_hdr *fchdr, fcp_conv_data_t *fcp_conv_data)
{
    int          offset  = 0;
    int          add_len = 0;
    guint8       flags, rwflags, lun0;
    guint16      lun     = 0xffff;
    tvbuff_t    *cdb_tvb;
    int          tvb_len, tvb_rlen;
    fcp_request_data_t *request_data = NULL;
    proto_item  *hidden_item;
    fcp_proto_data_t *proto_data;

    /* Determine the length of the FCP part of the packet */
    flags = tvb_get_guint8(tvb, offset+10);
    if (flags) {
        add_len = tvb_get_guint8(tvb, offset+11) & 0x7C;
        add_len = add_len >> 2;
    }

    hidden_item = proto_tree_add_uint(tree, hf_fcp_type, tvb, offset, 0, 0);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    lun0 = tvb_get_guint8(tvb, offset);

    /* Display single-level LUNs in decimal for clarity */
    /* I'm taking a shortcut here by assuming that if the first byte of the
     * LUN field is 0, it is a single-level LUN. This is not true. For a
     * real single-level LUN, all 8 bytes except byte 1 must be 0.
     */
    if (lun0) {
      proto_tree_add_item(tree, hf_fcp_multilun, tvb, offset, 8, ENC_NA);
      lun = tvb_get_guint8(tvb, offset) & 0x3f;
      lun <<= 8;
      lun |= tvb_get_guint8(tvb, offset+1);
    } else {
      proto_tree_add_item(tree, hf_fcp_singlelun, tvb, offset+1,
                          1, ENC_BIG_ENDIAN);
      lun = tvb_get_guint8(tvb, offset+1);
    }

    if (fchdr->itlq)
        fchdr->itlq->lun = lun;

    if (!pinfo->fd->flags.visited) {
        proto_data = wmem_new(wmem_file_scope(), fcp_proto_data_t);
        proto_data->lun = lun;
        p_add_proto_data(wmem_file_scope(), pinfo, proto_fcp, 0, proto_data);
    }

    request_data = (fcp_request_data_t*)wmem_tree_lookup32(fcp_conv_data->luns, lun);
    if (!request_data) {
        request_data = wmem_new(wmem_file_scope(), fcp_request_data_t);
        request_data->request_frame = pinfo->fd->num;
        request_data->response_frame = 0;
        request_data->request_time = pinfo->fd->abs_ts;
        request_data->itl = wmem_new(wmem_file_scope(), itl_nexus_t);
        request_data->itl->cmdset = 0xff;
        request_data->itl->conversation = conversation;
        wmem_tree_insert32(fcp_conv_data->luns, lun, request_data);
    }

    proto_tree_add_item(tree, hf_fcp_crn, tvb, offset+8, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_fcp_taskattr, tvb, offset+9, 1, ENC_BIG_ENDIAN);
    dissect_task_mgmt_flags(pinfo, tree, tvb, offset+10);
    proto_tree_add_item(tree, hf_fcp_addlcdblen, tvb, offset+11, 1, ENC_BIG_ENDIAN);
    rwflags = tvb_get_guint8(tvb, offset+11);
    if (fchdr->itlq) {
        if (rwflags & 0x02) {
            fchdr->itlq->task_flags |= SCSI_DATA_READ;
        }
        if (rwflags & 0x01) {
            fchdr->itlq->task_flags |= SCSI_DATA_WRITE;
        }
    }
    proto_tree_add_item(tree, hf_fcp_rddata, tvb, offset+11, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_fcp_wrdata, tvb, offset+11, 1, ENC_BIG_ENDIAN);

    tvb_len = tvb_length_remaining(tvb, offset+12);
    if (tvb_len > (16 + add_len))
      tvb_len = 16 + add_len;
    tvb_rlen = tvb_reported_length_remaining(tvb, offset+12);
    if (tvb_rlen > (16 + add_len))
      tvb_rlen = 16 + add_len;
    cdb_tvb = tvb_new_subset(tvb, offset+12, tvb_len, tvb_rlen);
    dissect_scsi_cdb(cdb_tvb, pinfo, parent_tree, SCSI_DEV_UNKNOWN, fchdr->itlq, request_data->itl);

    proto_tree_add_item(tree, hf_fcp_dl, tvb, offset+12+16+add_len,
                        4, ENC_BIG_ENDIAN);
    if (fchdr->itlq) {
        fchdr->itlq->data_length = tvb_get_ntohl(tvb, offset+12+16+add_len);
    }

    if ( ((rwflags & 0x03) == 0x03)
    &&  tvb_length_remaining(tvb, offset+12+16+add_len+4) >= 4) {
        proto_tree_add_item(tree, hf_fcp_bidir_dl, tvb, offset+12+16+add_len+4,
                            4, ENC_BIG_ENDIAN);
        if (fchdr->itlq) {
            fchdr->itlq->bidir_data_length = tvb_get_ntohl(tvb, offset+12+16+add_len+4);
        }

    }

}
Esempio n. 19
0
void
decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
                 proto_tree *tree, int uh_sport, int uh_dport, int uh_ulen)
{
  tvbuff_t *next_tvb;
  int low_port, high_port;
  gint len, reported_len;
  udp_p_info_t *udp_p_info = NULL;
  /* Save curr_layer_num as it might be changed by subdissector */
  guint8 curr_layer_num = pinfo->curr_layer_num;
  heur_dtbl_entry_t *hdtbl_entry;

  len = tvb_captured_length_remaining(tvb, offset);
  reported_len = tvb_reported_length_remaining(tvb, offset);
  if (uh_ulen != -1) {
    /* This is the length from the UDP header; the payload should be cut
       off at that length.  (If our caller passed a value here, they
       are assumed to have checked that it's >= 8, and hence >= offset.)

       XXX - what if it's *greater* than the reported length? */
    if ((uh_ulen - offset) < reported_len)
      reported_len = uh_ulen - offset;
    if (len > reported_len)
      len = reported_len;
  }

  next_tvb = tvb_new_subset(tvb, offset, len, reported_len);

  /* If the user has a "Follow UDP Stream" window loading, pass a pointer
   * to the payload tvb through the tap system. */
  if (have_tap_listener(udp_follow_tap))
    tap_queue_packet(udp_follow_tap, pinfo, next_tvb);

  if (pinfo->fd->flags.visited) {
    udp_p_info = (udp_p_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, pinfo->curr_layer_num);
    if (udp_p_info) {
      call_heur_dissector_direct(udp_p_info->heur_dtbl_entry, next_tvb, pinfo, tree, NULL);
      return;
    }
  }

  /* determine if this packet is part of a conversation and call dissector */
/* for the conversation if available */

  if (try_conversation_dissector(&pinfo->dst, &pinfo->src, PT_UDP,
                                 uh_dport, uh_sport, next_tvb, pinfo, tree, NULL)) {
    return;
  }

  if (try_heuristic_first) {
    /* Do lookup with the heuristic subdissector table */
    if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
      if (!udp_p_info) {
        udp_p_info = wmem_new0(wmem_file_scope(), udp_p_info_t);
        udp_p_info->heur_dtbl_entry = hdtbl_entry;
        p_add_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, curr_layer_num, udp_p_info);
      }
      return;
    }
  }

  /* Do lookups with the subdissector table.
     We try the port number with the lower value first, followed by the
     port number with the higher value.  This means that, for packets
     where a dissector is registered for *both* port numbers:

        1) we pick the same dissector for traffic going in both directions;

        2) we prefer the port number that's more likely to be the right
           one (as that prefers well-known ports to reserved ports);

     although there is, of course, no guarantee that any such strategy
     will always pick the right port number.

     XXX - we ignore port numbers of 0, as some dissectors use a port
     number of 0 to disable the port, and as RFC 768 says that the source
     port in UDP datagrams is optional and is 0 if not used. */
  if (uh_sport > uh_dport) {
    low_port  = uh_dport;
    high_port = uh_sport;
  } else {
    low_port  = uh_sport;
    high_port = uh_dport;
  }
  if ((low_port != 0) &&
      dissector_try_uint(udp_dissector_table, low_port, next_tvb, pinfo, tree))
    return;
  if ((high_port != 0) &&
      dissector_try_uint(udp_dissector_table, high_port, next_tvb, pinfo, tree))
    return;

  if (!try_heuristic_first) {
    /* Do lookup with the heuristic subdissector table */
    if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
      if (!udp_p_info) {
        udp_p_info = wmem_new0(wmem_file_scope(), udp_p_info_t);
        udp_p_info->heur_dtbl_entry = hdtbl_entry;
        p_add_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, curr_layer_num, udp_p_info);
      }
      return;
    }
  }

  call_dissector(data_handle,next_tvb, pinfo, tree);
}
Esempio n. 20
0
static void
dissect_beep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  int offset;
  struct beep_proto_data  *beep_frame_data;
  proto_tree              *beep_tree = NULL, *ti = NULL;
  conversation_t          *conversation = NULL;
  struct beep_request_key request_key, *new_request_key;
  struct beep_request_val *request_val = NULL;

  offset = 0;

  /* If we have per frame data, use that, else, we must have lost the per-
   * frame data, and we have to do a full dissect pass again.
   *
   * The per-frame data tells us how much of this frame is left over from a
   * previous frame, so we dissect it as payload and then try to dissect the
   * rest.
   *
   * We use the conversation to build up info on the first pass over the
   * packets of type BEEP, and record anything that is needed if the user
   * does random dissects of packets in per packet data.
   *
   * Once we have per-packet data, we don't need the conversation stuff
   * anymore, but if per-packet data and conversation stuff gets deleted, as
   * it does under some circumstances when a rescan is done, it all gets
   * rebuilt.
   */

  /* Find out what conversation this packet is part of ... but only
   * if we have no information on this packet, so find the per-frame
   * info first.
   */

  beep_frame_data = (struct beep_proto_data *)p_get_proto_data(pinfo->fd, proto_beep);

  if (!beep_frame_data) {

      conversation = find_or_create_conversation(pinfo);

      /*
       * Check for and insert an entry in the request table if does not exist
       */
      request_key.conversation = conversation->index;

      request_val = (struct beep_request_val *)g_hash_table_lookup(beep_request_hash, &request_key);

      if (!request_val) { /* Create one */

        new_request_key = (struct beep_request_key *)se_alloc(sizeof(struct beep_request_key));
        new_request_key->conversation = conversation->index;

        request_val = (struct beep_request_val *)se_alloc(sizeof(struct beep_request_val));
        request_val->processed = 0;
        request_val->size = 0;

        g_hash_table_insert(beep_request_hash, new_request_key, request_val);

      }
    }

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


  /* "tvb_format_text()" is passed a value that won't go past the end
   * of the packet, so it won't throw an exception.
   */
  if (tvb_length_remaining(tvb, offset) > 0)
    col_add_str(pinfo->cinfo, COL_INFO, tvb_format_text(tvb, offset, tvb_length_remaining(tvb, offset)));

  /* Here, we parse the message so we can retrieve the info we need, which
   * is that there is some payload left from a previous segment on the
   * front of this segment ... This all depends on TCP segments not getting
   * out of order ...
   *
   * As a huge kludge, we push the checking for the tree down into the code
   * and process as if we were given a tree but not call the routines that
   * adorn the protocol tree if they were NULL.
   */

  if (tree) {  /* Build the tree info ... */

    ti = proto_tree_add_item(tree, proto_beep, tvb, offset, -1, ENC_NA);

    beep_tree = proto_item_add_subtree(ti, ett_beep);

  }

  /* Check the per-frame data and the conversation for any left-over
   * payload from the previous frame
   *
   * We check that per-frame data exists first, and if so, use it,
   * else we use the conversation data.
   *
   * We create per-frame data here as well, but we must ensure we create it
   * after we have done the check for per-frame or conversation data.
   *
   * We also depend on the first frame in a group having a pl_size of 0.
   */

  if (beep_frame_data != NULL && beep_frame_data->pl_left > 0) {

    int pl_left = beep_frame_data->pl_left;

    pl_left = MIN(pl_left, MAX(0, tvb_length_remaining(tvb, offset)));

    /* Add the payload bit, only if we have a tree */
    if (tree && (pl_left > 0)) {
      proto_tree_add_item(tree, hf_beep_payload, tvb, offset, pl_left, ENC_NA|ENC_ASCII);
    }
    offset += pl_left;
  }
  else if (request_val && request_val->size > 0) {

    int pl_left = request_val->size;

    request_val->size = 0;

    /* We create the frame data here for this case, and
     * elsewhere for other frames
     */

    beep_frame_data = se_new(struct beep_proto_data);

    beep_frame_data->pl_left = pl_left;
    beep_frame_data->pl_size = 0;
    beep_frame_data->mime_hdr = 0;

    p_add_proto_data(pinfo->fd, proto_beep, beep_frame_data);

  }
static int
dissect_gssapi_work(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
		    gboolean is_verifier)
{
	proto_item *volatile item;
	proto_tree *volatile subtree;
	volatile int return_offset = 0;
	gssapi_conv_info_t *volatile gss_info;
	gssapi_oid_value *oidvalue;
	dissector_handle_t handle;
	conversation_t *conversation;
	tvbuff_t *oid_tvb;
	int len, start_offset, oid_start_offset;
	volatile int offset;
	gint8 appclass;
	gboolean pc, ind_field;
	gint32 tag;
	guint32 len1;
	const char *oid;
	fragment_data *fd_head=NULL;
	gssapi_frag_info_t *fi;
	tvbuff_t *volatile gss_tvb=NULL;
	asn1_ctx_t asn1_ctx;
	void *pd_save;

	start_offset=0;
	offset=0;
	asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
	/*
	 * We don't know whether the data is encrypted, so say it's
	 * not, for now.  The subdissector must set gssapi_data_encrypted
	 * if it is.
	 */
	pinfo->gssapi_data_encrypted = FALSE;


	/*
	 * We need a conversation for later
	 */
	conversation = find_or_create_conversation(pinfo);

	gss_info = (gssapi_conv_info_t *)conversation_get_proto_data(conversation, proto_gssapi);
	if (!gss_info) {
		gss_info = se_new(gssapi_conv_info_t);
		gss_info->oid=NULL;
		gss_info->do_reassembly=FALSE;
		gss_info->frags=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "gssapi_frags");

		conversation_add_proto_data(conversation, proto_gssapi, gss_info);
	}

	item = proto_tree_add_item(
		tree, proto_gssapi, tvb, offset, -1, ENC_NA);

	subtree = proto_item_add_subtree(item, ett_gssapi);

	/*
	 * Catch the ReportedBoundsError exception; the stuff we've been
	 * handed doesn't necessarily run to the end of the packet, it's
	 * an item inside a packet, so if it happens to be malformed (or
	 * we, or a dissector we call, has a bug), so that an exception
	 * is thrown, we want to report the error, but return and let
	 * our caller dissect the rest of the packet.
	 *
	 * If it gets a BoundsError, we can stop, as there's nothing more
	 * in the packet after our blob to see, so we just re-throw the
	 * exception.
	 */
	pd_save = pinfo->private_data;
	TRY {
		gss_tvb=tvb;


		/* First of all, if it's the first time we see this packet
		 * then check whether we are in the middle of reassembly or not
		 */
		if( (!pinfo->fd->flags.visited)
		&&  (gss_info->do_reassembly)
		&&  (gssapi_reassembly) ){
			fi=(gssapi_frag_info_t *)se_tree_lookup32(gss_info->frags, gss_info->first_frame);
			if(!fi){
				goto done;
			}
			se_tree_insert32(gss_info->frags, pinfo->fd->num, fi);
			fd_head=fragment_add(&gssapi_reassembly_table,
				tvb, 0, pinfo, fi->first_frame, NULL,
				gss_info->frag_offset,
				tvb_length(tvb), TRUE);
			gss_info->frag_offset+=tvb_length(tvb);

			/* we need more fragments */
			if(!fd_head){
				goto done;
			}

			/* this blob is now fully reassembled */
			gss_info->do_reassembly=FALSE;
			fi->reassembled_in=pinfo->fd->num;

			gss_tvb=tvb_new_child_real_data(tvb, fd_head->data, fd_head->datalen, fd_head->datalen);
			add_new_data_source(pinfo, gss_tvb, "Reassembled GSSAPI");
		}
		/* We have seen this packet before.
		 * Is this blob part of reassembly or a normal blob ?
		 */
		if( (pinfo->fd->flags.visited)
		&&  (gssapi_reassembly) ){
			fi=(gssapi_frag_info_t *)se_tree_lookup32(gss_info->frags, pinfo->fd->num);
			if(fi){
				fd_head=fragment_get(&gssapi_reassembly_table,
					pinfo, fi->first_frame, NULL);
				if(fd_head && (fd_head->flags&FD_DEFRAGMENTED)){
					if(pinfo->fd->num==fi->reassembled_in){
					        proto_item *frag_tree_item;
						gss_tvb=tvb_new_child_real_data(tvb, fd_head->data, fd_head->datalen, fd_head->datalen);
						add_new_data_source(pinfo, gss_tvb, "Reassembled GSSAPI");
						show_fragment_tree(fd_head, &gssapi_frag_items, tree, pinfo, tvb, &frag_tree_item);
					} else {
						proto_item *it;
						it=proto_tree_add_uint(tree, hf_gssapi_reassembled_in, tvb, 0, 0, fi->reassembled_in);
					        PROTO_ITEM_SET_GENERATED(it);
						goto done;
					}
				}
			}
		}

		/* Read header */
		offset = get_ber_identifier(gss_tvb, offset, &appclass, &pc, &tag);
		offset = get_ber_length(gss_tvb, offset, &len1, &ind_field);


		if (!(appclass == BER_CLASS_APP && pc && tag == 0)) {
		  /* It could be NTLMSSP, with no OID.  This can happen
		     for anything that microsoft calls 'Negotiate' or GSS-SPNEGO */
			if ((tvb_length_remaining(gss_tvb, start_offset)>7) && (tvb_strneql(gss_tvb, start_offset, "NTLMSSP", 7) == 0)) {
				return_offset = call_dissector(ntlmssp_handle,
							tvb_new_subset_remaining(gss_tvb, start_offset),
							pinfo, subtree);
				goto done;
			}
			/* Maybe it's new NTLMSSP payload */
			if ((tvb_length_remaining(gss_tvb, start_offset)>16) &&
			   ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) {
				return_offset = call_dissector(ntlmssp_payload_handle,
							tvb_new_subset_remaining(gss_tvb, start_offset),
							pinfo, subtree);
				pinfo->gssapi_data_encrypted = TRUE;
				goto done;
			}
			if ((tvb_length_remaining(gss_tvb, start_offset)==16) &&
			   ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) {
				if( is_verifier ) {
					return_offset = call_dissector(ntlmssp_verf_handle,
									tvb_new_subset_remaining(gss_tvb, start_offset),
									pinfo, subtree);
				}
				else if( pinfo->gssapi_encrypted_tvb ) {
					return_offset = call_dissector(ntlmssp_data_only_handle,
									tvb_new_subset_remaining(pinfo->gssapi_encrypted_tvb, 0),
									pinfo, subtree);
					pinfo->gssapi_data_encrypted = TRUE;
				}
		   		goto done;
		  	}

		  /* Maybe it's new GSSKRB5 CFX Wrapping */
		  if ((tvb_length_remaining(gss_tvb, start_offset)>2) &&
		      ((tvb_memeql(gss_tvb, start_offset, "\04\x04", 2) == 0) ||
		       (tvb_memeql(gss_tvb, start_offset, "\05\x04", 2) == 0))) {
		    return_offset = call_dissector(spnego_krb5_wrap_handle,
						   tvb_new_subset_remaining(gss_tvb, start_offset),
						   pinfo, subtree);
		    goto done;
		  }

		  /*
		   * If we do not recognise an Application class,
		   * then we are probably dealing with an inner context
		   * token or a wrap token, and we should retrieve the
		   * gssapi_oid_value pointer from the per-frame data or,
		   * if there is no per-frame data (as would be the case
		   * the first time we dissect this frame), from the
		   * conversation that exists or that we created from
		   * pinfo (and then make it per-frame data).
		   * We need to make it per-frame data as there can be
		   * more than one GSS-API negotiation in a conversation.
		   *
		   * Note! We "cheat". Since we only need the pointer,
		   * we store that as the data.  (That's not really
		   * "cheating" - the per-frame data and per-conversation
		   * data code doesn't care what you supply as a data
		   * pointer; it just treats it as an opaque pointer, it
		   * doesn't dereference it or free what it points to.)
		   */
		  oidvalue = (gssapi_oid_value *)p_get_proto_data(pinfo->fd, proto_gssapi, 0);
		  if (!oidvalue && !pinfo->fd->flags.visited)
		  {
		    /* No handle attached to this frame, but it's the first */
		    /* pass, so it'd be attached to the conversation. */
		    oidvalue = gss_info->oid;
		    if (gss_info->oid)
		      p_add_proto_data(pinfo->fd, proto_gssapi, 0, gss_info->oid);
		  }
		  if (!oidvalue)
		  {
                    proto_tree_add_text(subtree, gss_tvb, start_offset, 0,
					  "Unknown header (class=%d, pc=%d, tag=%d)",
					  appclass, pc, tag);
		    return_offset = tvb_length(gss_tvb);
		    goto done;
		  } else {
		    tvbuff_t *oid_tvb_local;

		    oid_tvb_local = tvb_new_subset_remaining(gss_tvb, start_offset);
		    if (is_verifier)
			handle = oidvalue->wrap_handle;
		    else
			handle = oidvalue->handle;
		    len = call_dissector(handle, oid_tvb_local, pinfo, subtree);
		    if (len == 0)
			return_offset = tvb_length(gss_tvb);
		    else
			return_offset = start_offset + len;
		    goto done; /* We are finished here */
		  }
		}

		/* Read oid */
		oid_start_offset=offset;
		offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, gss_tvb, offset, hf_gssapi_oid, &oid);
		oidvalue = gssapi_lookup_oid_str(oid);


		/* Check if we need reassembly of this blob.
		 * Only try reassembly for OIDs we recognize
		 * and when we have the entire tvb
		 *
		 * SMB will sometimes split one large GSSAPI blob
		 * across multiple SMB/SessionSetup commands.
		 * While we should look at the uid returned in the response
		 * to the first SessionSetup and use that as a key
		 * instead for simplicity we assume there will not be several
		 * such authentication at once on a single tcp session
		 */
		if( (!pinfo->fd->flags.visited)
		&&  (oidvalue)
		&&  (tvb_length(gss_tvb)==tvb_reported_length(gss_tvb))
		&&  (len1>(guint32)tvb_length_remaining(gss_tvb, oid_start_offset))
		&&  (gssapi_reassembly) ){
			fi=se_new(gssapi_frag_info_t);
			fi->first_frame=pinfo->fd->num;
			fi->reassembled_in=0;
			se_tree_insert32(gss_info->frags, pinfo->fd->num, fi);

			fragment_add(&gssapi_reassembly_table,
				gss_tvb, 0, pinfo, pinfo->fd->num, NULL,
				0, tvb_length(gss_tvb), TRUE);
			fragment_set_tot_len(&gssapi_reassembly_table,
				pinfo, pinfo->fd->num, NULL, len1+oid_start_offset);

			gss_info->do_reassembly=TRUE;
			gss_info->first_frame=pinfo->fd->num;
			gss_info->frag_offset=tvb_length(gss_tvb);
			goto done;
		}


		/*
		 * Hand off to subdissector.
		 */

		if ((oidvalue == NULL) ||
		    !proto_is_protocol_enabled(oidvalue->proto)) {
			/* No dissector for this oid */
			proto_tree_add_text(subtree, gss_tvb, oid_start_offset, -1,
					    "Token object");

			return_offset = tvb_length(gss_tvb);
			goto done;
		}

		/* Save a pointer to the data for the OID for the
		 * GSSAPI protocol for this conversation.
		 */

		/*
		 * Now add the proto data ...
		 * but only if it is not already there.
		 */
		if(!gss_info->oid){
		  gss_info->oid=oidvalue;
		}

		if (is_verifier) {
			handle = oidvalue->wrap_handle;
			if (handle != NULL) {
				oid_tvb = tvb_new_subset_remaining(gss_tvb, offset);
				len = call_dissector(handle, oid_tvb, pinfo,
				    subtree);
				if (len == 0)
					return_offset = tvb_length(gss_tvb);
				else
					return_offset = offset + len;
			} else {
				proto_tree_add_text(subtree, gss_tvb, offset, -1,
				    "Authentication verifier");
				return_offset = tvb_length(gss_tvb);
			}
		} else {
			handle = oidvalue->handle;
			if (handle != NULL) {
				oid_tvb = tvb_new_subset_remaining(gss_tvb, offset);
				len = call_dissector(handle, oid_tvb, pinfo,
				    subtree);
				if (len == 0)
					return_offset = tvb_length(gss_tvb);
				else
					return_offset = offset + len;
			} else {
				proto_tree_add_text(subtree, gss_tvb, offset, -1,
				    "Authentication credentials");
				return_offset = tvb_length(gss_tvb);
			}
		}

	 done:
		;
	} 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.
		 *
		 * Restore the private_data structure in case one of the
		 * called dissectors modified it (and, due to the exception,
		 * was unable to restore it).
		 */
		pinfo->private_data = pd_save;
		show_exception(gss_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
	} ENDTRY;

	proto_item_set_len(item, return_offset);
	return return_offset;
}
Esempio n. 22
0
/* Code to actually dissect the packets */
static void
dissect_brdwlk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

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

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

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

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

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

        brdwlk_tree = proto_item_add_subtree (ti, ett_brdwlk);

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

    }

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

                    /*
                     * Mark this frame as having been preceded by dropped
                     * packets.  (The data we use as the frame data doesn't
                     * matter - it just matters that it's non-null.)
                     */
                    p_add_proto_data(pinfo->fd, proto_brdwlk, &packet_count);
                }
            }

            if (tree) {
                hidden_item = proto_tree_add_boolean (brdwlk_tree, hf_brdwlk_drop,
                                               tvb, offset, 0, dropped_packets);
                PROTO_ITEM_SET_HIDDEN(hidden_item);
            }
        }
        packet_count = pkt_cnt;

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

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

        if ((error & BRDWLK_HAS_PLEN) && tree) {
            /* In newer Boardwalks, if this bit is set, the actual frame length
             * is also provided. This length is the size between SOF & EOF
             * including FC CRC.
             */
            plen = tvb_get_ntohl (tvb, offset-4);
            plen *= 4;
            proto_tree_add_uint (brdwlk_tree, hf_brdwlk_plen, tvb, offset-4,
                                 4, plen);
            
#if 0
            /* XXX - this would throw an exception if it would increase
             * the reported length.
             */
            if (error & BRDWLK_TRUNCATED_BIT) {
                tvb_set_reported_length (tvb, plen);
            }
#endif
        }
    }
    
    next_tvb = tvb_new_subset (tvb, 2, len, reported_len);
    if (fc_dissector_handle) {
        call_dissector (fc_dissector_handle, next_tvb, pinfo, tree);
    }
}
Esempio n. 23
0
static void
dissect_k12(tvbuff_t* tvb,packet_info* pinfo,proto_tree* tree)
{
    static dissector_handle_t data_handles[] = {NULL,NULL};
    proto_item* k12_item;
    proto_tree* k12_tree;
    proto_item* stack_item;
    dissector_handle_t sub_handle = NULL;
    dissector_handle_t* handles;
    guint i;

    k12_item = proto_tree_add_protocol_format(tree, proto_k12, tvb, 0, 0,
               "Packet from: '%s' (0x%.8x)",
               pinfo->pseudo_header->k12.input_name,
               pinfo->pseudo_header->k12.input);

    k12_tree = proto_item_add_subtree(k12_item, ett_k12);

    proto_tree_add_uint(k12_tree, hf_k12_port_id, tvb, 0,0,pinfo->pseudo_header->k12.input);
    proto_tree_add_string(k12_tree, hf_k12_port_name, tvb, 0,0,pinfo->pseudo_header->k12.input_name);
    stack_item = proto_tree_add_string(k12_tree, hf_k12_stack_file, tvb, 0,0,pinfo->pseudo_header->k12.stack_file);

    k12_item = proto_tree_add_uint(k12_tree, hf_k12_port_type, tvb, 0, 0,
                                   pinfo->pseudo_header->k12.input_type);

    k12_tree = proto_item_add_subtree(k12_item, ett_port);

    switch ( pinfo->pseudo_header->k12.input_type ) {
    case K12_PORT_DS0S:
        proto_tree_add_uint(k12_tree, hf_k12_ts, tvb, 0,0,pinfo->pseudo_header->k12.input_info.ds0mask);
        break;
    case K12_PORT_ATMPVC:
    {
        gchar* circuit_str = ep_strdup_printf("%u:%u:%u",
                                              (guint)pinfo->pseudo_header->k12.input_info.atm.vp,
                                              (guint)pinfo->pseudo_header->k12.input_info.atm.vc,
                                              (guint)pinfo->pseudo_header->k12.input_info.atm.cid);

        /*
         * XXX: this is prone to collisions!
         * we need an uniform way to manage circuits between dissectors
         */
        pinfo->circuit_id = g_str_hash(circuit_str);

        proto_tree_add_uint(k12_tree, hf_k12_atm_vp, tvb, 0, 0,
                            pinfo->pseudo_header->k12.input_info.atm.vp);
        proto_tree_add_uint(k12_tree, hf_k12_atm_vc, tvb, 0, 0,
                            pinfo->pseudo_header->k12.input_info.atm.vc);
        if (pinfo->pseudo_header->k12.input_info.atm.cid)
            proto_tree_add_uint(k12_tree, hf_k12_atm_cid, tvb, 0, 0,
                                pinfo->pseudo_header->k12.input_info.atm.cid);
        break;
    }
    default:
        break;
    }

    handles = se_tree_lookup32(port_handles, pinfo->pseudo_header->k12.input);

    if (! handles ) {
        for (i=0 ; i < nk12_handles; i++) {
            if ( epan_strcasestr(pinfo->pseudo_header->k12.stack_file, k12_handles[i].match)
                    || epan_strcasestr(pinfo->pseudo_header->k12.input_name, k12_handles[i].match) ) {
                handles = k12_handles[i].handles;
                break;
            }
        }

        if (!handles) {
            data_handles[0] = data_handle;
            handles = data_handles;
        }

        se_tree_insert32(port_handles, pinfo->pseudo_header->k12.input, handles);

    }

    if (handles == data_handles) {
        proto_tree* stack_tree = proto_item_add_subtree(stack_item,ett_stack_item);
        proto_item* item;

        item = proto_tree_add_text(stack_tree,tvb,0,0,
                                   "Warning: stk file not matched in the 'K12 Protocols' table");
        PROTO_ITEM_SET_GENERATED(item);
        expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN, "unmatched stk file");

        item = proto_tree_add_text(stack_tree,tvb,0,0,
                                   "Info: You can edit the 'K12 Protocols' table from Preferences->Protocols->k12xx");
        PROTO_ITEM_SET_GENERATED(item);

        call_dissector(data_handle, tvb, pinfo, tree);
        return;
    }

    /* Setup subdissector information */

    for (i = 0; handles[i] && handles[i+1]; ++i) {
        if (handles[i] == sscop_handle) {
            sscop_payload_info *p_sscop_info = p_get_proto_data(pinfo->fd, proto_sscop);
            if (!p_sscop_info) {
                p_sscop_info = se_alloc0(sizeof(sscop_payload_info));
                p_add_proto_data(pinfo->fd, proto_sscop, p_sscop_info);
                p_sscop_info->subdissector = handles[i+1];
            }
        }
        /* Add more protocols here */
    }

    sub_handle = handles[0];

    /* Setup information required by certain protocols */
    if (sub_handle == fp_handle) {
        fp_info *p_fp_info = p_get_proto_data(pinfo->fd, proto_fp);
        if (!p_fp_info) {
            p_fp_info = se_alloc0(sizeof(fp_info));
            p_add_proto_data(pinfo->fd, proto_fp, p_fp_info);

            fill_fp_info(p_fp_info,
                         pinfo->pseudo_header->k12.extra_info,
                         pinfo->pseudo_header->k12.extra_length);
        }
    }

    call_dissector(sub_handle, tvb, pinfo, tree);
}
Esempio n. 24
0
/** Dissector for SoupBinTCP messages */
static void
dissect_soupbintcp_common(
    tvbuff_t    *tvb,
    packet_info *pinfo,
    proto_tree  *tree)
{
    struct conv_data *conv_data;
    struct pdu_data  *pdu_data;
    const char       *pkt_name;
    const char       *tmp_buf;
    proto_item       *ti;
    proto_tree       *soupbintcp_tree = NULL;
    conversation_t   *conv            = NULL;
    guint16           expected_len;
    guint8            pkt_type;
    gint              offset          = 0;
    guint             this_seq        = 0, next_seq;
    heur_dtbl_entry_t *hdtbl_entry;

    /* Get the 16-bit big-endian SOUP packet length */
    expected_len = tvb_get_ntohs(tvb, 0);

    /* Get the 1-byte SOUP message type */
    pkt_type = tvb_get_guint8(tvb, 2);

    /* Since we use the packet name a few times, get and save that value */
    pkt_name = val_to_str(pkt_type, pkt_type_val, "Unknown (%u)");

    /* Set the protocol name in the summary display */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SoupBinTCP");

    /* Set the packet name in the info column */
    col_add_str(pinfo->cinfo, COL_INFO, pkt_name);

    /* Sequence number tracking
     *
     * SOUP does not number packets from client to server (the server
     * acknowledges all important messages, so the client should use
     * the acks to figure out if the server received the message, and
     * otherwise resend it).
     *
     * Packets from server to client are numbered, but it's implicit.
     * The Login Accept packet contains the next sequence number that
     * the server will send, and the client needs to count the
     * Sequenced Data packets that it receives to know what their
     * sequence numbers are.
     *
     * So, we grab the next sequence number from the Login Acceptance
     * packet, and save it in a conversation_t we associate with the
     * TCP session.  Then, for each Sequenced Data packet we receive,
     * the first time it's processed (when PINFO_FD_VISITED() is
     * false), we write it into the PDU's frame's private data pointer
     * and increment the saved sequence number (in the conversation_t).
     *
     * If the visited flag is true, then we've dissected this packet
     * already, and so we can fetch the sequence number from the
     * frame's private data area.
     *
     * In either case, if there's any problem, we report zero as the
     * sequence number, and try to continue dissecting. */

    /* If first dissection of Login Accept, save sequence number */
    if (pkt_type == 'A' && !PINFO_FD_VISITED(pinfo)) {
        tmp_buf = tvb_get_string_enc(wmem_packet_scope(), tvb, 13, 20, ENC_ASCII);
        next_seq = atoi(tmp_buf);

        /* Create new conversation for this session */
        conv = conversation_new(PINFO_FD_NUM(pinfo),
                                &pinfo->src,
                                &pinfo->dst,
                                pinfo->ptype,
                                pinfo->srcport,
                                pinfo->destport,
                                0);

        /* Store starting sequence number for session's packets */
        conv_data = (struct conv_data *)wmem_alloc(wmem_file_scope(), sizeof(struct conv_data));
        conv_data->next_seq = next_seq;
        conversation_add_proto_data(conv, proto_soupbintcp, conv_data);
    }

    /* Handle sequence numbering for a Sequenced Data packet */
    if (pkt_type == 'S') {
        if (!PINFO_FD_VISITED(pinfo)) {
            /* Get next expected sequence number from conversation */
            conv = find_conversation(PINFO_FD_NUM(pinfo),
                                     &pinfo->src,
                                     &pinfo->dst,
                                     pinfo->ptype,
                                     pinfo->srcport,
                                     pinfo->destport,
                                     0);
            if (!conv) {
                this_seq = 0;
            } else {
                conv_data = (struct conv_data *)conversation_get_proto_data(conv,
                                                        proto_soupbintcp);
                if (conv_data) {
                    this_seq = conv_data->next_seq++;
                } else {
                    this_seq = 0;
                }

                pdu_data = (struct pdu_data *)wmem_alloc(
                    wmem_file_scope(),
                    sizeof(struct pdu_data));
                pdu_data->seq_num = this_seq;
                p_add_proto_data(wmem_file_scope(), pinfo, proto_soupbintcp, 0, pdu_data);
            }
        } else {
            pdu_data = (struct pdu_data *)p_get_proto_data(wmem_file_scope(), pinfo, proto_soupbintcp, 0);
            if (pdu_data) {
                this_seq = pdu_data->seq_num;
            } else {
                this_seq = 0;
            }
        }

        col_append_fstr(pinfo->cinfo, COL_INFO, ", SeqNum = %u", this_seq);
    }

    if (tree) {
        /* Create sub-tree for SoupBinTCP details */
        ti = proto_tree_add_item(tree,
                                 proto_soupbintcp,
                                 tvb, 0, -1, ENC_NA);

        soupbintcp_tree = proto_item_add_subtree(ti, ett_soupbintcp);

        /* Append the packet name to the sub-tree item */
        proto_item_append_text(ti, ", %s", pkt_name);

        /* Length */
        proto_tree_add_item(soupbintcp_tree,
                            hf_soupbintcp_packet_length,
                            tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        /* Type */
        proto_tree_add_item(soupbintcp_tree,
                            hf_soupbintcp_packet_type,
                            tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;

        switch (pkt_type) {
        case '+': /* Debug Message */
            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_text,
                                tvb, offset, expected_len - 1, ENC_ASCII|ENC_NA);
            break;

        case 'A': /* Login Accept */
            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_session,
                                tvb, offset, 10, ENC_ASCII|ENC_NA);
            offset += 10;

            tmp_buf = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 20, ENC_ASCII);
            proto_tree_add_string_format_value(soupbintcp_tree,
                                               hf_soupbintcp_next_seq_num,
                                               tvb, offset, 20,
                                               "X", "%d", atoi(tmp_buf));
            break;

        case 'J': /* Login Reject */
            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_reject_code,
                                tvb, offset, 1, ENC_BIG_ENDIAN);
            break;

        case 'U': /* Unsequenced Data */
            /* Display handled by sub-dissector */
            break;

        case 'S': /* Sequenced Data */
            proto_item_append_text(ti, ", SeqNum=%u", this_seq);
            proto_tree_add_string_format_value(soupbintcp_tree,
                                               hf_soupbintcp_seq_num,
                                               tvb, offset, 0,
                                               "X",
                                               "%u (Calculated)",
                                               this_seq);

            /* Display handled by sub-dissector */
            break;

        case 'L': /* Login Request */
            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_username,
                                tvb, offset, 6, ENC_ASCII|ENC_NA);
            offset += 6;

            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_password,
                                tvb, offset, 10, ENC_ASCII|ENC_NA);
            offset += 10;

            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_session,
                                tvb, offset, 10, ENC_ASCII|ENC_NA);
            offset += 10;

            tmp_buf = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, 20, ENC_ASCII);
            proto_tree_add_string_format_value(soupbintcp_tree,
                                               hf_soupbintcp_req_seq_num,
                                               tvb, offset, 20,
                                               "X", "%d", atoi(tmp_buf));
            break;

        case 'H': /* Server Heartbeat */
            break;

        case 'O': /* Logout Request */
            break;

        case 'R': /* Client Heartbeat */
            break;

        case 'Z': /* End of Session */
            break;

        default:
            /* Unknown */
            proto_tree_add_item(tree,
                                hf_soupbintcp_message,
                                tvb, offset, -1, ENC_NA);
            break;
        }
    }

    /* Call sub-dissector for encapsulated data */
    if (pkt_type == 'S' || pkt_type == 'U') {
        tvbuff_t         *sub_tvb;

        /* Sub-dissector tvb starts at 3 (length (2) + pkt_type (1)) */
        sub_tvb = tvb_new_subset_remaining(tvb, 3);

#if 0   /* XXX: It's not valid for a soupbintcp subdissector to call       */
        /*  conversation_set_dissector() since the conversation is really  */
        /*  a TCP conversation.  (A 'soupbintcp' port type would need to   */
        /*  be defined to be able to use conversation_set_dissector()).    */
        /* In addition, no current soupbintcp subdissector calls           */
        /*  conversation_set_dissector().                                  */

        /* If this packet is part of a conversation, call dissector
         * for the conversation if available */
        if (try_conversation_dissector(&pinfo->dst, &pinfo->src, pinfo->ptype,
                                       pinfo->srcport, pinfo->destport,
                                       sub_tvb, pinfo, tree, NULL)) {
            return;
        }
#endif

        /* Otherwise, try heuristic dissectors */
        if (dissector_try_heuristic(heur_subdissector_list,
                                    sub_tvb,
                                    pinfo,
                                    tree,
                                    &hdtbl_entry,
                                    NULL)) {
            return;
        }

        /* Otherwise, give up, and just print the bytes in hex */
        if (tree) {
            proto_tree_add_item(soupbintcp_tree,
                                hf_soupbintcp_message,
                                sub_tvb, 0, -1,
                                ENC_NA);
        }
    }
}
Esempio n. 25
0
static void
dissect_smb_direct_payload(tvbuff_t *tvb, packet_info *pinfo,
			   proto_tree *tree, guint32 remaining_length)
{
	gboolean save_fragmented = pinfo->fragmented;
	int save_visited = pinfo->fd->flags.visited;
	conversation_t *conversation = NULL;
	fragment_head *fd_head = NULL;
	tvbuff_t *payload_tvb = NULL;
	gboolean more_frags = FALSE;
	gboolean fd_head_not_cached = FALSE;
	heur_dtbl_entry_t *hdtbl_entry;

	if (!smb_direct_reassemble) {
		payload_tvb = tvb;
		goto dissect_payload;
	}

	conversation = find_or_create_conversation(pinfo);

	if (remaining_length > 0) {
		more_frags = TRUE;
	}

	fd_head = (fragment_head *)p_get_proto_data(wmem_file_scope(), pinfo, proto_smb_direct, 0);
	if (fd_head == NULL) {
		fd_head_not_cached = TRUE;

		pinfo->fd->flags.visited = 0;
		fd_head = fragment_add_seq_next(&smb_direct_reassembly_table,
						tvb, 0, pinfo,
						conversation->index,
						NULL, tvb_captured_length(tvb),
						more_frags);
	}

	if (fd_head == NULL) {
		/*
		 * We really want the fd_head and pass it to
		 * process_reassembled_data()
		 *
		 * So that individual fragments gets the
		 * reassembled in field.
		 */
		fd_head = fragment_get_reassembled_id(&smb_direct_reassembly_table,
						      pinfo,
						      conversation->index);
	}

	if (fd_head == NULL) {
		/*
		 * we need more data...
		 */
		goto done;
	}

	if (fd_head_not_cached) {
		p_add_proto_data(wmem_file_scope(), pinfo,
				 proto_smb_direct, 0, fd_head);
	}

	payload_tvb = process_reassembled_data(tvb, 0, pinfo,
					       "Reassembled SMB Direct",
					       fd_head,
					       &smb_direct_frag_items,
					       NULL, /* update_col_info*/
					       tree);
	if (payload_tvb == NULL) {
		/*
		 * we need more data...
		 */
		goto done;
	}

dissect_payload:
	pinfo->fragmented = FALSE;
	if (!dissector_try_heuristic(smb_direct_heur_subdissector_list,
				     payload_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
		call_dissector(data_handle, payload_tvb, pinfo, tree);
	}
done:
	pinfo->fragmented = save_fragmented;
	pinfo->fd->flags.visited = save_visited;
	return;
}
Esempio n. 26
0
static void
dissect_fcp_cmnd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, proto_tree *tree, conversation_t *conversation, fc_hdr *fchdr, fcp_conv_data_t *fcp_conv_data)
{
    int          offset  = 0;
    int          add_len = 0;
    guint8       flags, rwflags, lun0;
    guint16      lun     = 0xffff;
    tvbuff_t    *cdb_tvb;
    int          tvb_len;
    fcp_request_data_t *request_data = NULL;
    itl_nexus_t itl;
    fcp_proto_data_t *proto_data;

    /* Determine the length of the FCP part of the packet */
    flags = tvb_get_guint8(tvb, offset+10);
    if (flags) {
        add_len = tvb_get_guint8(tvb, offset+11) & 0x7C;
        add_len = add_len >> 2;
    }

    lun0 = tvb_get_guint8(tvb, offset);

    /* Display single-level LUNs in decimal for clarity */
    /* I'm taking a shortcut here by assuming that if the first byte of the
     * LUN field is 0, it is a single-level LUN. This is not true. For a
     * real single-level LUN, all 8 bytes except byte 1 must be 0.
     */
    if (lun0) {
      proto_tree_add_item(tree, hf_fcp_multilun, tvb, offset, 8, ENC_NA);
      lun = tvb_get_guint8(tvb, offset) & 0x3f;
      lun <<= 8;
      lun |= tvb_get_guint8(tvb, offset+1);
    } else {
      proto_tree_add_item(tree, hf_fcp_singlelun, tvb, offset+1,
                          1, ENC_BIG_ENDIAN);
      lun = tvb_get_guint8(tvb, offset+1);
    }

    if (!pinfo->fd->flags.visited) {
        proto_data = wmem_new(wmem_file_scope(), fcp_proto_data_t);
        proto_data->lun = lun;
        p_add_proto_data(wmem_file_scope(), pinfo, proto_fcp, 0, proto_data);
    }

    request_data = (fcp_request_data_t*)wmem_map_lookup(fcp_conv_data->luns, GUINT_TO_POINTER((guint)lun));
    if (!request_data) {
        request_data = wmem_new(wmem_file_scope(), fcp_request_data_t);
        request_data->request_frame = pinfo->num;
        request_data->response_frame = 0;
        request_data->request_time = pinfo->abs_ts;

        request_data->itlq = wmem_new(wmem_file_scope(), itlq_nexus_t);
        request_data->itlq->first_exchange_frame=0;
        request_data->itlq->last_exchange_frame=0;
        request_data->itlq->lun=lun;
        request_data->itlq->scsi_opcode=0xffff;
        request_data->itlq->task_flags=0;
        request_data->itlq->data_length=0;
        request_data->itlq->bidir_data_length=0;
        request_data->itlq->fc_time=pinfo->abs_ts;
        request_data->itlq->flags=0;
        request_data->itlq->alloc_len=0;
        request_data->itlq->extra_data=NULL;

        wmem_map_insert(fcp_conv_data->luns, GUINT_TO_POINTER((guint)lun), request_data);
    }

    /* populate the exchange struct */
    if(!pinfo->fd->flags.visited){
        if(fchdr->fctl&FC_FCTL_EXCHANGE_FIRST){
            request_data->itlq->first_exchange_frame=pinfo->num;
            request_data->itlq->fc_time = pinfo->abs_ts;
        }
        if(fchdr->fctl&FC_FCTL_EXCHANGE_LAST){
            request_data->itlq->last_exchange_frame=pinfo->num;
        }
    }

    if (request_data->itlq)
        request_data->itlq->lun = lun;

    fchdr->lun = lun;

    proto_tree_add_item(tree, hf_fcp_crn, tvb, offset+8, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_fcp_taskattr, tvb, offset+9, 1, ENC_BIG_ENDIAN);
    dissect_task_mgmt_flags(pinfo, tree, tvb, offset+10);
    proto_tree_add_item(tree, hf_fcp_addlcdblen, tvb, offset+11, 1, ENC_BIG_ENDIAN);
    rwflags = tvb_get_guint8(tvb, offset+11);
    if (request_data->itlq) {
        if (rwflags & 0x02) {
            request_data->itlq->task_flags |= SCSI_DATA_READ;
        }
        if (rwflags & 0x01) {
            request_data->itlq->task_flags |= SCSI_DATA_WRITE;
        }
    }
    proto_tree_add_item(tree, hf_fcp_rddata, tvb, offset+11, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_fcp_wrdata, tvb, offset+11, 1, ENC_BIG_ENDIAN);

    tvb_len = tvb_captured_length_remaining(tvb, offset+12);
    if (tvb_len > (16 + add_len))
      tvb_len = 16 + add_len;

    itl.cmdset = 0xff;
    itl.conversation = conversation;

    cdb_tvb = tvb_new_subset_length(tvb, offset+12, tvb_len);
    dissect_scsi_cdb(cdb_tvb, pinfo, parent_tree, SCSI_DEV_UNKNOWN, request_data->itlq, &itl);

    proto_tree_add_item(tree, hf_fcp_dl, tvb, offset+12+16+add_len,
                        4, ENC_BIG_ENDIAN);
    if (request_data->itlq) {
        request_data->itlq->data_length = tvb_get_ntohl(tvb, offset+12+16+add_len);
    }

    if ( ((rwflags & 0x03) == 0x03)
    &&  tvb_reported_length_remaining(tvb, offset+12+16+add_len+4) >= 4) {
        proto_tree_add_item(tree, hf_fcp_bidir_dl, tvb, offset+12+16+add_len+4,
                            4, ENC_BIG_ENDIAN);
        if (request_data->itlq) {
            request_data->itlq->bidir_data_length = tvb_get_ntohl(tvb, offset+12+16+add_len+4);
        }

    }

}
Esempio n. 27
0
/* Packet dissection routine called by tcp (& udp) when port 873 detected */
static void
dissect_rsync_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                    gboolean desegment _U_)
{
    conversation_t			*conversation;
    struct rsync_conversation_data	*conversation_data;
    struct rsync_frame_data		*rsync_frame_data_p;
    proto_item				*ti;
    proto_tree				*rsync_tree;
    int					offset = 0;
    gchar				version[5];
    gchar				auth_string[10];
    guint				buff_length;
    gchar				magic_string[14];
    gchar				*version_out;

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

    col_clear(pinfo->cinfo, COL_INFO);

    conversation = find_or_create_conversation(pinfo);

    conversation_data = conversation_get_proto_data(conversation, proto_rsync);

    if (conversation_data == NULL) {
        conversation_data = se_alloc(sizeof(struct rsync_conversation_data));
        conversation_data->state = RSYNC_INIT;
        conversation_add_proto_data(conversation, proto_rsync, conversation_data);
    }

    conversation_set_dissector(conversation, rsync_handle);

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

    rsync_tree = proto_item_add_subtree(ti, ett_rsync);

    rsync_frame_data_p = p_get_proto_data(pinfo->fd, proto_rsync);
    if (!rsync_frame_data_p) {
        /* then we haven't seen this frame before */
        rsync_frame_data_p = se_alloc(sizeof(struct rsync_frame_data));
        rsync_frame_data_p->state = conversation_data->state;
        p_add_proto_data(pinfo->fd, proto_rsync, rsync_frame_data_p);
    }

    switch (rsync_frame_data_p->state) {
    case RSYNC_INIT:
        proto_tree_add_item(rsync_tree, hf_rsync_hdr_magic, tvb, offset, 8, ENC_ASCII|ENC_NA);
        offset += 8;
        proto_tree_add_item(rsync_tree, hf_rsync_hdr_version, tvb, offset, 4, ENC_ASCII|ENC_NA);
        tvb_get_nstringz0(tvb, offset, sizeof(version), version);
        offset += 4;

        if (check_col(pinfo->cinfo, COL_INFO)) {
            /* XXX - is this really a string? */
            version_out = format_text(version, 4);
            col_append_fstr(pinfo->cinfo, COL_INFO,
                            "Client Initialisation (Version %s)",
                            version_out);
        }

        conversation_data->state = RSYNC_SERV_INIT;

        break;
    case RSYNC_SERV_INIT:
        proto_tree_add_item(rsync_tree, hf_rsync_hdr_magic, tvb, offset, 8, ENC_ASCII|ENC_NA);
        offset += 8;
        proto_tree_add_item(rsync_tree, hf_rsync_hdr_version, tvb, offset, 4, ENC_ASCII|ENC_NA);
        tvb_get_nstringz0(tvb, offset, sizeof(version), version);
        offset += 4;

        if (check_col(pinfo->cinfo, COL_INFO)) {
            /* XXX - is this really a string? */
            version_out = format_text(version, 4);
            col_append_fstr(pinfo->cinfo, COL_INFO,
                            "Server Initialisation (Version %s)",
                            version_out);
        }

        conversation_data->state = RSYNC_CLIENT_QUERY;

        break;
    case RSYNC_CLIENT_QUERY:
        proto_tree_add_item(rsync_tree, hf_rsync_query_string, tvb, offset, -1, ENC_ASCII|ENC_NA);

        col_append_str(pinfo->cinfo, COL_INFO, "Client Query");

        conversation_data->state = RSYNC_SERV_MOTD;

        break;
    case RSYNC_SERV_MOTD:
        proto_tree_add_item(rsync_tree, hf_rsync_motd_string, tvb, offset, -1, ENC_ASCII|ENC_NA);

        col_append_str(pinfo->cinfo, COL_INFO, "Server MOTD");

        conversation_data->state = RSYNC_SERV_RESPONSE;

        break;
    case RSYNC_SERV_RESPONSE:
        /* there are two cases - file list, or authentication */
        tvb_get_nstringz0(tvb, offset, sizeof(auth_string), auth_string);
        if (0 == strncmp("@RSYNCD:", auth_string, 8)) {
            /* matches, so we assume its an authentication message */
            /* needs to handle the AUTHREQD case, but doesn't - FIXME */
            proto_tree_add_item(rsync_tree, hf_rsync_rsyncdok_string, tvb, offset, -1, ENC_ASCII|ENC_NA);

            col_append_str(pinfo->cinfo, COL_INFO, "Authentication");
            conversation_data->state = RSYNC_COMMAND;

        } else { /*  it didn't match, so it is probably a module list */

            proto_tree_add_item(rsync_tree, hf_rsync_response_string, tvb, offset, -1, ENC_ASCII|ENC_NA);

            col_append_str(pinfo->cinfo, COL_INFO, "Module list");

            /* we need to check the end of the buffer for magic string */
            buff_length = tvb_length_remaining(tvb, offset);
            tvb_get_nstringz0(tvb, buff_length-14, sizeof(magic_string), magic_string);
            if (0 == strncmp("@RSYNCD: EXIT", magic_string, 14)) {
                /* that's all, folks */
                conversation_data->state = RSYNC_COMMAND;
            } else { /* there must be more data */
                conversation_data->state = RSYNC_SERV_RESPONSE;
            }
        }

        break;

    case RSYNC_COMMAND:
        if (pinfo->destport == glb_rsync_tcp_port) {
            /* then we are still sending commands */
            proto_tree_add_item(rsync_tree, hf_rsync_command_string, tvb, offset, -1, ENC_ASCII|ENC_NA);

            col_append_str(pinfo->cinfo, COL_INFO, "Command");

            conversation_data->state = RSYNC_COMMAND;

            break;
        } /* else we fall through to the data phase */

    case RSYNC_DATA:
        /* then we are still sending commands */
        proto_tree_add_item(rsync_tree, hf_rsync_data, tvb, offset, -1, ENC_NA);

        col_append_str(pinfo->cinfo, COL_INFO, "Data");

        conversation_data->state = RSYNC_DATA;

        break;

    }

}
Esempio n. 28
0
/* initialize the tap t38_info and the conversation */
static void
init_t38_info_conv(packet_info *pinfo)
{
	/* tap info */
	t38_info_current++;
	if (t38_info_current==MAX_T38_MESSAGES_IN_PACKET) {
		t38_info_current=0;
	}
	t38_info = &t38_info_arr[t38_info_current];

	t38_info->seq_num = 0;
	t38_info->type_msg = 0;
	t38_info->data_value = 0;
	t38_info->t30ind_value =0;
	t38_info->setup_frame_number = 0;
	t38_info->Data_Field_field_type_value = 0;
	t38_info->desc[0] = '\0';
	t38_info->desc_comment[0] = '\0';
	t38_info->time_first_t4_data = 0;
	t38_info->frame_num_first_t4_data = 0;


	/*
		p_t38_packet_conv hold the conversation info in each of the packets.
		p_t38_conv hold the conversation info used to reassemble the HDLC packets, and also the Setup info (e.g SDP)
		If we already have p_t38_packet_conv in the packet, it means we already reassembled the HDLC packets, so we don't
		need to use p_t38_conv
	*/
	p_t38_packet_conv = NULL;
	p_t38_conv = NULL;

	/* Use existing packet info if available */
	 p_t38_packet_conv = (t38_conv *)p_get_proto_data(wmem_file_scope(), pinfo, proto_t38, 0);


	/* find the conversation used for Reassemble and Setup Info */
	p_conv = find_conversation(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src,
                                   pinfo->ptype,
                                   pinfo->destport, pinfo->srcport, NO_ADDR_B | NO_PORT_B);

	/* create a conv if it doen't exist */
	if (!p_conv) {
		p_conv = conversation_new(pinfo->fd->num, &pinfo->net_src, &pinfo->net_dst,
			      pinfo->ptype, pinfo->srcport, pinfo->destport, NO_ADDR_B | NO_PORT_B);

		/* Set dissector */
		conversation_set_dissector(p_conv, t38_udp_handle);
	}

	if (!p_t38_packet_conv) {
		p_t38_conv = (t38_conv *)conversation_get_proto_data(p_conv, proto_t38);

		/* create the conversation if it doen't exist */
		if (!p_t38_conv) {
			p_t38_conv = wmem_new(wmem_file_scope(), t38_conv);
			p_t38_conv->setup_method[0] = '\0';
			p_t38_conv->setup_frame_number = 0;

			p_t38_conv->src_t38_info.reass_ID = 0;
			p_t38_conv->src_t38_info.reass_start_seqnum = -1;
			p_t38_conv->src_t38_info.reass_data_type = 0;
			p_t38_conv->src_t38_info.last_seqnum = -1;
			p_t38_conv->src_t38_info.packet_lost = 0;
			p_t38_conv->src_t38_info.burst_lost = 0;
			p_t38_conv->src_t38_info.time_first_t4_data = 0;
			p_t38_conv->src_t38_info.additional_hdlc_data_field_counter = 0;
			p_t38_conv->src_t38_info.seqnum_prev_data_field = -1;

			p_t38_conv->dst_t38_info.reass_ID = 0;
			p_t38_conv->dst_t38_info.reass_start_seqnum = -1;
			p_t38_conv->dst_t38_info.reass_data_type = 0;
			p_t38_conv->dst_t38_info.last_seqnum = -1;
			p_t38_conv->dst_t38_info.packet_lost = 0;
			p_t38_conv->dst_t38_info.burst_lost = 0;
			p_t38_conv->dst_t38_info.time_first_t4_data = 0;
			p_t38_conv->dst_t38_info.additional_hdlc_data_field_counter = 0;
			p_t38_conv->dst_t38_info.seqnum_prev_data_field = -1;

			conversation_add_proto_data(p_conv, proto_t38, p_t38_conv);
		}

		/* copy the t38 conversation info to the packet t38 conversation */
		p_t38_packet_conv = wmem_new(wmem_file_scope(), t38_conv);
		g_strlcpy(p_t38_packet_conv->setup_method, p_t38_conv->setup_method, MAX_T38_SETUP_METHOD_SIZE);
		p_t38_packet_conv->setup_frame_number = p_t38_conv->setup_frame_number;

		memcpy(&(p_t38_packet_conv->src_t38_info), &(p_t38_conv->src_t38_info), sizeof(t38_conv_info));
		memcpy(&(p_t38_packet_conv->dst_t38_info), &(p_t38_conv->dst_t38_info), sizeof(t38_conv_info));

		p_add_proto_data(wmem_file_scope(), pinfo, proto_t38, 0, p_t38_packet_conv);
	}

	if (ADDRESSES_EQUAL(&p_conv->key_ptr->addr1, &pinfo->net_src)) {
		p_t38_conv_info = &(p_t38_conv->src_t38_info);
		p_t38_packet_conv_info = &(p_t38_packet_conv->src_t38_info);
	} else {
		p_t38_conv_info = &(p_t38_conv->dst_t38_info);
		p_t38_packet_conv_info = &(p_t38_packet_conv->dst_t38_info);
	}

	/* update t38_info */
	t38_info->setup_frame_number = p_t38_packet_conv->setup_frame_number;
}
Esempio n. 29
0
/* G.7041 6.1.2 GFP payload area */
static void
dissect_gfp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *gfp_tree, guint *offset, guint payload_len)
{
    tvbuff_t *payload_tvb;
    proto_item *type_ti = NULL;
    proto_item *fcs_ti;
    proto_tree *fcs_tree = NULL;
    guint pti, pfi, exi, upi;
    guint fcs, fcs_calc;
    guint fcs_len = 0;

    /* G.7041 6.1.2.3 Payload area scrambling
     * Note that payload when sent on the wire is scrambled as per ATM
     * with a 1 + x^43 multiplicative scrambler. Likely already removed by
     * the time we get a capture file (as with ATM). Could have a pref,
     * but if it's present we have to save state over subsequent frames,
     * always would fail to decode the first 43 payload bytes of a capture. */

    /* G.7041 6.1.2.1 Payload Header - at least 4 bytes */
    tvb_ensure_bytes_exist(tvb, *offset, 4);
    payload_len -= 4;

    /* G.7041 6.1.2.1.1 GFP type field - mandatory 2 bytes */
    pti = tvb_get_bits8(tvb, 8*(*offset), 3);
    pfi = tvb_get_bits8(tvb, 8*(*offset)+3, 1);
    exi = tvb_get_bits8(tvb, 8*(*offset)+4, 4);
    upi = tvb_get_guint8(tvb, *offset+1);
    p_add_proto_data(pinfo->pool, pinfo, proto_gfp, 0, GUINT_TO_POINTER(upi));

    col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pti, gfp_pti_vals, "Reserved PTI (%d)"));
    if (pti == GFP_USER_DATA ||
            pti == GFP_MANAGEMENT_COMMUNICATIONS) {
        /* G.7041 Table 6-3 - GFP_MANAGEMENT_COMMUNICATIONS
         * uses the same UPI table as USER_DATA, though
         * "not all of these UPI types are applicable" in that case. */
        type_ti = proto_tree_add_bitmask_with_flags(gfp_tree, tvb, *offset, hf_gfp_type,
                  ett_gfp_type, gfp_type_data_fields, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
        col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", rval_to_str(upi, gfp_upi_data_rvals, "Unknown 0x%02x"));
    } else if (pti == GFP_CLIENT_MANAGEMENT) {
        /* G.7041 Table 6-4 */
        type_ti = proto_tree_add_bitmask_with_flags(gfp_tree, tvb, *offset, hf_gfp_type,
                  ett_gfp_type, gfp_type_management_fields, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
        col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", rval_to_str(upi, gfp_upi_management_rvals, "Unknown 0x%02x"));
    }

    /* G.7041 6.1.2.1.2 Type HEC (tHEC) - mandatory 2 bytes */
    gfp_add_hec_tree(tvb, pinfo, gfp_tree, offset, 2, hf_gfp_thec, hf_gfp_thec_status, &ei_gfp_thec_bad);

    switch (exi) {
    case GFP_EXT_NULL:
        /* G.7041 6.1.2.1.3.1 Null extension header */
        break;

    case GFP_EXT_LINEAR:
        /* G.7041 6.1.2.1.3.2 Extension header for a linear frame */
        if (payload_len < 4) {
            expert_add_info(pinfo, type_ti, &ei_gfp_exi_short);
            payload_len = 0;
        }
        else {
            payload_len -= 4;
        }
        proto_tree_add_item(gfp_tree, hf_gfp_cid, tvb, *offset, 1, ENC_BIG_ENDIAN);
        /* Next byte spare field, reserved */

        /* 6.1.2.1.4 Extension HEC field */
        gfp_add_hec_tree(tvb, pinfo, gfp_tree, offset, 2, hf_gfp_ehec, hf_gfp_ehec_status, &ei_gfp_ehec_bad);
        break;
    case GFP_EXT_RING:
    /* 6.1.2.1.3.3 Extension header for a ring frame */
    /* "For further study." Undefined so fall through */
    default:
        /* Reserved */
        /* TODO: Mark as error / unhandled? */
        break;
    }

    proto_item_set_end(gfp_tree, tvb, *offset);

    if (pfi == 1) { /* 6.1.2.2.1 Payload FCS field present */
        if (payload_len < 4) {
            expert_add_info(pinfo, type_ti, &ei_gfp_pfi_short);
            fcs_len = payload_len;
            payload_len = 0;
        } else {
            fcs_len = 4;
            payload_len -= 4;
        }

        proto_tree_set_appendix(gfp_tree, tvb, *offset + payload_len, fcs_len);
        fcs = tvb_get_ntohl(tvb, *offset + payload_len);
        /* Same CRC32 as ATM */
        /* As with ATM, we can either compute the CRC as it would be
         * calculated and compare (last step involves taking the complement),
         * or we can include the passed CRC in the input and check to see
         * if the remainder is a known value. I like the first method
         * only because it lets us display what we should have received. */
        /* Method 1: */
        fcs_calc = crc32_mpeg2_tvb_offset(tvb, *offset, payload_len);
        if (fcs == ~fcs_calc) {
            fcs_ti = proto_tree_add_uint_format_value(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs, "0x%08x [correct]", fcs);
            fcs_tree = proto_item_add_subtree(fcs_ti, ett_gfp_fcs);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_good, tvb, *offset+payload_len, 4, TRUE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_bad, tvb, *offset+payload_len, 4, FALSE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
        } else {
            fcs_ti = proto_tree_add_uint_format_value(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs, "0x%08x [incorrect, should be 0x%08x]", fcs, fcs_calc);
            fcs_tree = proto_item_add_subtree(fcs_ti, ett_gfp_fcs);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_good, tvb, *offset+payload_len, 4, FALSE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_bad, tvb, *offset+payload_len, 4, TRUE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
            expert_add_info(pinfo, fcs_ti, &ei_gfp_fcs_bad);
        }
        /* Method 2: */
        /* fcs_calc = crc32_mpeg2_tvb_offset(tvb, *offset, payload_len+4);
        fcs_ti = proto_tree_add_uint(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs);
        proto_item_append_text(fcs_ti, (fcs_calc == 0xC704DD7B) ? " [correct]" : " [incorrect]"); */
    }

    /* Some client frames we can do. Others are not implemented yet.
     * Transparent mode types are much trickier than frame-mapped,
     * since they requires reassembling streams across multiple GFP packets. */
    payload_tvb = tvb_new_subset_length(tvb, *offset, payload_len);
    switch (pti) {
    case GFP_USER_DATA:
    case GFP_MANAGEMENT_COMMUNICATIONS:
        if (!dissector_try_uint(gfp_dissector_table, upi, payload_tvb, pinfo, tree)) {
            expert_add_info_format(pinfo, type_ti, &ei_gfp_payload_undecoded, "Payload type 0x%02x (%s) unsupported", upi, rval_to_str_const(upi, gfp_upi_data_rvals, "UNKNOWN"));
            call_data_dissector(payload_tvb, pinfo, tree);
        }
        break;

    case GFP_CLIENT_MANAGEMENT:
        call_data_dissector(payload_tvb, pinfo, tree);
        break;

    default:
        break;
    }
    *offset += payload_len;
    *offset += fcs_len;
}