/*
 * Compare two conversation keys, except for the port 2 value.
 * We don't check both directions of the conversation - the routine
 * doing the hash lookup has to do two searches, as the hash key
 * will be different for the two directions.
 */
static gint
conversation_match_no_port2(gconstpointer v, gconstpointer w)
{
	const conversation_key *v1 = (const conversation_key *)v;
	const conversation_key *v2 = (const conversation_key *)w;

	if (v1->ptype != v2->ptype)
		return 0;	/* different types of port */

	/*
	 * Are the first and second port 1 values the same, the first and
	 * second address 1 values the same, and the first and second
	 * address 2 values the same?
	 */
	if (v1->port1 == v2->port1 &&
	    ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
	    ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
		/*
		 * Yes.  It's the same conversation, and the two
		 * address/port pairs are going in the same direction.
		 */
		return 1;
	}

	/*
	 * The addresses or the ports don't match.
	 */
	return 0;
}
/** Compare two conversation keys for an exact match.
 * (Parameter types are gconstpointer for GHashTable compatibility.)
 *
 * @param key1 First conversation. MUST point to a conv_key_t struct.
 * @param key2 Second conversation. MUST point to a conv_key_t struct.
 * @return TRUE if conversations are equal, FALSE otherwise.
 */
static gboolean
conversation_equal(gconstpointer key1, gconstpointer key2)
{
    const conv_key_t *ck1 = (const conv_key_t *)key1;
    const conv_key_t *ck2 = (const conv_key_t *)key2;

    if (ck1->conv_id == ck2->conv_id)
    {
        if (ck1->port1 == ck2->port1 &&
            ck1->port2 == ck2->port2 &&
            ADDRESSES_EQUAL(&ck1->addr1, &ck2->addr1) &&
            ADDRESSES_EQUAL(&ck1->addr2, &ck2->addr2)) {
            return TRUE;
        }

        if (ck1->port2 == ck2->port1 &&
            ck1->port1 == ck2->port2 &&
            ADDRESSES_EQUAL(&ck1->addr2, &ck2->addr1) &&
            ADDRESSES_EQUAL(&ck1->addr1, &ck2->addr2)) {
            return TRUE;
        }
    }

    /*
     * The addresses, ports, or conversation IDs don't match.
     */
    return FALSE;
}
Example #3
0
/* compare the endpoints of two RTP streams */
gboolean rtp_stream_info_is_reverse(const rtp_stream_info_t *stream_a, rtp_stream_info_t *stream_b)
{
    if (stream_a == NULL || stream_b == NULL)
        return FALSE;

    if ((ADDRESSES_EQUAL(&(stream_a->src_addr), &(stream_b->dest_addr)))
        && (stream_a->src_port == stream_b->dest_port)
        && (ADDRESSES_EQUAL(&(stream_a->dest_addr), &(stream_b->src_addr)))
        && (stream_a->dest_port == stream_b->src_port))
        return TRUE;
    else
        return FALSE;
}
Example #4
0
static sctp_assoc_info_t * add_address(address * vadd, sctp_assoc_info_t *info, guint8 direction)
{
	GList *list;
	address *v=NULL;

	if (direction == 1)
		list = g_list_first(info->addr1);
	else
		list = g_list_first(info->addr2);

	while (list)
	{
		v = (address *) (list->data);
		if (ADDRESSES_EQUAL(vadd, v)) {
			g_free(vadd);
			return info;
		}
		list = g_list_next(list);
	}

	if (direction == 1)
		info->addr1 = g_list_append(info->addr1, vadd);
	else if (direction==2)
		info->addr2 = g_list_append(info->addr2, vadd);

	return info;
}
Example #5
0
/* GCompareFunc style comparison function for _rtp_stream_info */
gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
{
	const struct _rtp_stream_info* a = (const struct _rtp_stream_info*)aa;
	const struct _rtp_stream_info* b = (const struct _rtp_stream_info*)bb;

	if (a==b)
		return 0;
	if (a==NULL || b==NULL)
		return 1;
	if (ADDRESSES_EQUAL(&(a->src_addr), &(b->src_addr))
		&& (a->src_port == b->src_port)
		&& ADDRESSES_EQUAL(&(a->dest_addr), &(b->dest_addr))
		&& (a->dest_port == b->dest_port)
		&& (a->ssrc == b->ssrc))
		return 0;
	else
		return 1;
}
Example #6
0
/* checks if a packet matches the source/destination manually-configured in preferences */
static gboolean
manual_addr_match(packet_info *pinfo) {
    if (gPREF_MAN_EN) {
        /* If the manual settings are enabled see if this fits - in which case we can skip
           the following checks entirely and go straight to dissecting */
        if (    (ADDRESSES_EQUAL(&pinfo->src, &manual_addr[0]) &&
                 ADDRESSES_EQUAL(&pinfo->dst, &manual_addr[1]) &&
                 (pinfo->srcport == 0xffffffff /* is unknown */ || pinfo->srcport == gPREF_QP[0]) &&
                 (pinfo->destport == 0xffffffff /* is unknown */ || pinfo->destport == gPREF_QP[1]))    ||
                (ADDRESSES_EQUAL(&pinfo->src, &manual_addr[1]) &&
                 ADDRESSES_EQUAL(&pinfo->dst, &manual_addr[0]) &&
                 (pinfo->srcport == 0xffffffff /* is unknown */ || pinfo->srcport == gPREF_QP[1]) &&
                 (pinfo->destport == 0xffffffff /* is unknown */ || pinfo->destport == gPREF_QP[0]))    )
            return TRUE;
    }

    return FALSE;
}
Example #7
0
/* GCompareFunc style comparison function for _mcast_stream_info */
static gint
mcast_stream_info_cmp(gconstpointer aa, gconstpointer bb)
{
	const struct _mcast_stream_info* a = aa;
	const struct _mcast_stream_info* b = bb;

        if (a==b)
                return 0;
        if (a==NULL || b==NULL)
                return 1;
        if (ADDRESSES_EQUAL(&(a->src_addr), &(b->src_addr))
                && (a->src_port == b->src_port)
                && ADDRESSES_EQUAL(&(a->dest_addr), &(b->dest_addr))
                && (a->dest_port == b->dest_port))
                return 0;
        else
                return 1;

}
static gboolean
is_broadcast(address* addr)
{
	static address broadcast_addr;
	static const guint8 broadcast_addr_bytes[6] = {
		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
	};

	SET_ADDRESS(&broadcast_addr, AT_ETHER, 6, broadcast_addr_bytes);
	return ADDRESSES_EQUAL(addr, &broadcast_addr);
}
Example #9
0
WSLUA_METAMETHOD Address__eq(lua_State* L) { /* Compares two Addresses */
    Address addr1 = checkAddress(L,1);
    Address addr2 = checkAddress(L,2);
    gboolean result = FALSE;

    if (ADDRESSES_EQUAL(addr1, addr2))
        result = TRUE;

    lua_pushboolean(L,result);

    return 1;
}
static sctp_assoc_info_t *
add_chunk_count(address *vadd, sctp_assoc_info_t *info, guint32 direction, guint32 type)
{
	GList *list;
	address *v=NULL;
	sctp_addr_chunk *ch=NULL;
	guint8 * dat;
	int i;

	list = g_list_first(info->addr_chunk_count);

	while (list)
	{
		ch = (sctp_addr_chunk *)(list->data);
		if (ch->direction == direction)
		{
			v = (address *) (ch->addr);
			if (ADDRESSES_EQUAL(vadd, v))
			{
				if (IS_SCTP_CHUNK_TYPE(type))
					ch->addr_count[type]++;
				else
					ch->addr_count[OTHER_CHUNKS_INDEX]++;
				return info;
			}
			else
			{
				list = g_list_next(list);
			}
		}
		else
			list = g_list_next(list);
	}
	ch = (sctp_addr_chunk *)g_malloc(sizeof(sctp_addr_chunk));
	ch->direction = direction;
	ch->addr = (address *)g_malloc(sizeof(address));
	ch->addr->type = vadd->type;
	ch->addr->len = vadd->len;
	dat = (guint8 *)g_malloc(vadd->len);
	memcpy(dat, vadd->data, vadd->len);
	ch->addr->data = dat;
	for (i=0; i < NUM_CHUNKS; i++)
		ch->addr_count[i] = 0;

	if (IS_SCTP_CHUNK_TYPE(type))
		ch->addr_count[type]++;
	else
		ch->addr_count[OTHER_CHUNKS_INDEX]++;

	info->addr_chunk_count = g_list_append(info->addr_chunk_count, ch);
	return info;
}
Example #11
0
/*
 * Compare two host keys for an exact match.
 */
