Beispiel #1
0
/*
 * Given two address/port pairs for a packet, create a new conversation
 * to contain packets between those address/port pairs.
 *
 * The options field is used to specify whether the address 2 value
 * and/or port 2 value are not given and any value is acceptable
 * when searching for this conversation.
 */
conversation_t *
conversation_new(const guint32 setup_frame, const address *addr1, const address *addr2, const port_type ptype,
    const guint32 port1, const guint32 port2, const guint options)
{
/*
	DISSECTOR_ASSERT(!(options | CONVERSATION_TEMPLATE) || ((options | (NO_ADDR2 | NO_PORT2 | NO_PORT2_FORCE))) &&
				"A conversation template may not be constructed without wildcard options");
*/
	GHashTable* hashtable;
	conversation_t *conversation=NULL;
	conversation_key *new_key;

	DPRINT(("creating conversation for frame #%d: %s:%d -> %s:%d (ptype=%d)",
		    setup_frame, address_to_str(wmem_packet_scope(), addr1), port1,
		    address_to_str(wmem_packet_scope(), addr2), port2, ptype));

	if (options & NO_ADDR2) {
		if (options & (NO_PORT2|NO_PORT2_FORCE)) {
			hashtable = conversation_hashtable_no_addr2_or_port2;
		} else {
			hashtable = conversation_hashtable_no_addr2;
		}
	} else {
		if (options & (NO_PORT2|NO_PORT2_FORCE)) {
			hashtable = conversation_hashtable_no_port2;
		} else {
			hashtable = conversation_hashtable_exact;
		}
	}

	new_key = wmem_new(wmem_file_scope(), struct conversation_key);
	new_key->next = conversation_keys;
	conversation_keys = new_key;
	copy_address_wmem(wmem_file_scope(), &new_key->addr1, addr1);
	copy_address_wmem(wmem_file_scope(), &new_key->addr2, addr2);
	new_key->ptype = ptype;
	new_key->port1 = port1;
	new_key->port2 = port2;

	conversation = wmem_new(wmem_file_scope(), conversation_t);
	memset(conversation, 0, sizeof(conversation_t));

	conversation->index = new_index;
	conversation->setup_frame = conversation->last_frame = setup_frame;
	conversation->data_list = NULL;

	conversation->dissector_tree = wmem_tree_new(wmem_file_scope());

	/* set the options and key pointer */
	conversation->options = options;
	conversation->key_ptr = new_key;

	new_index++;

	DINDENT();
	conversation_insert_into_hashtable(hashtable, conversation);
	DENDENT();

	return conversation;
}
Beispiel #2
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);
}
Beispiel #3
0
static int get_address_v5(tvbuff_t *tvb, int offset,
    socks_hash_entry_t *hash_info) {

    /* decode the v5 address and return offset of next byte */
    int     a_type;
    address addr;

    a_type = tvb_get_guint8(tvb, offset);
    offset += 1;

    switch(a_type)
    {
    case 1: /* IPv4 address */
        if ( hash_info) {
            set_address_tvb(&addr, AT_IPv4, 4, tvb, offset);
            copy_address_wmem(wmem_file_scope(), &hash_info->dst_addr, &addr);
        }
        offset += 4;
        break;

    case 4: /* IPv6 address */
        if ( hash_info) {
            set_address_tvb(&addr, AT_IPv6, 16, tvb, offset);
            copy_address_wmem(wmem_file_scope(), &hash_info->dst_addr, &addr);
        }
        offset += 16;
        break;

    case 3: /* domain name address */
        offset += tvb_get_guint8(tvb, offset) + 1;
        break;
    }

    return offset;
}
Beispiel #4
0
/*
 * Set the address 2 value in a key.  Remove the original from
 * table, update the options and port values, insert the updated key.
 */
