Пример #1
0
/* Set up an MSRP conversation using the info given */
void msrp_add_address( packet_info *pinfo,
                       address *addr, int port,
                       const gchar *setup_method, guint32 setup_frame_number)
{
	address null_addr;
	conversation_t* p_conv;
	struct _msrp_conversation_info *p_conv_data = NULL;

	/*
	 * If this isn't the first time this packet has been processed,
	 * we've already done this work, so we don't need to do it
	 * again.
	 */
	if (pinfo->fd->flags.visited)
	{
		return;
	}

	SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);

	/*
	 * Check if the ip address and port combination is not
	 * already registered as a conversation.
	 */
	p_conv = find_conversation( pinfo->fd->num, addr, &null_addr, PT_TCP, port, 0,
	                            NO_ADDR_B | NO_PORT_B);

	/*
	 * If not, create a new conversation.
	 */
	if (!p_conv) {
		p_conv = conversation_new( pinfo->fd->num, addr, &null_addr, PT_TCP,
		                           (guint32)port, 0,
		                           NO_ADDR2 | NO_PORT2);
	}

	/* Set dissector */
	conversation_set_dissector(p_conv, msrp_handle);

	/*
	 * Check if the conversation has data associated with it.
	 */
	p_conv_data = conversation_get_proto_data(p_conv, proto_msrp);

	/*
	 * If not, add a new data item.
	 */
	if (!p_conv_data) {
		/* Create conversation data */
		p_conv_data = se_alloc0(sizeof(struct _msrp_conversation_info));
		conversation_add_proto_data(p_conv, proto_msrp, p_conv_data);
	}

	/*
	 * Update the conversation data.
	 */
	p_conv_data->setup_method_set = TRUE;
	g_strlcpy(p_conv_data->setup_method, setup_method, MAX_MSRP_SETUP_METHOD_SIZE);
	p_conv_data->setup_frame_number = setup_frame_number;
}
Пример #2
0
/*  A helper function that calls find_conversation() and, if a conversation is
 *  not found, calls conversation_new().
 *  The frame number and addresses are taken from pinfo.
 *  No options are used, though we could extend this API to include an options
 *  parameter.
 */