static gint
host_match(gconstpointer v, gconstpointer w)
{
    const host_key_t *v1 = (const host_key_t *)v;
    const host_key_t *v2 = (const host_key_t *)w;

    if (v1->port == v2->port &&
        ADDRESSES_EQUAL(&v1->myaddress, &v2->myaddress)) {
        return 1;
    }
    /*
     * The addresses or the ports don't match.
     */
    return 0;
}
Example #12
0
/* compare two bindings (except the interface related things, e.g. uuid) */
static gint
decode_dcerpc_binding_cmp(gconstpointer a, gconstpointer b)
{
    const decode_dcerpc_bind_values_t *binding_a = a;
    const decode_dcerpc_bind_values_t *binding_b = b;


    /* don't compare uuid and ver! */
    if(
        ADDRESSES_EQUAL(&binding_a->addr_a, &binding_b->addr_a) &&
        ADDRESSES_EQUAL(&binding_a->addr_b, &binding_b->addr_b) &&
        binding_a->ptype == binding_b->ptype &&
        binding_a->port_a == binding_b->port_a &&
        binding_a->port_b == binding_b->port_b &&
        binding_a->ctx_id == binding_b->ctx_id &&
        binding_a->smb_fid == binding_b->smb_fid)
    {
        /* equal */
        return 0;
    }

    /* unequal */
    return 1;
}
Example #13
0
void
reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement,
                guint32 length, const char* data, guint32 data_length, 
                int synflag, address *net_src, address *net_dst, 
                guint srcport, guint dstport) {
  guint8 srcx[MAX_IPADDR_LEN], dstx[MAX_IPADDR_LEN];
  int src_index, j, first = 0, len;
  guint32 newseq;
  tcp_frag *tmp_frag;
  tcp_stream_chunk sc;

  src_index = -1;

  /* First, check if this packet should be processed. */
  if (find_tcp_index) {
    if ((port[0] == srcport && port[1] == dstport &&
         ADDRESSES_EQUAL(&tcp_addr[0], net_src) &&
         ADDRESSES_EQUAL(&tcp_addr[1], net_dst))
        ||
        (port[1] == srcport && port[0] == dstport &&
         ADDRESSES_EQUAL(&tcp_addr[1], net_src) &&
         ADDRESSES_EQUAL(&tcp_addr[0], net_dst))) {
      find_tcp_index = FALSE;
      tcp_stream_to_follow = tcp_stream;
    }
    else {
      return;
    }
  }
  else if ( tcp_stream != tcp_stream_to_follow )
    return;

  if ((net_src->type != AT_IPv4 && net_src->type != AT_IPv6) ||
      (net_dst->type != AT_IPv4 && net_dst->type != AT_IPv6))
    return;

  if (net_src->type == AT_IPv4)
    len = 4;
  else
    len = 16;

  memcpy(srcx, net_src->data, len);
  memcpy(dstx, net_dst->data, len);

  /* follow_tcp_index() needs to learn address/port pairs */
  if (find_tcp_addr) {
    find_tcp_addr = FALSE;
    memcpy(ip_address[0], net_src->data, net_src->len);
    port[0] = srcport;
    memcpy(ip_address[1], net_dst->data, net_dst->len);
    port[1] = dstport;
  }

  /* Check to see if we have seen this source IP and port before.
     (Yes, we have to check both source IP and port; the connection
     might be between two different ports on the same machine.) */
  for( j=0; j<2; j++ ) {
    if (memcmp(src_addr[j], srcx, len) == 0 && src_port[j] == srcport ) {
      src_index = j;
    }
  }
  /* we didn't find it if src_index == -1 */
  if( src_index < 0 ) {
    /* assign it to a src_index and get going */
    for( j=0; j<2; j++ ) {
      if( src_port[j] == 0 ) {
	memcpy(src_addr[j], srcx, len);
	src_port[j] = srcport;
	src_index = j;
	first = 1;
	break;
      }
    }
  }
  if( src_index < 0 ) {
    fprintf( stderr, "ERROR in reassemble_tcp: Too many addresses!\n");
    return;
  }

  if( data_length < length ) {
    incomplete_tcp_stream = TRUE;
  }

  /* Before adding data for this flow to the data_out_file, check whether
   * this frame acks fragments that were already seen. This happens when
   * frames are not in the capture file, but were actually seen by the 
   * receiving host (Fixes bug 592).
   */
  if( frags[1-src_index] ) {
    memcpy(sc.src_addr, dstx, len);
    sc.src_port = dstport;
    sc.dlen     = 0;        /* Will be filled in in check_fragments */
    while ( check_fragments( 1-src_index, &sc, acknowledgement ) )
      ;
  }

  /* Initialize our stream chunk.  This data gets written to disk. */
  memcpy(sc.src_addr, srcx, len);
  sc.src_port = srcport;
  sc.dlen     = data_length;

  /* now that we have filed away the srcs, lets get the sequence number stuff
     figured out */
  if( first ) {
    /* this is the first time we have seen this src's sequence number */
    seq[src_index] = sequence + length;
    if( synflag ) {
      seq[src_index]++;
    }
    /* write out the packet data */
    write_packet_data( src_index, &sc, data );
    return;
  }
  /* if we are here, we have already seen this src, let's
     try and figure out if this packet is in the right place */
  if( sequence < seq[src_index] ) {
    /* this sequence number seems dated, but
       check the end to make sure it has no more
       info than we have already seen */
    newseq = sequence + length;
    if( newseq > seq[src_index] ) {
      guint32 new_len;

      /* this one has more than we have seen. let's get the
	 payload that we have not seen. */

      new_len = seq[src_index] - sequence;

      if ( data_length <= new_len ) {
	data = NULL;
	data_length = 0;
	incomplete_tcp_stream = TRUE;
      } else {
	data += new_len;
	data_length -= new_len;
      }
      sc.dlen = data_length;
      sequence = seq[src_index];
      length = newseq - seq[src_index];

      /* this will now appear to be right on time :) */
    }
  }
  if ( sequence == seq[src_index] ) {
    /* right on time */
    seq[src_index] += length;
    if( synflag ) seq[src_index]++;
    if( data ) {
      write_packet_data( src_index, &sc, data );
    }
    /* done with the packet, see if it caused a fragment to fit */
    while( check_fragments( src_index, &sc, 0 ) )
      ;
  }
  else {
    /* out of order packet */
    if(data_length > 0 && ((glong)(sequence - seq[src_index]) > 0) ) {
      tmp_frag = (tcp_frag *)g_malloc( sizeof( tcp_frag ) );
      tmp_frag->data = (gchar *)g_malloc( data_length );
      tmp_frag->seq = sequence;
      tmp_frag->len = length;
      tmp_frag->data_len = data_length;
      memcpy( tmp_frag->data, data, data_length );
      if( frags[src_index] ) {
	tmp_frag->next = frags[src_index];
      } else {
	tmp_frag->next = NULL;
      }
      frags[src_index] = tmp_frag;
    }
  }
} /* end reassemble_tcp */
Example #14
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;
        }
    }
}
Example #15
0
static int
dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    const char		*opcode_str;
    proto_tree		*slimp3_tree = NULL;
    proto_item		*ti = NULL, *hidden_item;
    gint		i1;
    gint		offset = 0;
    guint16		opcode;
    guchar		lcd_char;
    char		lcd_str[MAX_LCD_STR_LEN + 1];
    int			to_server = FALSE;
    int			old_protocol = FALSE;
    address		tmp_addr;
    gboolean		in_str;
    int			lcd_strlen;

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

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

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

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

    }

    if (tree) {

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

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

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

    switch (opcode) {

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

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

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

    case SLIMP3_DISPLAY:
        if (tree) {

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

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

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

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

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

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

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

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

        break;

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

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

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

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

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

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

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

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

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

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

        if (check_col(pinfo->cinfo, COL_INFO)) {
            guint8 fw_ver = tvb_get_guint8(tvb, offset+2);
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Device ID: %d. Firmware: %d.%d",
                            tvb_get_guint8(tvb, offset+1), fw_ver>>4, fw_ver & 0xf);
        }
Iax2AnalysisDialog::Iax2AnalysisDialog(QWidget &parent, CaptureFile &cf) :
    WiresharkDialog(parent, cf),
    ui(new Ui::Iax2AnalysisDialog),
    port_src_fwd_(0),
    port_dst_fwd_(0),
    port_src_rev_(0),
    port_dst_rev_(0)
{
    ui->setupUi(this);
    setWindowSubtitle(tr("IAX2 Stream Analysis"));

    // XXX Use recent settings instead
    resize(parent.width() * 4 / 5, parent.height() * 4 / 5);
    ui->progressFrame->hide();

    stream_ctx_menu_.addAction(ui->actionGoToPacket);
    stream_ctx_menu_.addAction(ui->actionNextProblem);
    stream_ctx_menu_.addSeparator();
    stream_ctx_menu_.addAction(ui->actionSaveAudio);
    stream_ctx_menu_.addAction(ui->actionSaveForwardAudio);
    stream_ctx_menu_.addAction(ui->actionSaveReverseAudio);
    stream_ctx_menu_.addSeparator();
    stream_ctx_menu_.addAction(ui->actionSaveCsv);
    stream_ctx_menu_.addAction(ui->actionSaveForwardCsv);
    stream_ctx_menu_.addAction(ui->actionSaveReverseCsv);
    stream_ctx_menu_.addSeparator();
    stream_ctx_menu_.addAction(ui->actionSaveGraph);
    ui->forwardTreeWidget->installEventFilter(this);
    ui->forwardTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->forwardTreeWidget, SIGNAL(customContextMenuRequested(QPoint)),
                SLOT(showStreamMenu(QPoint)));
    ui->reverseTreeWidget->installEventFilter(this);
    ui->reverseTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->reverseTreeWidget, SIGNAL(customContextMenuRequested(QPoint)),
                SLOT(showStreamMenu(QPoint)));
    connect(ui->streamGraph, SIGNAL(mousePress(QMouseEvent*)),
            this, SLOT(graphClicked(QMouseEvent*)));

    graph_ctx_menu_.addAction(ui->actionSaveGraph);

    QStringList header_labels;
    for (int i = 0; i < ui->forwardTreeWidget->columnCount(); i++) {
        header_labels << ui->forwardTreeWidget->headerItem()->text(i);
    }
    ui->reverseTreeWidget->setHeaderLabels(header_labels);

    memset(&src_fwd_, 0, sizeof(address));
    memset(&dst_fwd_, 0, sizeof(address));
    memset(&src_rev_, 0, sizeof(address));
    memset(&dst_rev_, 0, sizeof(address));

    QList<QCheckBox *> graph_cbs = QList<QCheckBox *>()
            << ui->fJitterCheckBox << ui->fDiffCheckBox
            << ui->rJitterCheckBox << ui->rDiffCheckBox;

    for (int i = 0; i < num_graphs_; i++) {
        QCPGraph *graph = ui->streamGraph->addGraph();
        graph->setPen(QPen(ColorUtils::graph_colors_[i]));
        graph->setName(graph_cbs[i]->text());
        graphs_ << graph;
        graph_cbs[i]->setChecked(true);
        graph_cbs[i]->setIcon(StockIcon::colorIcon(ColorUtils::graph_colors_[i], QPalette::Text));
    }
    ui->streamGraph->xAxis->setLabel("Arrival Time");
    ui->streamGraph->yAxis->setLabel("Value (ms)");

    // We keep our temp files open for the lifetime of the dialog. The GTK+
    // UI opens and closes at various points.
    QString tempname = QString("%1/wireshark_iax2_f").arg(QDir::tempPath());
    fwd_tempfile_ = new QTemporaryFile(tempname, this);
    fwd_tempfile_->open();
    tempname = QString("%1/wireshark_iax2_r").arg(QDir::tempPath());
    rev_tempfile_ = new QTemporaryFile(tempname, this);
    rev_tempfile_->open();

    if (fwd_tempfile_->error() != QFile::NoError || rev_tempfile_->error() != QFile::NoError) {
        err_str_ = tr("Unable to save RTP data.");
        ui->actionSaveAudio->setEnabled(false);
        ui->actionSaveForwardAudio->setEnabled(false);
        ui->actionSaveReverseAudio->setEnabled(false);
    }

    QMenu *save_menu = new QMenu();
    save_menu->addAction(ui->actionSaveAudio);
    save_menu->addAction(ui->actionSaveForwardAudio);
    save_menu->addAction(ui->actionSaveReverseAudio);
    save_menu->addSeparator();
    save_menu->addAction(ui->actionSaveCsv);
    save_menu->addAction(ui->actionSaveForwardCsv);
    save_menu->addAction(ui->actionSaveReverseCsv);
    save_menu->addSeparator();
    save_menu->addAction(ui->actionSaveGraph);
    ui->buttonBox->button(QDialogButtonBox::Save)->setMenu(save_menu);

    const gchar *filter_text = "iax2 && (ip || ipv6)";
    dfilter_t *sfcode;
    gchar *err_msg;

    if (!dfilter_compile(filter_text, &sfcode, &err_msg)) {
        QMessageBox::warning(this, tr("No IAX2 packets found"), QString("%1").arg(err_msg));
        g_free(err_msg);
        close();
    }

    if (!cap_file_.capFile() || !cap_file_.capFile()->current_frame) close();

    frame_data *fdata = cap_file_.capFile()->current_frame;

    if (!cf_read_record(cap_file_.capFile(), fdata)) close();

    epan_dissect_t edt;

    epan_dissect_init(&edt, cap_file_.capFile()->epan, TRUE, FALSE);
    epan_dissect_prime_dfilter(&edt, sfcode);
    epan_dissect_run(&edt, cap_file_.capFile()->cd_t, &cap_file_.capFile()->phdr,
                     frame_tvbuff_new_buffer(fdata, &cap_file_.capFile()->buf), fdata, NULL);

    // This shouldn't happen (the menu item should be disabled) but check anyway
    if (!dfilter_apply_edt(sfcode, &edt)) {
        epan_dissect_cleanup(&edt);
        dfilter_free(sfcode);
        err_str_ = tr("Please select an IAX2 packet");
        updateWidgets();
        return;
    }

    dfilter_free(sfcode);

    /* ok, it is a IAX2 frame, so let's get the ip and port values */
    COPY_ADDRESS(&(src_fwd_), &(edt.pi.src));
    COPY_ADDRESS(&(dst_fwd_), &(edt.pi.dst));
    port_src_fwd_ = edt.pi.srcport;
    port_dst_fwd_ = edt.pi.destport;

    /* assume the inverse ip/port combination for the reverse direction */
    COPY_ADDRESS(&(src_rev_), &(edt.pi.dst));
    COPY_ADDRESS(&(dst_rev_), &(edt.pi.src));
    port_src_rev_ = edt.pi.destport;
    port_dst_rev_ = edt.pi.srcport;

#if 0
    /* check if it is Voice or MiniPacket */
    bool ok;
    getIntFromProtoTree(edt.tree, "iax2", "iax2.call", &ok);
    if (!ok) {
        err_str_ = tr("Please select an IAX2 packet.");
        updateWidgets();
        return;
    }
#endif

#ifdef IAX2_RTP_STREAM_CHECK
    rtpstream_tapinfot tapinfo;

    /* Register the tap listener */
    memset(&tapinfo, 0, sizeof(rtpstream_tapinfot));
    tapinfo.tap_data = this;
    tapinfo.mode = TAP_ANALYSE;

//    register_tap_listener_rtp_stream(&tapinfo, NULL);
    /* Scan for RTP streams (redissect all packets) */
    rtpstream_scan(&tapinfo, cap_file_.capFile(), NULL);

    int num_streams = 0;
    GList *filtered_list = NULL;
    for (GList *strinfo_list = g_list_first(tapinfo.strinfo_list); strinfo_list; strinfo_list = g_list_next(strinfo_list)) {
        rtp_stream_info_t * strinfo = (rtp_stream_info_t*)(strinfo_list->data);
                 << address_to_qstring(&strinfo->dest_addr) << address_to_qstring(&src_rev_) << address_to_qstring(&dst_rev_);
        if (ADDRESSES_EQUAL(&(strinfo->src_addr), &(src_fwd_))
            && (strinfo->src_port == port_src_fwd_)
            && (ADDRESSES_EQUAL(&(strinfo->dest_addr), &(dst_fwd_)))
            && (strinfo->dest_port == port_dst_fwd_))
        {
            ++num_streams;
            filtered_list = g_list_prepend(filtered_list, strinfo);
        }

        if (ADDRESSES_EQUAL(&(strinfo->src_addr), &(src_rev_))
            && (strinfo->src_port == port_src_rev_)
            && (ADDRESSES_EQUAL(&(strinfo->dest_addr), &(dst_rev_)))
            && (strinfo->dest_port == port_dst_rev_))
        {
            ++num_streams;
            filtered_list = g_list_append(filtered_list, strinfo);
        }
    }
Example #17
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;
}
//Copy from ui/gtk/follow_ssl.c
static int
ssl_queue_packet_data(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, const void *ssl)
{
    Q_UNUSED(edt);

    follow_info_t *      follow_info = (follow_info_t*) tapdata;
    SslDecryptedRecord * rec = NULL;
    SslDataInfo *        appl_data = NULL;
    int                  proto_ssl = GPOINTER_TO_INT(ssl);
    SslPacketInfo *      pi = NULL;
    show_stream_t        from = FROM_CLIENT;

    /* Skip packets without decrypted payload data. */
    pi = (SslPacketInfo*) p_get_proto_data(wmem_file_scope(), pinfo, proto_ssl, 0);
    if (!pi || !pi->appl_data) return 0;

    /* Compute the packet's sender. */
    if (follow_info->client_port == 0) {
        follow_info->client_port = pinfo->srcport;
        copy_address(&follow_info->client_ip, &pinfo->src);
    }
    if (ADDRESSES_EQUAL(&follow_info->client_ip, &pinfo->src) &&
            follow_info->client_port == pinfo->srcport) {
        from = FROM_CLIENT;
    } else {
        from = FROM_SERVER;
    }

    for (appl_data = pi->appl_data; appl_data != NULL; appl_data = appl_data->next) {

        /* TCP segments that contain the end of two or more SSL PDUs will be
           queued to SSL taps for each of those PDUs. Therefore a single
           packet could be processed by this SSL tap listener multiple times.
           The following test handles that scenario by treating the
           follow_info->bytes_written[] values as the next expected
           appl_data->seq. Any appl_data instances that fall below that have
           already been processed and must be skipped. */
        if (appl_data->seq < follow_info->bytes_written[from]) continue;

        /* Allocate a SslDecryptedRecord to hold the current appl_data
           instance's decrypted data. Even though it would be possible to
           consolidate multiple appl_data instances into a single rec, it is
           beneficial to use a one-to-one mapping. This affords the Follow
           Stream dialog view modes (ASCII, EBCDIC, Hex Dump, C Arrays, Raw)
           the opportunity to accurately reflect SSL PDU boundaries. Currently
           the Hex Dump view does by starting a new line, and the C Arrays
           view does by starting a new array declaration. */
        rec = (SslDecryptedRecord*) g_malloc(sizeof(SslDecryptedRecord) + appl_data->plain_data.data_len);
        rec->is_from_server = from == FROM_SERVER;
        rec->packet_num = pinfo->fd->num;
        rec->data.data = (guchar*) (rec + 1);
        rec->data.data_len = appl_data->plain_data.data_len;
        memcpy(rec->data.data, appl_data->plain_data.data, appl_data->plain_data.data_len);

        /* Append the record to the follow_info structure. */
        follow_info->payload = g_list_append(follow_info->payload, rec);
        follow_info->bytes_written[from] += rec->data.data_len;
    }

    return 0;
}