void
conversation_set_addr2(conversation_t *conv, const address *addr)
{
	char* addr_str;
	DISSECTOR_ASSERT_HINT(!(conv->options & CONVERSATION_TEMPLATE),
			"Use the conversation_create_from_template function when the CONVERSATION_TEMPLATE bit is set in the options mask");

	addr_str = address_to_str(NULL, addr);
	DPRINT(("called for addr=%s", addr_str));
	wmem_free(NULL, addr_str);

	/*
	 * If the address 2 value is not wildcarded, don't set it.
	 */
	if (!(conv->options & NO_ADDR2))
		return;

	DINDENT();
	if (conv->options & NO_PORT2) {
		conversation_remove_from_hashtable(conversation_hashtable_no_addr2_or_port2, conv);
	} else {
		conversation_remove_from_hashtable(conversation_hashtable_no_port2, conv);
	}
	conv->options &= ~NO_ADDR2;
	copy_address_wmem(wmem_file_scope(), &conv->key_ptr->addr2, addr);
	if (conv->options & NO_PORT2) {
		conversation_insert_into_hashtable(conversation_hashtable_no_port2, conv);
	} else {
		conversation_insert_into_hashtable(conversation_hashtable_exact, conv);
	}
	DENDENT();
}
Beispiel #5
0
static lbttcp_transport_t * lbttcp_transport_create(const address * source_address, guint16 source_port, guint32 session_id)
{
    lbttcp_transport_t * transport = NULL;

    transport = wmem_new(wmem_file_scope(), lbttcp_transport_t);
    copy_address_wmem(wmem_file_scope(), &(transport->source_address), source_address);
    transport->source_port = source_port;
    transport->session_id = session_id;
    transport->channel = lbm_channel_assign(LBM_CHANNEL_TRANSPORT_LBTTCP);
    transport->next_client_id = 1;
    transport->client_list = wmem_list_new(wmem_file_scope());
    return (transport);
}
Beispiel #6
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);
}
Beispiel #7
0
/* Broadcasts are searches, offers or promises.
 *
 * Searches are sent by
 * a peer when it needs a file (ie. while applying its policy, when it needs
 * files such as installers to install software.)
 *
 * Each broadcast relates to one file and each file is identified only by its
 * checksum - no file names are ever used. A search times out after 10 seconds
 * (configurable) and the peer will then attempt to act on any offers by
 * downloading (via push or pull - see dissect_ldss_transfer) from those peers.
 *
 * If no offers are received, the search fails and the peer fetches the file
 * from a remote server, generally a HTTP server on the other side of a WAN.
 * The protocol exists to minimize the number of WAN downloads needed.
 *
 * While downloading from WAN the peer sends promises to inform other peers
 * when it will be available for them to download. This prevents multiple peers
 * simultaneously downloading the same file. Promises also inform other peers
 * how much download bandwidth is being used by their download. Other peers use
 * this information and the configured knowledge of the WAN bandwidth to avoid
 * saturating the WAN link, as file downloads are a non-time-critical and
 * non-business-critical network function. LDSS is intended for networks of
 * 5-20 machines connected by slow WAN link. The current implementation of the
 * protocol allows administrator to configure "time windows" when WAN usage is
 * throttled/unthrottled, though this isn't visible in LDSS.
 *
 * Once a WAN download or a LAN transfer (see below above dissect_ldss_transfer)
 * has complete the peer will offer the file to other peers on the LAN so they
 * don't need to download it themselves.
 *
 * Peers also notify when they shut down in case any other peer is waiting for
 * a file. */