conversation_t *
find_or_create_conversation(packet_info *pinfo)
{
	conversation_t *conv=NULL;

	DPRINT(("called for frame #%d: %s:%d -> %s:%d (ptype=%d)",
		pinfo->fd->num, address_to_str(wmem_packet_scope(), &pinfo->src), pinfo->srcport,
		address_to_str(wmem_packet_scope(), &pinfo->dst), pinfo->destport, pinfo->ptype));
	DINDENT();

	/* Have we seen this conversation before? */
	if((conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
				     pinfo->ptype, pinfo->srcport,
				     pinfo->destport, 0)) != NULL) {
		DPRINT(("found previous conversation for frame #%d (last_frame=%d)",
				pinfo->fd->num, conv->last_frame));
		if (pinfo->fd->num > conv->last_frame) {
			conv->last_frame = pinfo->fd->num;
		}
	} else {
		/* No, this is a new conversation. */
		DPRINT(("did not find previous conversation for frame #%d",
				pinfo->fd->num));
		DINDENT();
		conv = conversation_new(pinfo->fd->num, &pinfo->src,
					&pinfo->dst, pinfo->ptype,
					pinfo->srcport, pinfo->destport, 0);
		DENDENT();
	}

	DENDENT();

	return conv;
}
Пример #3
0
static lbmtcp_transport_t * lbmtcp_transport_add(const address * address1, guint16 port1, const address * address2, guint16 port2, guint32 frame)
{
    lbmtcp_transport_t * entry;
    conversation_t * conv = NULL;

    conv = find_conversation(frame, address1, address2, PT_TCP, port1, port2, 0);
    if (conv == NULL)
    {
        conv = conversation_new(frame, address1, address2, PT_TCP, port1, port2, 0);
    }
    entry = (lbmtcp_transport_t *) conversation_get_proto_data(conv, lbmpdm_tcp_protocol_handle);
    if (entry != NULL)
    {
        return (entry);
    }
    entry = wmem_new(wmem_file_scope(), lbmtcp_transport_t);
    copy_address_wmem(wmem_file_scope(), &(entry->addr1), address1);
    entry->port1 = port1;
    copy_address_wmem(wmem_file_scope(), &(entry->addr2), address2);
    entry->port2 = port2;
    lbmtcp_order_key(entry);
    entry->channel = lbm_channel_assign(LBM_CHANNEL_TCP);
    conversation_add_proto_data(conv, lbmpdm_tcp_protocol_handle, (void *) entry);
    return (entry);
}
Пример #4
0
lbttcp_transport_t * lbttcp_transport_add(const address * source_address, guint16 source_port, guint32 session_id, guint32 frame)
{
    lbttcp_transport_t * entry = NULL;
    conversation_t * conv = NULL;
    lbttcp_transport_conv_data_t * conv_data = NULL;

    conv = find_conversation(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0);
    if (conv == NULL)
    {
        conv = conversation_new(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0);
    }
    conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp);
    if (conv_data == NULL)
    {
        conv_data = wmem_new(wmem_file_scope(), lbttcp_transport_conv_data_t);
        conv_data->frame_tree = wmem_tree_new(wmem_file_scope());
        conv_data->session_tree = wmem_tree_new(wmem_file_scope());
        conversation_add_proto_data(conv, proto_lbttcp, (void *) conv_data);
    }
    entry = (lbttcp_transport_t *) wmem_tree_lookup32(conv_data->session_tree, session_id);
    if (entry != NULL)
    {
        return (entry);
    }
    entry = lbttcp_transport_create(source_address, source_port, session_id);
    wmem_tree_insert32(conv_data->session_tree, session_id, (void *) entry);
    wmem_tree_insert32(conv_data->frame_tree, frame, (void *) entry);
    return (entry);
}
Пример #5
0
void lbttcp_transport_sid_add(const address * source_address, guint16 source_port, guint32 frame, guint32 session_id)
{
    conversation_t * conv = NULL;
    lbttcp_transport_conv_data_t * conv_data = NULL;
    lbttcp_transport_t * transport = NULL;

    conv = find_conversation(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0);
    if (conv == NULL)
    {
        conv = conversation_new(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0);
    }
    conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp);
    if (conv_data == NULL)
    {
        conv_data = wmem_new(wmem_file_scope(), lbttcp_transport_conv_data_t);
        conv_data->frame_tree = wmem_tree_new(wmem_file_scope());
        conv_data->session_tree = wmem_tree_new(wmem_file_scope());
        conversation_add_proto_data(conv, proto_lbttcp, (void *) conv_data);
    }
    /* Lookup by frame */
    transport = (lbttcp_transport_t *) wmem_tree_lookup32_le(conv_data->frame_tree, frame);
    if (transport != NULL)
    {
        if (transport->session_id != session_id)
        {
            transport = NULL;
        }
    }
    if (transport == NULL)
    {
        transport = lbttcp_transport_create(source_address, source_port, session_id);
        wmem_tree_insert32(conv_data->session_tree, session_id, (void *) transport);
        wmem_tree_insert32(conv_data->frame_tree, frame, (void *) transport);
    }
}
Пример #6
0
static gboolean
dissect_msrp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	gint offset = 0;
	conversation_t* conversation;

	if ( check_msrp_header(tvb)){
		/*
		 * TODO Set up conversation here
		 */
		if (pinfo->fd->flags.visited){
			/* Look for existing conversation */
			conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
				pinfo->srcport, pinfo->destport, 0);
			/* Create new one if not found */
			if (conversation == NULL){
				conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
					pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
				/* Set dissector */
				conversation_set_dissector(conversation, msrp_handle);
			}
		}
		offset = dissect_msrp(tvb, pinfo, tree);
		return TRUE;
	}
	return FALSE;
}
Пример #7
0
/* Find the current conversation or make a new one if required */
static ts2_conversation* ts2_get_conversation(packet_info *pinfo)
{
    conversation_t *conversation;
    ts2_conversation *conversation_data;
    conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
    if(conversation)
    {

        conversation_data = (ts2_conversation*)conversation_get_proto_data(conversation, proto_ts2);
    }
    else
    {
        conversation_data = g_mem_chunk_alloc(conv_vals);
        conversation_data->last_inorder_server_frame=0; /* sequence number should never be zero so we can use this as an initial number */
        conversation_data->last_inorder_client_frame=0;
        conversation_data->server_port=pinfo->srcport;
        conversation_data->server_frag_size=0;
        conversation_data->server_frag_num=0;
        conversation_data->client_frag_size=0;
        conversation_data->client_frag_num=0;
        conversation = conversation_new(pinfo->fd->num,  &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
        conversation_add_proto_data(conversation, proto_ts2, (void *)conversation_data);
    }
    return conversation_data;
}
Пример #8
0
static void
new_udp_conversation( socks_hash_entry_t *hash_info, packet_info *pinfo){

    conversation_t *conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst,  PT_UDP,
            hash_info->udp_port, hash_info->port, 0);

    DISSECTOR_ASSERT( conversation);

    conversation_add_proto_data(conversation, proto_socks, hash_info);
    conversation_set_dissector(conversation, socks_udp_handle);
}
Пример #9
0
/* Set up an MSRP conversation using the info given */
void
msrp_add_address( packet_info *pinfo,
                       address *addr, int port,
                       const gchar *setup_method, guint32 setup_frame_number)
{
    address null_addr;
    conversation_t* p_conv;
    struct _msrp_conversation_info *p_conv_data = NULL;

    /*
     * If this isn't the first time this packet has been processed,
     * we've already done this work, so we don't need to do it
     * again.
     */
    if (pinfo->fd->flags.visited)
    {
        return;
    }

    clear_address(&null_addr);

    /*
     * Check if the ip address and port combination is not
     * already registered as a conversation.
     */
    p_conv = find_conversation( pinfo->num, addr, &null_addr, ENDPOINT_TCP, port, 0,
                                NO_ADDR_B | NO_PORT_B);

    /*
     * If not, create a new conversation.
     */
    if (!p_conv) {
        p_conv = conversation_new( pinfo->num, addr, &null_addr, ENDPOINT_TCP,
                                   (guint32)port, 0,
                                   NO_ADDR2 | NO_PORT2);
    }

    /* Set dissector */
    conversation_set_dissector(p_conv, msrp_handle);

    /*
     * Check if the conversation has data associated with it.
     */
    p_conv_data = (struct _msrp_conversation_info *)conversation_get_proto_data(p_conv, proto_msrp);

    /*
     * If not, add a new data item.
     */
    if (!p_conv_data) {
        /* Create conversation data */
        p_conv_data = wmem_new0(wmem_file_scope(), struct _msrp_conversation_info);
        conversation_add_proto_data(p_conv, proto_msrp, p_conv_data);
    }
Пример #10
0
/* returns TRUE if this TCP segment carries a MPA REQUEST and FLASE otherwise */
static gboolean
is_mpa_req(tvbuff_t *tvb, packet_info *pinfo)
{
	conversation_t *conversation = NULL;
	mpa_state_t *state = NULL;
	guint8 mcrres;

	if (tvb_get_ntoh64(tvb, 0) != MPA_REQ_REP_FRAME
			|| tvb_get_ntoh64(tvb, 8) != MPA_ID_REQ_FRAME)
		return FALSE;

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

	if (!conversation) {
		conversation = conversation_new(pinfo->fd->num, &pinfo->src,
				&pinfo->dst, pinfo->ptype, pinfo->srcport,
				pinfo->destport, 0);
	}

	if (!get_mpa_state(conversation)) {

		/* associate a MPA connection state to this conversation if
		 * there is no MPA state already associated to this connection
		 */
		state = init_mpa_state();

		/* anaylize MPA connection parameter and record them */
		mcrres = tvb_get_guint8(tvb, 16);
		state->ini_exp_m_res = mcrres & MPA_MARKER_FLAG;
		state->crc = mcrres & MPA_CRC_FLAG;
		state->revision = tvb_get_guint8(tvb, 17);
		state->req_frame_num = pinfo->fd->num;
		state->minfo[MPA_INITIATOR].port = pinfo->srcport;
		state->minfo[MPA_RESPONDER].port = pinfo->destport;

		conversation_add_proto_data(conversation, proto_iwarp_mpa, state);

		/* update expert info */
		if (mcrres & MPA_RESERVED_FLAG)
			expert_add_info_format(pinfo, NULL, PI_REQUEST_CODE, PI_WARN,
					"Res field is NOT set to zero as required by RFC 5044");

		if (state->revision != 1)
			expert_add_info_format(pinfo, NULL, PI_REQUEST_CODE, PI_WARN,
					"Rev field is NOT set to one as required by RFC 5044");
	}
	return TRUE;
}
Пример #11
0
/* When seeing a broadcast talking about an open TCP port on a host, create
 * a conversation to dissect anything sent/received at that address.  Setup
 * protocol data so the TCP dissection knows what broadcast triggered it. */
static void
prepare_ldss_transfer_conv(ldss_broadcast_t *broadcast)
{
	conversation_t *transfer_conv;
	ldss_transfer_info_t *transfer_info;

	transfer_info = wmem_new0(wmem_file_scope(), ldss_transfer_info_t);
	transfer_info->broadcast = broadcast;

	/* Preparation for later push/pull dissection */
	transfer_conv = conversation_new (broadcast->num, &broadcast->broadcaster->addr, &broadcast->broadcaster->addr,
					  PT_TCP, broadcast->broadcaster->port, broadcast->broadcaster->port, NO_ADDR2|NO_PORT2);
	conversation_add_proto_data(transfer_conv, proto_ldss, transfer_info);
	conversation_set_dissector(transfer_conv, ldss_tcp_handle);
}
static void add_msproxy_conversation( packet_info *pinfo,
	hash_entry_t *hash_info){

/* check to see if a conversation already exists, if it does assume 	*/
/* it's our conversation and quit. Otherwise create a new conversation.	*/
/* Load the conversation dissector to our  dissector and load the	*/
/* conversation data structure with the info needed to call the TCP or 	*/
/* UDP port decoder.							*/

/* NOTE: Currently this assume that the conversation will be created 	*/
/* 	during a packet from the server.  If that changes, pinfo->src	*/
/*	and pinfo->dst will not be correct and this routine will have	*/
/*	to change.							*/

	conversation_t *conversation;
	redirect_entry_t *new_conv_info;

	if (pinfo->fd->flags.visited) {
		/*
		 * We've already processed this frame once, so we
		 * should already have done this.
		 */
		return;
	}

	conversation = find_conversation( pinfo->fd->num, &pinfo->src,
		&pinfo->dst, (port_type)hash_info->proto, hash_info->server_int_port,
		hash_info->clnt_port, 0);

	if ( !conversation) {
		conversation = conversation_new( pinfo->fd->num, &pinfo->src, &pinfo->dst,
			(port_type)hash_info->proto, hash_info->server_int_port,
			hash_info->clnt_port, 0);
	}
	conversation_set_dissector(conversation, msproxy_sub_handle);

	new_conv_info = se_new(redirect_entry_t);

	new_conv_info->remote_addr = hash_info->dst_addr;
	new_conv_info->clnt_port = hash_info->clnt_port;
	new_conv_info->remote_port = hash_info->dst_port;
	new_conv_info->server_int_port = hash_info->server_int_port;
	new_conv_info->proto = hash_info->proto;

	conversation_add_proto_data(conversation, proto_msproxy,
		new_conv_info);
}
Пример #13
0
/*  A helper function that calls find_conversation() and, if a conversation is
 *  not found, calls conversation_new().
 *  The frame number and addresses are taken from pinfo.
 *  No options are used, though we could extend this API to include an options
 *  parameter.
 */
conversation_t *
find_or_create_conversation(packet_info *pinfo)
{
	conversation_t *conv=NULL;

	/* Have we seen this conversation before? */
	if((conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
				     pinfo->ptype, pinfo->srcport,
				     pinfo->destport, 0)) == NULL) {
		/* No, this is a new conversation. */
		conv = conversation_new(pinfo->fd->num, &pinfo->src,
					&pinfo->dst, pinfo->ptype,
					pinfo->srcport, pinfo->destport, 0);
	}

	return conv;
}
Пример #14
0
static lbttcp_client_transport_t * lbttcp_client_transport_add(lbttcp_transport_t * transport, const address * receiver_address, guint16 receiver_port, guint32 frame)
{
    lbttcp_client_transport_t * entry;
    conversation_t * client_conv = NULL;
    wmem_tree_t * session_tree = NULL;

    if (transport == NULL)
    {
        return (NULL);
    }
    entry = lbttcp_client_transport_find(transport, receiver_address, receiver_port, frame);
    if (entry != NULL)
    {
        return (entry);
    }
    entry = wmem_new(wmem_file_scope(), lbttcp_client_transport_t);
    copy_address_wmem(wmem_file_scope(), &(entry->receiver_address), receiver_address);
    entry->receiver_port = receiver_port;
    entry->id = transport->next_client_id++;

    /* See if a conversation for this address/port pair exists. */
    client_conv = find_conversation(frame, &(transport->source_address), receiver_address, PT_TCP, transport->source_port, receiver_port, 0);
    if (client_conv == NULL)
    {
        client_conv = conversation_new(frame, &(transport->source_address), receiver_address, PT_TCP, transport->source_port, receiver_port, 0);
        session_tree = wmem_tree_new(wmem_file_scope());
        conversation_add_proto_data(client_conv, proto_lbttcp, (void *) session_tree);
    }
    session_tree = (wmem_tree_t *) conversation_get_proto_data(client_conv, proto_lbttcp);
    if (session_tree == NULL)
    {
        session_tree = wmem_tree_new(wmem_file_scope());
        conversation_add_proto_data(client_conv, proto_lbttcp, (void *) session_tree);
    }
    wmem_tree_insert32(session_tree, transport->session_id, (void *) entry);

    /* Add this client to the transport. */
    wmem_list_append(transport->client_list, (void *) entry);
    return (entry);
}
Пример #15
0
static gboolean
dissect_tuxedo_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	if (tvb_length(tvb) >= 8)
	{
		guint32 magic;
		magic = tvb_get_ntohl(tvb, 0);
		if (magic == TUXEDO_MAGIC || magic == TUXEDO_SMAGIC) 
		{
			/* Register this dissector for this conversation */
			conversation_t  *conversation = NULL;
			conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
			if (conversation == NULL) 
			{
				conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
			}
			conversation_set_dissector(conversation, tuxedo_handle);

			dissect_tuxedo(tvb, pinfo, tree);
			return TRUE;
		}
	}
	return FALSE;
}
Пример #16
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;
    }
  } 
}
Пример #17
0
/*
 * Creates a new conversation with known endpoints based on a conversation
 * created with the CONVERSATION_TEMPLATE option while keeping the
 * conversation created with the CONVERSATION_TEMPLATE option so it can still
 * match future connections.
 *
 * Passing a pointer to a conversation whose options mask does not include
 * CONVERSATION_TEMPLATE or where the conversation's protocol type (ptype)
 * indicates a non-connnection oriented protocol will return the conversation
 * without changes.
 *
 * addr2 and port2 are used in the function if their respective conversation
 * options bits are set (NO_ADDR2 and NO_PORT2).
 */
static conversation_t *
conversation_create_from_template(conversation_t *conversation, const address *addr2, const guint32 port2)
{
   /*
    * Add a new conversation and keep the conversation template only if the
    * CONVERSATION_TEMPLATE bit is set for a connection oriented protocol.
    */
   if(conversation->options & CONVERSATION_TEMPLATE &&
      conversation->key_ptr->ptype != PT_UDP)
   {
      /*
       * Set up a new options mask where the conversation template bit and the
       * bits for absence of a second address and port pair have been removed.
       */
      conversation_t *new_conversation_from_template;
      guint options = conversation->options & ~(CONVERSATION_TEMPLATE | NO_ADDR2 | NO_PORT2);

      /*
       * Are both the NO_ADDR2 and NO_PORT2 wildcards set in the options mask?
       */
      if(conversation->options & NO_ADDR2 &&
         conversation->options & NO_PORT2)
      {
         /*
          * The conversation template was created without knowledge of both
          * the second address as well as the second port. Create a new
          * conversation with new 2nd address and 2nd port.
          */
         new_conversation_from_template =
            conversation_new(conversation->setup_frame,
                             &conversation->key_ptr->addr1, addr2,
                             conversation->key_ptr->ptype, conversation->key_ptr->port1,
                             port2, options);
      }
      else if(conversation->options & NO_PORT2)
      {
         /*
          * The conversation template was created without knowledge of port 2
          * only. Create a new conversation with new 2nd port.
          */
         new_conversation_from_template =
            conversation_new(conversation->setup_frame,
                             &conversation->key_ptr->addr1, &conversation->key_ptr->addr2,
                             conversation->key_ptr->ptype, conversation->key_ptr->port1,
                             port2, options);
      }
      else if(conversation->options & NO_ADDR2)
      {
         /*
          * The conversation template was created without knowledge of address
          * 2. Create a new conversation with new 2nd address.
          */
         new_conversation_from_template =
            conversation_new(conversation->setup_frame,
                             &conversation->key_ptr->addr1, addr2,
                             conversation->key_ptr->ptype, conversation->key_ptr->port1,
                             conversation->key_ptr->port2, options);
      }
      else
      {
         /*
          * The CONVERSATION_TEMPLATE bit was set, but no other bit that the
          * CONVERSATION_TEMPLATE bit controls is active. Just return the old
          * conversation.
          */
         return conversation;
      }

      /*
       * Set the protocol dissector used for the template conversation as
       * the handler of the new conversation as well.
       */
      new_conversation_from_template->dissector_handle = conversation->dissector_handle;

      return new_conversation_from_template;
   }
   else
   {
      return conversation;
   }
}
Пример #18
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;
	}
}
Пример #19
0
static void
dissect_fcfcs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

/* Set up structures needed to add the protocol subtree and manage it */
    int offset = 0;
    proto_item *ti;
    proto_tree *fcfcs_tree = NULL;
    fc_ct_preamble cthdr;
    gboolean isreq = 1;
    conversation_t *conversation;
    fcfcs_conv_data_t *cdata;
    fcfcs_conv_key_t ckey, *req_key;
    int opcode,
        failed_opcode = 0;

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

    if (tree) {
        ti = proto_tree_add_protocol_format (tree, proto_fcfcs, tvb, 0,
                                             tvb_reported_length (tvb),
                                             "FCS");
        fcfcs_tree = proto_item_add_subtree (ti, ett_fcfcs);
    }

    tvb_memcpy (tvb, (guint8 *)&cthdr, offset, FCCT_PRMBL_SIZE);
    cthdr.revision = tvb_get_guint8 (tvb, offset);
    cthdr.in_id = tvb_get_ntoh24 (tvb, offset+1);
    cthdr.opcode = g_ntohs (cthdr.opcode);
    opcode = tvb_get_ntohs (tvb, offset+8);
    cthdr.maxres_size = g_ntohs (cthdr.maxres_size);

    if ((opcode != FCCT_MSG_ACC) && (opcode != FCCT_MSG_RJT)) {
        conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
                                          pinfo->ptype, pinfo->oxid,
                                          pinfo->rxid, NO_PORT2);
        if (!conversation) {
            conversation = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst,
                                             pinfo->ptype, pinfo->oxid,
                                             pinfo->rxid, NO_PORT2);
        }

        ckey.conv_idx = conversation->index;

        cdata = (fcfcs_conv_data_t *)g_hash_table_lookup (fcfcs_req_hash,
                                                            &ckey);
        if (cdata) {
            /* Since we never free the memory used by an exchange, this maybe a
             * case of another request using the same exchange as a previous
             * req.
             */
            cdata->opcode = opcode;
        }
        else {
            req_key = se_alloc (sizeof(fcfcs_conv_key_t));
            req_key->conv_idx = conversation->index;

            cdata = se_alloc (sizeof(fcfcs_conv_data_t));
            cdata->opcode = opcode;

            g_hash_table_insert (fcfcs_req_hash, req_key, cdata);
        }
        if (check_col (pinfo->cinfo, COL_INFO)) {
            col_add_str (pinfo->cinfo, COL_INFO,
                         val_to_str (opcode, fc_fcs_opcode_abbrev_val, "0x%x"));
        }
    }
    else {
        /* Opcode is ACC or RJT */
        conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
                                          pinfo->ptype, pinfo->oxid,
                                          pinfo->rxid, NO_PORT2);
        isreq = 0;
        if (!conversation) {
            if (tree && (opcode == FCCT_MSG_ACC)) {
                if (check_col (pinfo->cinfo, COL_INFO)) {
                    col_add_str (pinfo->cinfo, COL_INFO,
                                 val_to_str (opcode, fc_fcs_opcode_abbrev_val,
                                             "0x%x"));
                }
                /* No record of what this accept is for. Can't decode */
                proto_tree_add_text (fcfcs_tree, tvb, 0, tvb_length (tvb),
                                     "No record of Exchg. Unable to decode MSG_ACC/RJT");
                return;
            }
        }
        else {
            ckey.conv_idx = conversation->index;

            cdata = (fcfcs_conv_data_t *)g_hash_table_lookup (fcfcs_req_hash,
                                                              &ckey);

            if (cdata != NULL) {
                if (opcode == FCCT_MSG_ACC)
                    opcode = cdata->opcode;
                else
                    failed_opcode = cdata->opcode;
            }

            if (check_col (pinfo->cinfo, COL_INFO)) {
                if (opcode != FCCT_MSG_RJT) {
                    col_add_fstr (pinfo->cinfo, COL_INFO, "MSG_ACC (%s)",
                                  val_to_str (opcode, fc_fcs_opcode_abbrev_val,
                                              "0x%x"));
                }
                else {
                    col_add_fstr (pinfo->cinfo, COL_INFO, "MSG_RJT (%s)",
                                  val_to_str (failed_opcode,
                                              fc_fcs_opcode_abbrev_val,
                                              "0x%x"));
                }
            }

            if (tree) {
                if ((cdata == NULL) && (opcode != FCCT_MSG_RJT)) {
                    /* No record of what this accept is for. Can't decode */
                    proto_tree_add_text (fcfcs_tree, tvb, 0, tvb_length (tvb),
                                         "No record of Exchg. Unable to decode MSG_ACC/RJT");
                    return;
                }
            }
        }
    }


    if (tree) {
        proto_tree_add_item (fcfcs_tree, hf_fcs_opcode, tvb, offset+8, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item (fcfcs_tree, hf_fcs_maxres_size, tvb, offset+10,
                             2, ENC_BIG_ENDIAN);
    }

    switch (opcode) {
    case FCCT_MSG_RJT:
        dissect_fcfcs_rjt (tvb, fcfcs_tree);
        break;
    case FCFCS_GIEL:
        dissect_fcfcs_giel (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GIET:
        dissect_fcfcs_giet (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GDID:
        dissect_fcfcs_gdid (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GMID:
        dissect_fcfcs_gmid (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GFN:
        dissect_fcfcs_gfn (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GIELN:
        dissect_fcfcs_gieln (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GMAL:
        dissect_fcfcs_gmal (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GIEIL:
        dissect_fcfcs_gieil (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GPL:
        dissect_fcfcs_gpl (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GPT:
        dissect_fcfcs_gpt (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GPPN:
        dissect_fcfcs_gppn (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GAPNL:
        dissect_fcfcs_gapnl (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GPS:
        dissect_fcfcs_gps (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GPLNL:
        dissect_fcfcs_gplnl (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GPLT:
        dissect_fcfcs_gplt (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GPLML:
        dissect_fcfcs_gplml (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GNPL:
        dissect_fcfcs_gnpl (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GPNL:
        dissect_fcfcs_gpnl (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_RIELN:
        dissect_fcfcs_rieln (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_RPL:
        dissect_fcfcs_rpl (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_RPLN:
        dissect_fcfcs_rpln (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_RPLT:
        dissect_fcfcs_rplt (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_RPLM:
        dissect_fcfcs_rplm (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_DPL:
        dissect_fcfcs_dpl (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_DPLN:
        dissect_fcfcs_dpln (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_DPLML:
        dissect_fcfcs_dplml (tvb, fcfcs_tree, isreq);
        break;
    case FCFCS_GCAP:
        dissect_fcfcs_gcap (tvb, fcfcs_tree, isreq);
        break;
    default:
        call_dissector (data_handle, tvb, pinfo, fcfcs_tree);
        break;
    }
}
Пример #20
0
static void
dissect_exec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	/* Set up structures needed to add the protocol subtree and manage it */
	proto_item *ti;
	proto_tree *exec_tree=NULL;

	/* Variables for extracting and displaying data from the packet */
	guchar *field_stringz; /* Temporary storage for each field we extract */

	gint length;
	guint offset = 0;
	conversation_t *conversation;
	exec_hash_entry_t *hash_info;

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

	if(!conversation){  /* Conversation does not exist yet - create it */
		conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
	}


	/* Retrieve information from conversation 
	 * or add it if it isn't there yet
	 */
	hash_info = conversation_get_proto_data(conversation, proto_exec);
	if(!hash_info){
		hash_info = se_alloc(sizeof(exec_hash_entry_t));
      
		hash_info->first_packet_number = pinfo->fd->num;
		hash_info->second_packet_number = 0;
		hash_info->third_packet_number  = 0;
		hash_info->fourth_packet_number  = 0;

		hash_info->state = WAIT_FOR_STDERR_PORT; /* The first field we'll see */

		/* Start with empty username and command strings */
		hash_info->username=NULL;
		hash_info->command=NULL;

		/* These will be set on the first pass by the first 
		 * four packets of the conversation
		 */
		hash_info->first_packet_state  = NONE;
		hash_info->second_packet_state = NONE;
		hash_info->third_packet_state  = NONE;
		hash_info->fourth_packet_state  = NONE;

		conversation_add_proto_data(conversation, proto_exec, hash_info);
	}

	/* Store the number of the first three packets of this conversation
	 * as we reach them the first time */

	if(!hash_info->second_packet_number
	&& pinfo->fd->num > hash_info->first_packet_number){
		/* We're on the second packet of the conversation */
		hash_info->second_packet_number = pinfo->fd->num;
	} else if(hash_info->second_packet_number
	 && !hash_info->third_packet_number
	 && pinfo->fd->num > hash_info->second_packet_number) {
		/* We're on the third packet of the conversation */
		hash_info->third_packet_number = pinfo->fd->num;
	} else if(hash_info->third_packet_number
	 && !hash_info->fourth_packet_number
	 && pinfo->fd->num > hash_info->third_packet_number) {
		/* We're on the fourth packet of the conversation */
		hash_info->fourth_packet_number = pinfo->fd->num;
	}

	/* Save this packet's state so we can retrieve it if this packet
	 * is selected again later.  If the packet's state was already stored,
	 * then retrieve it */
	if(pinfo->fd->num == hash_info->first_packet_number){
		if(hash_info->first_packet_state == NONE){
			hash_info->first_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->first_packet_state;
		}
	}
      
	if(pinfo->fd->num == hash_info->second_packet_number){
		if(hash_info->second_packet_state == NONE){
			hash_info->second_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->second_packet_state;
		}
	}
      
	if(pinfo->fd->num == hash_info->third_packet_number){
		if(hash_info->third_packet_state == NONE){
			hash_info->third_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->third_packet_state;
		}
	}
      
	if(pinfo->fd->num == hash_info->fourth_packet_number){
		if(hash_info->fourth_packet_state == NONE){
			hash_info->fourth_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->fourth_packet_state;
		}
	}

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

	if(check_col(pinfo->cinfo, COL_INFO)){
		/* First, clear the info column */
		col_clear(pinfo->cinfo, COL_INFO);

		/*username */
		if(hash_info->username && preference_info_show_username == TRUE){
			col_append_fstr(pinfo->cinfo, COL_INFO, "Username:%s ", hash_info->username);
		}
      
		/* Command */
		if(hash_info->command && preference_info_show_command == TRUE){
			col_append_fstr(pinfo->cinfo, COL_INFO, "Command:%s ", hash_info->command);
		}
	}
  
	/* create display subtree for the protocol */
	ti = proto_tree_add_item(tree, proto_exec, tvb, 0, -1, FALSE);
	exec_tree = proto_item_add_subtree(ti, ett_exec);

	/* If this packet doesn't end with a null terminated string,
	 * then it must be session data only and we can skip looking
	 * for the other fields.
	 */
	if(tvb_find_guint8(tvb, tvb_length(tvb)-1, 1, '\0') == -1){
		hash_info->state = WAIT_FOR_DATA;
	}

	if(hash_info->state == WAIT_FOR_STDERR_PORT
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length);

		/* Check if this looks like the stderr_port field.
		 * It is optional, so it may only be 1 character long
		 * (the NULL)
		 */
		if(length == 1 || (exec_isdigit_string(field_stringz)
		&& length <= EXEC_STDERR_PORT_LEN)){
			proto_tree_add_string(exec_tree, hf_exec_stderr_port, tvb, offset, length, (gchar*)field_stringz);
			 /* Next field we need */
			hash_info->state = WAIT_FOR_USERNAME;
		} else { 
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}
       
		/* Used if the next field is in the same packet */
		offset += length;
	}
  
 
	if(hash_info->state == WAIT_FOR_USERNAME
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length);
	  
		/* Check if this looks like the username field */
		if(length != 1 && length <= EXEC_USERNAME_LEN
		&& exec_isprint_string(field_stringz)){
			proto_tree_add_string(exec_tree, hf_exec_username, tvb, offset, length, (gchar*)field_stringz);

			/* Store the username so we can display it in the 
			 * info column of the entire conversation
			 */
			if(!hash_info->username){
				hash_info->username=se_strdup((gchar*)field_stringz);
			}

			 /* Next field we need */
			hash_info->state = WAIT_FOR_PASSWORD;
		} else { 
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}
 
		/* Used if the next field is in the same packet */
		offset += length;
	}
      

	if(hash_info->state == WAIT_FOR_PASSWORD
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length);
	  
		/* Check if this looks like the password field */
		if(length != 1 && length <= EXEC_PASSWORD_LEN
		&& exec_isprint_string(field_stringz)){
			proto_tree_add_string(exec_tree, hf_exec_password, tvb, offset, length, (gchar*)field_stringz);

			/* Next field we need */
			hash_info->state = WAIT_FOR_COMMAND;
		} else {
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}
	  
		/* Used if the next field is in the same packet */
		offset += length;
		 /* Next field we are looking for */
		hash_info->state = WAIT_FOR_COMMAND;
	}
      

	if(hash_info->state == WAIT_FOR_COMMAND
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length);
	  
		/* Check if this looks like the command field */
		if(length != 1 && length <= EXEC_COMMAND_LEN
		&& exec_isprint_string(field_stringz)){
			proto_tree_add_string(exec_tree, hf_exec_command, tvb, offset, length, (gchar*)field_stringz);
	      
			/* Store the username so we can display it in the 
			 * info column of the entire conversation
			 */
			if(!hash_info->command){
				hash_info->command=se_strdup((gchar*)field_stringz);
			}

		} else {
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}
	}

  
	if(hash_info->state == WAIT_FOR_DATA
	&& tvb_length_remaining(tvb, offset)){
		if(pinfo->destport == EXEC_PORT){
			/* Packet going to the server */
			/* offset = 0 since the whole packet is data */
			proto_tree_add_text(exec_tree, tvb, 0, -1, "Client -> Server Data");
	  
			if(check_col(pinfo->cinfo, COL_INFO))
				col_append_str(pinfo->cinfo, COL_INFO, "Client -> Server data");
		} else {
			/* This packet must be going back to the client */
			/* offset = 0 since the whole packet is data */
			proto_tree_add_text(exec_tree, tvb, 0, -1, "Server -> Client Data");
	  
			if(check_col(pinfo->cinfo, COL_INFO))
				col_append_str(pinfo->cinfo, COL_INFO, "Server -> Client Data");
		}
	}

	/* We haven't seen all of the fields yet */
	if(hash_info->state < WAIT_FOR_DATA){
		col_set_str(pinfo->cinfo, COL_INFO, "Session Establishment");
	}
}
Пример #21
0
static void
dissect_beep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  int offset;
  struct beep_proto_data  *beep_frame_data = NULL;
  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 = p_get_proto_data(pinfo->fd, proto_beep);

  if (!beep_frame_data) {

    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);

      }

      /*
       * 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 = se_alloc(sizeof(struct beep_request_key));
	new_request_key->conversation = conversation->index;

	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");

  if (check_col(pinfo->cinfo, COL_INFO)) {  /* Check the type ... */

    /* "tvb_format_text()" is passed a value that won't go past the end
     * of the packet, so it won't throw an exception. */
    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, FALSE);

    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 && beep_frame_data->pl_left > 0) {

    int pl_left = beep_frame_data->pl_left;

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

    /* Add the payload bit, only if we have a tree */
    if (tree) {
      proto_tree_add_text(beep_tree, tvb, offset, pl_left, "Payload: %s",
			  tvb_format_text(tvb, offset, pl_left));
    }
    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_alloc(sizeof(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);

  }

  /* Set up the per-frame data here if not already done so
   * This _must_ come after the checks above ...
   */

  if (beep_frame_data == NULL) {

    beep_frame_data = se_alloc(sizeof(struct beep_proto_data));

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

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

  }

  if (tvb_length_remaining(tvb, offset) > 0) {

    offset += dissect_beep_tree(tvb, offset, pinfo, beep_tree, request_val, beep_frame_data);

  }

}
Пример #22
0
static void
dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
    gboolean is_tcp)
{
    proto_tree            *ncp_tree = NULL;
    proto_item            *ti;
    struct ncp_ip_header  ncpiph;
    struct ncp_ip_rqhdr   ncpiphrq;
    guint16               ncp_burst_seqno, ncp_ack_seqno;
    guint16               flags = 0;
    proto_tree            *flags_tree = NULL;
    int                   hdr_offset = 0;
    int                   commhdr = 0;
    int                   offset = 0;
    gint                  length_remaining;
    tvbuff_t              *next_tvb;
    guint32               testvar = 0, ncp_burst_command, burst_len, burst_off, burst_file;
    guint8                subfunction;
    guint32               nw_connection = 0, data_offset;
    guint16               data_len = 0;
    guint16               missing_fraglist_count = 0;
    mncp_rhash_value      *request_value = NULL;
    conversation_t        *conversation;
    proto_item            *expert_item;

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

    ncp_hdr = &header;

    ti = proto_tree_add_item(tree, proto_ncp, tvb, 0, -1, ENC_NA);
    ncp_tree = proto_item_add_subtree(ti, ett_ncp);
    if (is_tcp) {
        if (tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RQST && tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RPLY)
            commhdr += 1;
        /* Get NCPIP Header data */
        ncpiph.signature = tvb_get_ntohl(tvb, commhdr);
        proto_tree_add_uint(ncp_tree, hf_ncp_ip_sig, tvb, commhdr, 4, ncpiph.signature);
        ncpiph.length = (0x7fffffff & tvb_get_ntohl(tvb, commhdr+4));
        proto_tree_add_uint(ncp_tree, hf_ncp_ip_length, tvb, commhdr+4, 4, ncpiph.length);
        commhdr += 8;
        if (ncpiph.signature == NCPIP_RQST) {
            ncpiphrq.version = tvb_get_ntohl(tvb, commhdr);
            proto_tree_add_uint(ncp_tree, hf_ncp_ip_ver, tvb, commhdr, 4, ncpiphrq.version);
            commhdr += 4;
            ncpiphrq.rplybufsize = tvb_get_ntohl(tvb, commhdr);
            proto_tree_add_uint(ncp_tree, hf_ncp_ip_rplybufsize, tvb, commhdr, 4, ncpiphrq.rplybufsize);
            commhdr += 4;
        }
        /* Check to see if this is a valid offset, otherwise increment for packet signature */
        if (try_val_to_str(tvb_get_ntohs(tvb, commhdr), ncp_type_vals)==NULL) {
            /* Check to see if we have a valid type after packet signature length */
            if (try_val_to_str(tvb_get_ntohs(tvb, commhdr+8), ncp_type_vals)!=NULL) {
                proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, commhdr, 8, ENC_NA);
                commhdr += 8;
            }
        }
    } else {
        /* Initialize this structure, we use it below */
        memset(&ncpiph, 0, sizeof(ncpiph));
    }

    header.type         = tvb_get_ntohs(tvb, commhdr);
    header.sequence     = tvb_get_guint8(tvb, commhdr+2);
    header.conn_low     = tvb_get_guint8(tvb, commhdr+3);
    header.task         = tvb_get_guint8(tvb, commhdr+4);
    header.conn_high    = tvb_get_guint8(tvb, commhdr+5);
    proto_tree_add_uint(ncp_tree, hf_ncp_type, tvb, commhdr, 2, header.type);
    nw_connection = (header.conn_high*256)+header.conn_low;

    /* Ok, we need to track the conversation so that we can
     * determine if a new server session is occuring for this
     * connection.
     */
    conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
        PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport,
        0);
    if ((ncpiph.length & 0x80000000) || ncpiph.signature == NCPIP_RPLY) {
        /* First time through we will record the initial connection and task
         * values
         */
        if (!pinfo->fd->flags.visited) {
            if (conversation != NULL) {
                /* find the record telling us the
                 * request made that caused this
                 * reply
                 */
                request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
                /* if for some reason we have no
                 * conversation in our hash, create
                 * one */
                if (request_value == NULL) {
                    mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
                }
            } else {
                /* It's not part of any conversation
                 * - create a new one.
                 */
                conversation = conversation_new(pinfo->fd->num, &pinfo->src,
                    &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
                mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
            }
            /* If this is a request packet then we
             * might have a new task
             */
            if (ncpiph.signature == NCPIP_RPLY) {
                /* Now on reply packets we have to
                 * use the state of the original
                 * request packet, so look up the
                 * request value and check the task number
                 */
                /*request_value = mncp_hash_lookup(conversation, nw_connection, header.task);*/
            }
        } else {
            /* Get request value data */
            request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
            if (request_value) {
                if ((request_value->session_start_packet_num == pinfo->fd->num) && ncp_echo_conn) {
                    expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
                }
            }
        }
    } else {
        if (!pinfo->fd->flags.visited) {
            if (conversation != NULL) {
                /* find the record telling us the
                 * request made that caused this
                 * reply
                 */
                request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
                /* if for some reason we have no
                 * conversation in our hash, create
                 * one */
                if (request_value == NULL) {
                    mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
                }
            } else {
                /* It's not part of any conversation
                 * - create a new one.
                 */
                conversation = conversation_new(pinfo->fd->num, &pinfo->src,
                    &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
                mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
            }
            /* find the record telling us the request
             * made that caused this reply
             */
        } else {
            request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
            if (request_value) {
                if ((request_value->session_start_packet_num == pinfo->fd->num) && ncp_echo_conn) {
                    expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
                }
            }
        }
    }

    tap_queue_packet(ncp_tap.hdr, pinfo, ncp_hdr);

    col_add_str(pinfo->cinfo, COL_INFO,
        val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)"));

    /*
     * Process the packet-type-specific header.
     */
    switch (header.type) {

    case NCP_BROADCAST_SLOT:    /* Server Broadcast */
        proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
        proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
        proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_oplock_flag, tvb, commhdr + 9, 1, tvb_get_guint8(tvb, commhdr+9));
        proto_tree_add_item(ncp_tree, hf_ncp_oplock_handle, tvb, commhdr + 10, 4, ENC_BIG_ENDIAN);
        if ((tvb_get_guint8(tvb, commhdr+9)==0x24) && ncp_echo_file) {
            expert_add_info_format(pinfo, NULL, &ei_ncp_oplock_handle, "Server requesting station to clear oplock on handle - %08x", tvb_get_ntohl(tvb, commhdr+10));
        }
        break;

    case NCP_LIP_ECHO:    /* Lip Echo Packet */
        proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr, 13, ENC_ASCII|ENC_NA);
        break;

    case NCP_BURST_MODE_XFER:    /* Packet Burst Packet */
        /*
         * XXX - we should keep track of whether there's a burst
         * outstanding on a connection and, if not, treat the
         * beginning of the data as a burst header.
         *
         * The burst header contains:
         *
         *    4 bytes of little-endian function number:
         *        1 = read, 2 = write;
         *
         *    4 bytes of file handle;
         *
         *    8 reserved bytes;
         *
         *    4 bytes of big-endian file offset;
         *
         *    4 bytes of big-endian byte count.
         *
         * The data follows for a burst write operation.
         *
         * The first packet of a burst read reply contains:
         *
         *    4 bytes of little-endian result code:
         *       0: No error
         *       1: Initial error
         *       2: I/O error
         *       3: No data read;
         *
         *    4 bytes of returned byte count (big-endian?).
         *
         * The data follows.
         *
         * Each burst of a write request is responded to with a
         * burst packet with a 2-byte little-endian result code:
         *
         *    0: Write successful
         *    4: Write error
         */
        flags = tvb_get_guint8(tvb, commhdr + 2);

        ti = proto_tree_add_uint(ncp_tree, hf_ncp_system_flags,
            tvb, commhdr + 2, 1, flags);
        flags_tree = proto_item_add_subtree(ti, ett_ncp_system_flags);

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_abt,
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
        if (flags & ABT) {
            proto_item_append_text(ti, "  ABT");
        }
        flags&=(~( ABT ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_bsy,
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
        if (flags & BSY) {
            proto_item_append_text(ti, "  BSY");
        }
        flags&=(~( BSY ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_eob,
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
        if (flags & EOB) {
            proto_item_append_text(ti, "  EOB");
        }
        flags&=(~( EOB ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_lst,
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
        if (flags & LST) {
            proto_item_append_text(ti, "  LST");
        }
        flags&=(~( LST ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_sys,
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
        if (flags & SYS) {
            proto_item_append_text(ti, "  SYS");
        }
        flags&=(~( SYS ));


        proto_tree_add_item(ncp_tree, hf_ncp_stream_type,
            tvb, commhdr + 3, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_src_connection,
            tvb, commhdr + 4, 4, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_dst_connection,
            tvb, commhdr + 8, 4, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_packet_seqno,
            tvb, commhdr + 12, 4, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_delay_time,
            tvb, commhdr + 16, 4, ENC_BIG_ENDIAN);
        ncp_burst_seqno = tvb_get_ntohs(tvb, commhdr+20);
        proto_tree_add_item(ncp_tree, hf_ncp_burst_seqno,
            tvb, commhdr + 20, 2, ENC_BIG_ENDIAN);
        ncp_ack_seqno = tvb_get_ntohs(tvb, commhdr+22);
        proto_tree_add_item(ncp_tree, hf_ncp_ack_seqno,
            tvb, commhdr + 22, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_burst_len,
            tvb, commhdr + 24, 4, ENC_BIG_ENDIAN);
        data_offset = tvb_get_ntohl(tvb, commhdr + 28);
        proto_tree_add_uint(ncp_tree, hf_ncp_data_offset,
            tvb, commhdr + 28, 4, data_offset);
        data_len = tvb_get_ntohs(tvb, commhdr + 32);
        proto_tree_add_uint(ncp_tree, hf_ncp_data_bytes,
            tvb, commhdr + 32, 2, data_len);
        missing_fraglist_count = tvb_get_ntohs(tvb, commhdr + 34);
        proto_tree_add_item(ncp_tree, hf_ncp_missing_fraglist_count,
            tvb, commhdr + 34, 2, ENC_BIG_ENDIAN);
        offset = commhdr + 36;
        if (!(flags & SYS) && ncp_burst_seqno == ncp_ack_seqno &&
            data_offset == 0) {
            /*
             * This is either a Burst Read or Burst Write
             * command.  The data length includes the burst
             * mode header, plus any data in the command
             * (there shouldn't be any in a read, but there
             * might be some in a write).
             */
            if (data_len < 4)
                return;
            ncp_burst_command = tvb_get_ntohl(tvb, offset);
            proto_tree_add_item(ncp_tree, hf_ncp_burst_command,
                tvb, offset, 4, ENC_BIG_ENDIAN);
            offset += 4;
            data_len -= 4;

            if (data_len < 4)
                return;
            burst_file = tvb_get_ntohl(tvb, offset);
            proto_tree_add_item(ncp_tree, hf_ncp_burst_file_handle,
                tvb, offset, 4, ENC_BIG_ENDIAN);
            offset += 4;
            data_len -= 4;

            if (data_len < 8)
                return;
            proto_tree_add_item(ncp_tree, hf_ncp_burst_reserved,
                tvb, offset, 8, ENC_NA);
            offset += 8;
            data_len -= 8;

            if (data_len < 4)
                return;
            burst_off = tvb_get_ntohl(tvb, offset);
            proto_tree_add_uint(ncp_tree, hf_ncp_burst_offset,
                tvb, offset, 4, burst_off);
            offset += 4;
            data_len -= 4;

            if (data_len < 4)
                return;
            burst_len = tvb_get_ntohl(tvb, offset);
            proto_tree_add_uint(ncp_tree, hf_ncp_burst_len,
                tvb, offset, 4, burst_len);
            offset += 4;
            data_len -= 4;

            col_add_fstr(pinfo->cinfo, COL_INFO,
                "%s %d bytes starting at offset %d in file 0x%08x",
                val_to_str(ncp_burst_command,
                    burst_command, "Unknown (0x%08x)"),
                    burst_len, burst_off, burst_file);
            break;
        } else {
            if (tvb_get_guint8(tvb, commhdr + 2) & 0x10) {
                col_set_str(pinfo->cinfo, COL_INFO, "End of Burst");
            }
        }
        break;

    case NCP_ALLOCATE_SLOT:        /* Allocate Slot Request */
        length_remaining = tvb_length_remaining(tvb, commhdr + 4);
        if (length_remaining > 4) {
            testvar = tvb_get_ntohl(tvb, commhdr+4);
            if (testvar == 0x4c495020) {
                proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr+4, 13, ENC_ASCII|ENC_NA);
                break;
            }
        }
        /* otherwise fall through */

    case NCP_POSITIVE_ACK:        /* Positive Acknowledgement */
    case NCP_SERVICE_REQUEST:    /* Server NCP Request */
    case NCP_SERVICE_REPLY:        /* Server NCP Reply */
    case NCP_WATCHDOG:        /* Watchdog Packet */
    case NCP_DEALLOCATE_SLOT:    /* Deallocate Slot Request */
    default:
        proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
        proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
        proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, ENC_BIG_ENDIAN);
        break;
    }

    /*
     * Process the packet body.
     */
    switch (header.type) {

    case NCP_ALLOCATE_SLOT:        /* Allocate Slot Request */
        length_remaining = tvb_length_remaining(tvb, commhdr + 4);
        if (length_remaining > 4) {
            testvar = tvb_get_ntohl(tvb, commhdr+4);
            if (testvar == 0x4c495020) {
                proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
                    "Lip Echo Packet");
                /*break;*/
            }
        }
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        dissect_ncp_request(next_tvb, pinfo, nw_connection,
            header.sequence, header.type, ncp_tree);
        break;

    case NCP_DEALLOCATE_SLOT:    /* Deallocate Slot Request */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        dissect_ncp_request(next_tvb, pinfo, nw_connection,
            header.sequence, header.type, ncp_tree);
        break;

    case NCP_SERVICE_REQUEST:    /* Server NCP Request */
    case NCP_BROADCAST_SLOT:    /* Server Broadcast Packet */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        if (tvb_get_guint8(tvb, commhdr+6) == 0x68) {
            subfunction = tvb_get_guint8(tvb, commhdr+7);
            switch (subfunction) {

            case 0x02:    /* NDS Frag Packet to decode */
                dissect_nds_request(next_tvb, pinfo,
                    nw_connection, header.sequence,
                    header.type, ncp_tree);
                break;

            case 0x01:    /* NDS Ping */
                dissect_ping_req(next_tvb, pinfo,
                    nw_connection, header.sequence,
                    header.type, ncp_tree);
                break;

            default:
                dissect_ncp_request(next_tvb, pinfo,
                    nw_connection, header.sequence,
                    header.type, ncp_tree);
                break;
             }
        } else {
            dissect_ncp_request(next_tvb, pinfo, nw_connection,
                header.sequence, header.type, ncp_tree);
        }
        break;

    case NCP_SERVICE_REPLY:        /* Server NCP Reply */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        nds_defrag(next_tvb, pinfo, nw_connection, header.sequence,
            header.type, ncp_tree, &ncp_tap);
        break;

    case NCP_POSITIVE_ACK:        /* Positive Acknowledgement */
        /*
         * XXX - this used to call "nds_defrag()", which would
         * clear out "frags".  Was that the right thing to
         * do?
         */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        dissect_ncp_reply(next_tvb, pinfo, nw_connection,
            header.sequence, header.type, ncp_tree, &ncp_tap);
        break;

    case NCP_WATCHDOG:        /* Watchdog Packet */
        /*
         * XXX - should the completion code be interpreted as
         * it is in "packet-ncp2222.inc"?  If so, this
         * packet should be handled by "dissect_ncp_reply()".
         */
        proto_tree_add_item(ncp_tree, hf_ncp_completion_code,
            tvb, commhdr + 6, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_connection_status,
            tvb, commhdr + 7, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_slot,
            tvb, commhdr + 8, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_control_code,
            tvb, commhdr + 9, 1, ENC_LITTLE_ENDIAN);
        /*
         * Display the rest of the packet as data.
         */
        if (tvb_offset_exists(tvb, commhdr + 10)) {
            call_dissector(data_handle,
                tvb_new_subset_remaining(tvb, commhdr + 10),
                pinfo, ncp_tree);
        }
        break;

    case NCP_BURST_MODE_XFER:    /* Packet Burst Packet */
        if (flags & SYS) {
            /*
             * System packet; show missing fragments if there
             * are any.
             */
            while (missing_fraglist_count != 0) {
                proto_tree_add_item(ncp_tree, hf_ncp_missing_data_offset,
                    tvb, offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                proto_tree_add_item(ncp_tree, hf_ncp_missing_data_count,
                    tvb, offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                missing_fraglist_count--;
            }
        } else {
            /*
             * XXX - do this by using -1 and -1 as the length
             * arguments to "tvb_new_subset()" and then calling
             * "tvb_set_reported_length()"?  That'll throw an
             * exception if "data_len" goes past the reported
             * length of the packet, but that's arguably a
             * feature in this case.
             */
            length_remaining = tvb_length_remaining(tvb, offset);
            if (length_remaining > data_len)
                length_remaining = data_len;
            if (data_len != 0) {
                call_dissector(data_handle,
                    tvb_new_subset(tvb, offset,
                    length_remaining, data_len),
                    pinfo, ncp_tree);
            }
        }
        break;

    case NCP_LIP_ECHO:        /* LIP Echo Packet */
        proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
            "Lip Echo Packet");
        break;

    default:
        expert_item = proto_tree_add_text(ncp_tree, tvb, commhdr + 6, -1,
            "%s packets not supported yet",
            val_to_str(header.type, ncp_type_vals,
                "Unknown type (0x%04x)"));
        if (ncp_echo_err) {
            expert_add_info_format(pinfo, expert_item, &ei_ncp_type, "%s packets not supported yet", val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)"));
        }
        break;
    }
}
Пример #23
0
/* Set up an T38 conversation */
void t38_add_address(packet_info *pinfo,
                     address *addr, int port,
                     int other_port,
                     const gchar *setup_method, guint32 setup_frame_number)
{
        address null_addr;
        conversation_t* p_conversation;
        t38_conv* p_conversation_data = NULL;

        /*
         * If this isn't the first time this packet has been processed,
         * we've already done this work, so we don't need to do it
         * again.
         */
        if ((pinfo->fd->flags.visited) || (t38_udp_handle == NULL))
        {
                return;
        }

        SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);

        /*
         * Check if the ip address and port combination is not
         * already registered as a conversation.
         */
        p_conversation = find_conversation( setup_frame_number, addr, &null_addr, PT_UDP, port, other_port,
                                NO_ADDR_B | (!other_port ? NO_PORT_B : 0));

        /*
         * If not, create a new conversation.
         */
        if ( !p_conversation || p_conversation->setup_frame != setup_frame_number) {
                p_conversation = conversation_new( setup_frame_number, addr, &null_addr, PT_UDP,
                                           (guint32)port, (guint32)other_port,
                                                                   NO_ADDR2 | (!other_port ? NO_PORT2 : 0));
        }

        /* Set dissector */
        conversation_set_dissector(p_conversation, t38_udp_handle);

        /*
         * Check if the conversation has data associated with it.
         */
        p_conversation_data = (t38_conv*)conversation_get_proto_data(p_conversation, proto_t38);

        /*
         * If not, add a new data item.
         */
        if ( ! p_conversation_data ) {
                /* Create conversation data */
                p_conversation_data = wmem_new(wmem_file_scope(), t38_conv);

                conversation_add_proto_data(p_conversation, proto_t38, p_conversation_data);
        }

        /*
         * Update the conversation data.
         */
        g_strlcpy(p_conversation_data->setup_method, setup_method, MAX_T38_SETUP_METHOD_SIZE);
        p_conversation_data->setup_frame_number = setup_frame_number;
		p_conversation_data->src_t38_info.reass_ID = 0;
		p_conversation_data->src_t38_info.reass_start_seqnum = -1;
		p_conversation_data->src_t38_info.reass_data_type = 0;
		p_conversation_data->src_t38_info.last_seqnum = -1;
		p_conversation_data->src_t38_info.packet_lost = 0;
		p_conversation_data->src_t38_info.burst_lost = 0;
		p_conversation_data->src_t38_info.time_first_t4_data = 0;


		p_conversation_data->dst_t38_info.reass_ID = 0;
		p_conversation_data->dst_t38_info.reass_start_seqnum = -1;
		p_conversation_data->dst_t38_info.reass_data_type = 0;
		p_conversation_data->dst_t38_info.last_seqnum = -1;
		p_conversation_data->dst_t38_info.packet_lost = 0;
		p_conversation_data->dst_t38_info.burst_lost = 0;
		p_conversation_data->dst_t38_info.time_first_t4_data = 0;
}
Пример #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);
        }
    }
}
Пример #25
0
static void
dissect_xyplex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*xyplex_tree = NULL;
	proto_item	*ti;
	conversation_t  *conversation;
	gint		offset = 0;

	guint8		prototype;
	guint8		padding;
	guint16		server_port;
	guint16		return_port;
	guint16		reserved;
	guint16		reply;

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

	if (tree) {
	  ti = proto_tree_add_item(tree, proto_xyplex, tvb, offset, -1, FALSE);
	  xyplex_tree = proto_item_add_subtree(ti, ett_xyplex);
	}

	if (pinfo->destport == UDP_PORT_XYPLEX) {
		/* This is a registration request from a Unix server
		 * to the Xyplex server.  The server_port indicates
		 * which Xyplex serial port is desired.  The
		 * return_port tells the Xyplex server what TCP port
		 * to open to the Unix server.
		 */
		prototype = tvb_get_guint8(tvb, offset);
		padding = tvb_get_guint8(tvb, offset+1);
		server_port = tvb_get_ntohs(tvb, offset+2);
		return_port = tvb_get_ntohs(tvb, offset+4);
		reserved = tvb_get_ntohs(tvb, offset+6);
		if (check_col(pinfo->cinfo, COL_INFO)) {
		  col_add_fstr(pinfo->cinfo, COL_INFO,
			  "Registration Request: %d Return: %d",
			  server_port, return_port);
		}
		if (tree) {
		  proto_tree_add_uint(xyplex_tree, hf_xyplex_type, tvb,
				    offset, 1, prototype);
		  proto_tree_add_uint(xyplex_tree, hf_xyplex_pad, tvb,
				    offset+1, 1, padding);
		  proto_tree_add_uint(xyplex_tree, hf_xyplex_server_port, tvb,
				    offset+2, 2, server_port);
		  proto_tree_add_uint(xyplex_tree, hf_xyplex_return_port, tvb,
				    offset+4, 2, return_port);
		  proto_tree_add_uint(xyplex_tree, hf_xyplex_reserved, tvb,
				    offset+6, 2, reserved);
		}
		offset += 8;

		/* Look for all future TCP conversations between the
		 * requestiong server and the Xyplex host using the
		 * return_port.
		 */
		conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
				  PT_TCP, return_port, 0, NO_PORT_B);
		if (conversation == NULL) {
		    conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
				    PT_TCP, return_port, 0, NO_PORT2);
		    conversation_set_dissector(conversation, xyplex_handle);
		}
		return;
	}

	if (pinfo->srcport == UDP_PORT_XYPLEX) {
		prototype = tvb_get_guint8(tvb, offset);
		padding = tvb_get_guint8(tvb, offset+1);
		reply = tvb_get_ntohs(tvb, offset+2);
		if (check_col(pinfo->cinfo, COL_INFO)) {
		  col_add_fstr(pinfo->cinfo, COL_INFO, "Registration Reply: %s",
			val_to_str(reply, xyplex_reg_vals, "Unknown (0x%02x)"));
		}
		if (tree) {
		  proto_tree_add_uint(xyplex_tree, hf_xyplex_type, tvb,
				    offset, 1, prototype);
		  proto_tree_add_uint(xyplex_tree, hf_xyplex_pad, tvb,
				    offset+1, 1, padding);
		  proto_tree_add_uint(xyplex_tree, hf_xyplex_reply, tvb,
				    offset+2, 2, reply);
		}
		offset += 4;
		return;
	}

	/*
	 * This must be the TCP data stream.  This will just be
	 * the raw data being transfered from the remote server
	 * and the Xyplex serial port.
	 */
	if (check_col(pinfo->cinfo, COL_INFO)) {
	  col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d Data",
		  pinfo->srcport, pinfo->destport);
	}
	if (tree) {
	  proto_tree_add_text(xyplex_tree, tvb, offset, -1,
		"Data (%d bytes)", tvb_reported_length_remaining(tvb, offset));
	}
}
Пример #26
0
/*
 * Function for the PANA PDU dissector.
 */
static void
dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

       proto_tree *pana_tree=NULL;
       proto_tree *avp_tree=NULL;
       proto_item *ti=NULL;
       proto_item *avp_item=NULL;
       tvbuff_t *avp_tvb;
       guint16 flags = 0;
       guint16 msg_type;
       gint16 msg_length;
       gint16 avp_length;
       guint32 session_id;
       guint32 seq_num;
       conversation_t *conversation;
       pana_conv_info_t *pana_info;
       pana_transaction_t *pana_trans;
       int offset = 0;


       /* Get message length, type and flags */
       msg_length = tvb_get_ntohs(tvb, 2);
       flags = tvb_get_ntohs(tvb, 4);
       msg_type = tvb_get_ntohs(tvb, 6);
       session_id = tvb_get_ntohl(tvb, 8);
       seq_num = tvb_get_ntohl(tvb, 12);
       avp_length = msg_length-16;

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

       if (check_col(pinfo->cinfo, COL_INFO)) {
               col_clear(pinfo->cinfo, COL_INFO);
               col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s-%s",
			    val_to_str(msg_type, msg_type_names, "Unknown (%d)"),
			    val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"));
       }

       /* Make the protocol tree */
       if (tree) {
               ti = proto_tree_add_item(tree, proto_pana, tvb, 0, -1, FALSE);
               pana_tree = proto_item_add_subtree(ti, ett_pana);
       }


       /*
        * We need to track some state for this protocol on a per conversation
        * basis so we can do neat things like request/response tracking
        */
       /*
        * Do we have a conversation for this connection?
        */
       conversation = find_conversation(pinfo->fd->num,
                                   &pinfo->src, &pinfo->dst,
                                   pinfo->ptype,
                                   pinfo->srcport, pinfo->destport, 0);
       if (conversation == NULL) {
             /* We don't yet have a conversation, so create one. */
             conversation = conversation_new(pinfo->fd->num,
                                   &pinfo->src, &pinfo->dst,
    	                    	   pinfo->ptype,
                                   pinfo->srcport, pinfo->destport, 0);
       }
       /*
        * Do we already have a state structure for this conv
        */
       pana_info = conversation_get_proto_data(conversation, proto_pana);
       if (!pana_info) {
               /* No.  Attach that information to the conversation, and add
                * it to the list of information structures.
                */
               pana_info = se_alloc(sizeof(pana_conv_info_t));
               pana_info->pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "pana_pdus");

               conversation_add_proto_data(conversation, proto_pana, pana_info);
       }
       if(!pinfo->fd->flags.visited){
               if(flags&PANA_FLAG_R){
                      /* This is a request */
                      pana_trans=se_alloc(sizeof(pana_transaction_t));
                      pana_trans->req_frame=pinfo->fd->num;
                      pana_trans->rep_frame=0;
                      pana_trans->req_time=pinfo->fd->abs_ts;
                      se_tree_insert32(pana_info->pdus, seq_num, (void *)pana_trans);
               } else {
                      pana_trans=se_tree_lookup32(pana_info->pdus, seq_num);
                      if(pana_trans){
                              pana_trans->rep_frame=pinfo->fd->num;
                      }
               }
       } else {
               pana_trans=se_tree_lookup32(pana_info->pdus, seq_num);
       }
       if(!pana_trans){
               /* create a "fake" pana_trans structure */
               pana_trans=ep_alloc(sizeof(pana_transaction_t));
               pana_trans->req_frame=0;
               pana_trans->rep_frame=0;
               pana_trans->req_time=pinfo->fd->abs_ts;
       }


       /* print state tracking in the tree */
       if(flags&PANA_FLAG_R){
               /* This is a request */
               if(pana_trans->rep_frame){
                       proto_item *it;

                       it=proto_tree_add_uint(pana_tree, hf_pana_response_in, tvb, 0, 0, pana_trans->rep_frame);
                       PROTO_ITEM_SET_GENERATED(it);
               }
       } else {
               /* This is a reply */
               if(pana_trans->req_frame){
                       proto_item *it;
                       nstime_t ns;

                       it=proto_tree_add_uint(pana_tree, hf_pana_response_to, tvb, 0, 0, pana_trans->req_frame);
                       PROTO_ITEM_SET_GENERATED(it);

                       nstime_delta(&ns, &pinfo->fd->abs_ts, &pana_trans->req_time);
                       it=proto_tree_add_time(pana_tree, hf_pana_time, tvb, 0, 0, &ns);
                       PROTO_ITEM_SET_GENERATED(it);
               }
       }



       /* Reserved field */
       proto_tree_add_item(pana_tree, hf_pana_reserved_type, tvb, offset, 2, FALSE);
       offset += 2;

       /* Length */
       proto_tree_add_item(pana_tree, hf_pana_length_type, tvb, offset, 2, FALSE);
       offset += 2;

       /* Flags */
       dissect_pana_flags(pana_tree, tvb, offset, flags);
       offset += 2;

       /* Message Type */
       proto_tree_add_uint_format_value(pana_tree, hf_pana_msg_type, tvb,
                           offset, 2, msg_type, "%s-%s (%d)",
                           val_to_str(msg_type, msg_type_names, "Unknown (%d)"),
			   val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"),
			   msg_type);
       offset += 2;

       /* Session ID */
       proto_tree_add_item(pana_tree, hf_pana_session_id, tvb, offset, 4, FALSE);
       offset += 4;

       /* Sequence Number */
       proto_tree_add_item(pana_tree, hf_pana_seqnumber, tvb, offset, 4, FALSE);
       offset += 4;

       /* AVPs */
       if(avp_length>0){
               avp_tvb = tvb_new_subset(tvb, offset, avp_length, avp_length);
               avp_item = proto_tree_add_text(pana_tree, tvb, offset, avp_length, "Attribute Value Pairs");
               avp_tree = proto_item_add_subtree(avp_item, ett_pana_avp);

               if (avp_tree != NULL) {
                       dissect_avps(avp_tvb, pinfo, avp_tree);
               }
        }
}
Пример #27
0
static void
dissect_ftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    gboolean        is_request;
    proto_tree     *ftp_tree          = NULL;
    proto_tree     *reqresp_tree      = NULL;
    proto_item     *ti, *hidden_item;
    gint            offset            = 0;
    const guchar   *line;
    guint32         code;
    gchar           code_str[4];
    gboolean        is_port_request   = FALSE;
    gboolean        is_pasv_response  = FALSE;
    gboolean        is_epasv_response = FALSE;
    gint            next_offset;
    int             linelen;
    int             tokenlen;
    const guchar   *next_token;
    guint32         pasv_ip;
    guint32         ftp_ip;
    guint16         ftp_port;
    address         ftp_ip_address;
    gboolean        ftp_nat;
    conversation_t *conversation;

    ftp_ip_address = pinfo->src;

    if (pinfo->match_uint == pinfo->destport)
        is_request = TRUE;
    else
        is_request = FALSE;

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

    /*
     * 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);

    /*
     * Put the first line from the buffer into the summary
     * (but leave out the line terminator).
     */
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
        is_request ? "Request" : "Response",
        format_text(line, linelen));

    if (tree) {
        ti = proto_tree_add_item(tree, proto_ftp, tvb, offset, -1, ENC_NA);
        ftp_tree = proto_item_add_subtree(ti, ett_ftp);

        if (is_request) {
            hidden_item = proto_tree_add_boolean(ftp_tree,
                hf_ftp_request, tvb, 0, 0, TRUE);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            hidden_item = proto_tree_add_boolean(ftp_tree,
                hf_ftp_response, tvb, 0, 0, FALSE);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
        } else {
            hidden_item = proto_tree_add_boolean(ftp_tree,
                hf_ftp_request, tvb, 0, 0, FALSE);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            hidden_item = proto_tree_add_boolean(ftp_tree,
                hf_ftp_response, tvb, 0, 0, TRUE);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
        }

        /*
         * Put the line into the protocol tree.
         */
        ti = proto_tree_add_text(ftp_tree, tvb, offset,
            next_offset - offset, "%s",
            tvb_format_text(tvb, offset, next_offset - offset));
        reqresp_tree = proto_item_add_subtree(ti, ett_ftp_reqresp);
    }

    if (is_request) {
        /*
         * Extract the first token, and, if there is a first
         * token, add it as the request.
         */
        tokenlen = get_token_len(line, line + linelen, &next_token);
        if (tokenlen != 0) {
            if (tree) {
                proto_tree_add_item(reqresp_tree,
                    hf_ftp_request_command, tvb, offset,
                    tokenlen, ENC_ASCII|ENC_NA);
            }
            if (strncmp(line, "PORT", tokenlen) == 0)
                is_port_request = TRUE;
        }
    } else {
        /*
         * This is a response; the response code is 3 digits,
         * followed by a space or hyphen, possibly followed by
         * text.
         *
         * If the line doesn't start with 3 digits, it's part of
         * a continuation.
         *
         * XXX - keep track of state in the first pass, and
         * treat non-continuation lines not beginning with digits
         * as errors?
         */
        if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1])
            && isdigit(line[2])) {
            /*
             * One-line reply, or first or last line
             * of a multi-line reply.
             */
            tvb_get_nstringz0(tvb, offset, sizeof(code_str), code_str);
            code = strtoul(code_str, NULL, 10);

            if (tree) {
                proto_tree_add_uint(reqresp_tree,
                    hf_ftp_response_code, tvb, offset, 3, code);
            }

            /*
             * See if it's a passive-mode response.
             *
             * XXX - does anybody do FOOBAR, as per RFC
             * 1639, or has that been supplanted by RFC 2428?
             */
            if (code == 227)
                is_pasv_response = TRUE;

            /*
             * Responses to EPSV command, as per RFC 2428
             * XXX - handle IPv6?
             */
            if (code == 229)
                is_epasv_response = TRUE;

            /*
             * Skip the 3 digits and, if present, the
             * space or hyphen.
             */
            if (linelen >= 4)
                next_token = line + 4;
            else
                next_token = line + linelen;
        } else {
            /*
             * Line doesn't start with 3 digits; assume it's
             * a line in the middle of a multi-line reply.
             */
            next_token = line;
        }
    }
    offset  += (gint) (next_token - line);
    linelen -= (int) (next_token - line);
    line     = next_token;

    if (tree) {
        /*
         * Add the rest of the first line as request or
         * reply data.
         */
        if (linelen != 0) {
            if (is_request) {
                proto_tree_add_item(reqresp_tree,
                    hf_ftp_request_arg, tvb, offset,
                    linelen, ENC_ASCII|ENC_NA);
            } else {
                proto_tree_add_item(reqresp_tree,
                    hf_ftp_response_arg, tvb, offset,
                    linelen, ENC_ASCII|ENC_NA);
            }
        }
        offset = next_offset;
    }

    /*
     * If this is a PORT request or a PASV response, handle it.
     */
    if (is_port_request) {
        if (parse_port_pasv(line, linelen, &ftp_ip, &ftp_port)) {
            if (tree) {
                proto_tree_add_ipv4(reqresp_tree,
                    hf_ftp_active_ip, tvb, 0, 0,
                    ftp_ip);
                proto_tree_add_uint(reqresp_tree,
                    hf_ftp_active_port, tvb, 0, 0,
                    ftp_port);
            }
            SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4, (const guint8 *)&ftp_ip);
            ftp_nat = !ADDRESSES_EQUAL(&pinfo->src, &ftp_ip_address);
            if (ftp_nat) {
                if (tree) {
                    proto_tree_add_boolean(
                        reqresp_tree,
                        hf_ftp_active_nat, tvb,
                        0, 0, ftp_nat);
                }
            }
        }
    }

    if (is_pasv_response) {
        if (linelen != 0) {
            /*
             * This frame contains a PASV response; set up a
             * conversation for the data.
             */
            if (parse_port_pasv(line, linelen, &pasv_ip, &ftp_port)) {
                if (tree) {
                    proto_tree_add_ipv4(reqresp_tree,
                        hf_ftp_pasv_ip, tvb, 0, 0, pasv_ip);
                    proto_tree_add_uint(reqresp_tree,
                        hf_ftp_pasv_port, tvb, 0, 0,
                        ftp_port);
                }
                SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4,
                    (const guint8 *)&pasv_ip);
                ftp_nat = !ADDRESSES_EQUAL(&pinfo->src, &ftp_ip_address);
                if (ftp_nat) {
                    if (tree) {
                        proto_tree_add_boolean(reqresp_tree,
                            hf_ftp_pasv_nat, tvb, 0, 0,
                            ftp_nat);
                    }
                }

                /*
                 * We use "ftp_ip_address", so that if
                 * we're NAT'd we look for the un-NAT'd
                 * connection.
                 *
                 * XXX - should this call to
                 * "find_conversation()" just use
                 * "ftp_ip_address" and "server_port", and
                 * wildcard everything else?
                 */
                conversation = find_conversation(pinfo->fd->num, &ftp_ip_address,
                    &pinfo->dst, PT_TCP, ftp_port, 0,
                    NO_PORT_B);
                if (conversation == NULL) {
                    /*
                     * XXX - should this call to "conversation_new()"
                     * just use "ftp_ip_address" and "server_port",
                     * and wildcard everything else?
                     *
                     * XXX - what if we did find a conversation?  As
                     * we create it only on the first pass through the
                     * packets, if we find one, it's presumably an
                     * unrelated conversation.  Should we remove the
                     * old one from the hash table and put this one in
                     * its place?  Can the conversation code handle
                     * conversations not in the hash table?  Or should
                     * we make conversations support start and end
                     * frames, as circuits do, and treat this as an
                     * indication that one conversation was closed and
                     * a new one was opened?
                     */
                    conversation = conversation_new(
                        pinfo->fd->num, &ftp_ip_address, &pinfo->dst,
                        PT_TCP, ftp_port, 0, NO_PORT2);
                    conversation_set_dissector(conversation, ftpdata_handle);
                }
            }
        }
    }


    if (is_epasv_response) {
        if (linelen != 0) {
            /*
             * This frame contains an  EPSV response; set up a
             * conversation for the data.
             */
            if (parse_extended_pasv_response(line, linelen, &ftp_port)) {
                /* Add port number to tree */
                if (tree) {
                    proto_tree_add_uint(reqresp_tree,
                                        hf_ftp_pasv_port, tvb, 0, 0,
                                        ftp_port);
                }

                /* Find/create conversation for data */
                conversation = find_conversation(pinfo->fd->num, &pinfo->src,
                                                 &pinfo->dst, PT_TCP, ftp_port, 0,
                                                 NO_PORT_B);
                if (conversation == NULL) {
                    conversation = conversation_new(
                        pinfo->fd->num, &pinfo->src, &pinfo->dst,
                        PT_TCP, ftp_port, 0, NO_PORT2);
                    conversation_set_dissector(conversation,
                        ftpdata_handle);
                }
            }
        }
    }

    if (tree) {
        /*
         * Show the rest of the request or response as text,
         * a line at a time.
         * XXX - only if there's a continuation indicator?
         */
        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_text(ftp_tree, tvb, offset,
                next_offset - offset, "%s",
                tvb_format_text(tvb, offset, next_offset - offset));
            offset = next_offset;
        }
    }
}
Пример #28
0
static void
rtsp_create_conversation(packet_info *pinfo, const guchar *line_begin,
                         size_t line_len, gint rdt_feature_level)
{
	conversation_t	*conv;
	guchar		buf[256];
	guchar		*tmp;
	gboolean	rtp_transport = FALSE;
	gboolean	rdt_transport = FALSE;
	guint		c_data_port, c_mon_port;
	guint		s_data_port, s_mon_port;
	gboolean	is_video = FALSE; /* FIX ME - need to indicate video or not */

	/* Copy line into buf */
	if (line_len > sizeof(buf) - 1)
	{
		/* Don't overflow the buffer. */
		line_len = sizeof(buf) - 1;
	}
	memcpy(buf, line_begin, line_len);
	buf[line_len] = '\0';

	/* Get past "Transport:" and spaces */ 
	tmp = buf + STRLEN_CONST(rtsp_transport);
	while (*tmp && isspace(*tmp))
		tmp++;

	/* Work out which transport type is here */
	if (g_ascii_strncasecmp(tmp, rtsp_rtp, strlen(rtsp_rtp)) == 0)
		rtp_transport = TRUE;
	else
	if (g_ascii_strncasecmp(tmp, rtsp_real_rdt, strlen(rtsp_real_rdt)) == 0 ||
	    g_ascii_strncasecmp(tmp, rtsp_real_tng, strlen(rtsp_real_tng)) == 0)
		rdt_transport = TRUE;
	else
	{
		/* Give up on unknown transport types */
		return;
	}
	
	c_data_port = c_mon_port = 0;
	s_data_port = s_mon_port = 0;
	
	/* Look for server port */
	if ((tmp = strstr(buf, rtsp_sps))) {
		tmp += strlen(rtsp_sps);
		if (sscanf(tmp, "%u-%u", &s_data_port, &s_mon_port) < 1) {
			g_warning("Frame %u: rtsp: bad server_port",
				pinfo->fd->num);
			return;
		}
	}
	/* Look for client port */
	if ((tmp = strstr(buf, rtsp_cps))) {
		tmp += strlen(rtsp_cps);
		if (sscanf(tmp, "%u-%u", &c_data_port, &c_mon_port) < 1) {
			g_warning("Frame %u: rtsp: bad client_port",
				pinfo->fd->num);
			return;
		}
	}
	
	
	/* Deal with RTSP TCP-interleaved conversations. */
	if (!c_data_port) {
		rtsp_conversation_data_t	*data;
		guint				s_data_chan, s_mon_chan;
		int				i;

		/* Search tranport line for interleaved string */
		if ((tmp = strstr(buf, rtsp_inter)) == NULL) {
			/*
			 * No interleaved or server_port - probably a
			 * SETUP request, rather than reply.
			 */
			return;
		}
		
		/* Move tmp to beyone interleaved string */
		tmp += strlen(rtsp_inter);
		/* Look for channel number(s) */
		i = sscanf(tmp, "%u-%u", &s_data_chan, &s_mon_chan);
		if (i < 1)
		{
			g_warning("Frame %u: rtsp: bad interleaved", pinfo->fd->num);
			return;
		}
		
		/* At least data channel present, look for conversation (presumably TCP) */
		conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
		                         pinfo->srcport, pinfo->destport, 0);

		/* Create new conversation if necessary */
		if (!conv)
		{
			conv = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
			                        pinfo->ptype, pinfo->srcport, pinfo->destport,
			                        0);
		}
		
		/* Look for previous data */
		data = conversation_get_proto_data(conv, proto_rtsp);

		/* Create new data if necessary */
		if (!data)
		{
			data = se_alloc(sizeof(rtsp_conversation_data_t));
			conversation_add_proto_data(conv, proto_rtsp, data);
		}

		/* Now set the dissector handle of the interleaved channel
		   according to the transport protocol used */
		if (rtp_transport)
		{
			if (s_data_chan < RTSP_MAX_INTERLEAVED) {
				data->interleaved[s_data_chan].dissector =
					rtp_handle;
			}
			if (i > 1 && s_mon_chan < RTSP_MAX_INTERLEAVED) {
				data->interleaved[s_mon_chan].dissector =
					rtcp_handle;
			}
		}
		else if (rdt_transport)
		{
			if (s_data_chan < RTSP_MAX_INTERLEAVED) {
				data->interleaved[s_data_chan].dissector =
					rdt_handle;
			}
		}
		return;
	}

	/*
	 * We only want to match on the destination address, not the
	 * source address, because the server might send back a packet
	 * from an address other than the address to which its client
	 * sent the packet, so we construct a conversation with no
	 * second address.
	 */
	if (rtp_transport)
	{
		/* There is always data for RTP */
		rtp_add_address(pinfo, &pinfo->dst, c_data_port, s_data_port,
		                "RTSP", pinfo->fd->num, is_video, NULL);
	
		/* RTCP only if indicated */
		if (c_mon_port)
		{
			rtcp_add_address(pinfo, &pinfo->dst, c_mon_port, s_mon_port,
			                 "RTSP", pinfo->fd->num);
		}
	}
	else
	if (rdt_transport)
	{
		/* Real Data Transport */
		rdt_add_address(pinfo, &pinfo->dst, c_data_port, s_data_port,
		                "RTSP", rdt_feature_level);
	}
}
Пример #29
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;
}
Пример #30
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_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
                           pinfo->srcport, pinfo->destport, 0);
  if (!conv) {
    conv = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
                            pinfo->srcport, pinfo->destport, 0);
  }
  cd = (ajp13_conv_data*)conversation_get_proto_data(conv, proto_ajp13);
  if (!cd) {
    cd = se_alloc(sizeof(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_alloc(sizeof(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 (check_col(pinfo->cinfo, COL_INFO)) {
    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, tvb_length(tvb), FALSE);
    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);

  }
}