static int
dissect_ldss_broadcast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint16	messageID;
	guint8 digest_type;
	guint8 compression;
	guint32 cookie;
	guint8 *digest;
	guint64	size;
	guint64	offset;
	guint32	targetTime;
	guint16 port;
	guint16	rate;
	guint16 messageDetail = INFERRED_NONE;

	proto_tree	*ti, *ldss_tree;

	const gchar *packet_type, *packet_detail;

	messageID   = tvb_get_ntohs  (tvb,  0);
	digest_type = tvb_get_guint8 (tvb,  2);
	compression = tvb_get_guint8 (tvb,  3);
	cookie      = tvb_get_ntohl  (tvb,  4);
	digest      = (guint8 *)tvb_memdup (wmem_file_scope(), tvb,  8, DIGEST_LEN);
	size	    = tvb_get_ntoh64 (tvb, 40);
	offset	    = tvb_get_ntoh64 (tvb, 48);
	targetTime  = tvb_get_ntohl  (tvb, 56);
	port        = tvb_get_ntohs  (tvb, 64);
	rate	    = tvb_get_ntohs  (tvb, 66);

	packet_type = val_to_str_const(messageID, ldss_message_id_value, "unknown");

	if (messageID == MESSAGE_ID_WILLSEND) {
		if (cookie == 0) {
			/* Shutdown: Dishonor promises from this peer. Current
			 * implementation abuses WillSend for this. */
			messageDetail = INFERRED_PEERSHUTDOWN;
		}
		else if (size == 0 && offset == 0) {
			/* NeedFile search failed - going to WAN */
			messageDetail = INFERRED_WANDOWNLOAD;
		}
		else if (size > 0) {
			/* Size is known (not always the case) */
			if (size == offset) {
				/* File is available for pull on this peer's TCP port */
				messageDetail = INFERRED_OFFER;
			}
			else {
				/* WAN download progress announcement from this peer */
				messageDetail = INFERRED_PROMISE;
			}
		}
	}
	else if (messageID == MESSAGE_ID_NEEDFILE) {
		messageDetail = INFERRED_SEARCH;
	}
	packet_detail = val_to_str_const(messageDetail, ldss_inferred_info, "unknown");

	/* Set the info column */
	col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS Broadcast (%s%s)",
			     packet_type,
			     packet_detail);

	/* If we have a non-null tree (ie we are building the proto_tree
	 * instead of just filling out the columns), then give more detail. */
	ti = proto_tree_add_item(tree, proto_ldss,
			tvb, 0, (tvb_captured_length(tvb) > 72) ? tvb_captured_length(tvb) : 72, ENC_NA);
	ldss_tree = proto_item_add_subtree(ti, ett_ldss_broadcast);

	proto_tree_add_item(ldss_tree, hf_ldss_message_id,
			tvb, 0, 2, ENC_BIG_ENDIAN);
	ti = proto_tree_add_uint(ldss_tree, hf_ldss_message_detail,
			tvb, 0, 0, messageDetail);
	PROTO_ITEM_SET_GENERATED(ti);
	proto_tree_add_item(ldss_tree, hf_ldss_digest_type,
			tvb, 2,	    1,	ENC_BIG_ENDIAN);
	proto_tree_add_item(ldss_tree, hf_ldss_compression,
			tvb, 3,	    1,	ENC_BIG_ENDIAN);
	proto_tree_add_uint_format_value(ldss_tree, hf_ldss_cookie,
			tvb, 4,	    4,	FALSE,
			"0x%x%s",
			cookie,
			(cookie == 0)
			? " - shutdown (promises from this peer are no longer valid)"
			: "");
	proto_tree_add_item(ldss_tree, hf_ldss_digest,
			tvb, 8,	    DIGEST_LEN, ENC_NA);
	proto_tree_add_item(ldss_tree, hf_ldss_size,
			tvb, 40,    8,	ENC_BIG_ENDIAN);
	proto_tree_add_item(ldss_tree, hf_ldss_offset,
			tvb, 48,    8,	ENC_BIG_ENDIAN);
	proto_tree_add_uint_format_value(ldss_tree, hf_ldss_target_time,
			tvb, 56,    4,	FALSE,
			"%d:%02d:%02d",
			(int)(targetTime / 3600),
			(int)((targetTime / 60) % 60),
			(int)(targetTime % 60));
	proto_tree_add_item(ldss_tree, hf_ldss_reserved_1,
			tvb, 60,    4,	ENC_BIG_ENDIAN);
	proto_tree_add_uint_format_value(ldss_tree, hf_ldss_port,
			tvb, 64,    2,	FALSE,
			"%d%s",
			port,
			(messageID == MESSAGE_ID_WILLSEND &&
			 size > 0 &&
			 size == offset)
			? " - file can be pulled at this TCP port"
			: (messageID == MESSAGE_ID_NEEDFILE
				? " - file can be pushed to this TCP port"
				: ""));
	proto_tree_add_uint_format_value(ldss_tree, hf_ldss_rate,
			tvb, 66,    2,	FALSE,
			"%ld",
			(rate > 0)
			? (long)floor(exp(rate * G_LN2 / 2048))
			: 0);
	proto_tree_add_item(ldss_tree, hf_ldss_priority,
			tvb, 68, 2, ENC_BIG_ENDIAN);
	proto_tree_add_item(ldss_tree, hf_ldss_property_count,
			tvb, 70, 2, ENC_BIG_ENDIAN);
	if (tvb_reported_length(tvb) > 72) {
		proto_tree_add_item(ldss_tree, hf_ldss_properties,
				tvb, 72, tvb_captured_length(tvb) - 72, ENC_NA);
	}

	/* Finally, store the broadcast and register ourselves to dissect
	 * any pushes or pulls that result from this broadcast. All data
	 * is pushed/pulled over TCP using the port from the broadcast
	 * packet's port field.
	 * Track each by a TCP conversation with the remote end wildcarded.
	 * The TCP conv tracks back to a broadcast conv to determine what it
	 * is in response to.
	 *
	 * These steps only need to be done once per packet, so a variable
	 * tracks the highest frame number seen. Handles the case of first frame
	 * being frame zero. */
	if (messageDetail != INFERRED_PEERSHUTDOWN &&
	    (highest_num_seen == 0 ||
	     highest_num_seen < pinfo->num)) {

		ldss_broadcast_t *data;

		/* Populate data from the broadcast */
		data = wmem_new0(wmem_file_scope(), ldss_broadcast_t);
		data->num = pinfo->num;
		data->ts = pinfo->abs_ts;
		data->message_id = messageID;
		data->message_detail = messageDetail;
		data->port = port;
		data->size = size;
		data->offset = offset;
		data->compression = compression;

		data->file = wmem_new0(wmem_file_scope(), ldss_file_t);
		data->file->digest = digest;
		data->file->digest_type = digest_type;

		data->broadcaster = wmem_new0(wmem_file_scope(), ldss_broadcaster_t);
		copy_address_wmem(wmem_file_scope(), &data->broadcaster->addr, &pinfo->src);
		data->broadcaster->port = port;

		/* Dissect any future pushes/pulls */
		if (port > 0) {
			prepare_ldss_transfer_conv(data);
		}

		/* Record that the frame was processed */
		highest_num_seen = pinfo->num;
	}

	return tvb_captured_length(tvb);
}