Esempio n. 1
0
/**
 * Fill dump header with node address information.
 */
static void
dump_header_set(struct dump_header *dh, const struct gnutella_node *node)
{
	ZERO(dh);

	dh->data[0] = NODE_IS_UDP(node) ? DH_F_UDP : DH_F_TCP;
	switch (host_addr_net(node->addr)) {
	case NET_TYPE_IPV4:
		{
			guint32 ip;
			
			dh->data[0] |= DH_F_IPV4;
			ip = host_addr_ipv4(node->addr);
			poke_be32(&dh->data[1], ip);
		}
		break;
	case NET_TYPE_IPV6:
		dh->data[0] |= DH_F_IPV6;
		memcpy(&dh->data[1], host_addr_ipv6(&node->addr), 16);
		break;
	case NET_TYPE_LOCAL:
	case NET_TYPE_NONE:
		break;
	}
	poke_be16(&dh->data[17], node->port);
}
Esempio n. 2
0
/**
 * Check whether the Gnutella host vector already contains the address:port.
 *
 * @return TRUE if the host vector already contains it.
 */
bool
gnet_host_vec_contains(gnet_host_vec_t *vec, host_addr_t addr, uint16 port)
{
	size_t i;

	g_return_val_if_fail(vec, FALSE);

	switch (host_addr_net(addr)) {
	case NET_TYPE_IPV4:
		for (i = 0; i < vec->n_ipv4; i++) {
			char *dest = cast_to_pointer(&vec->hvec_v4[i]);
			uint32 ip = peek_be32(&dest[0]);
			uint16 pt = peek_le16(&dest[4]);

			if (pt == port && host_addr_ipv4(addr) == ip)
				return TRUE;
		}
		break;
	case NET_TYPE_IPV6:
		for (i = 0; i < vec->n_ipv6; i++) {
			char *dest = cast_to_pointer(&vec->hvec_v6[i]);
			uint16 pt = peek_le16(&dest[16]);

			if (pt == port && 0 == memcmp(dest, host_addr_ipv6(&addr), 16))
				return TRUE;
		}
		break;
	case NET_TYPE_LOCAL:
	case NET_TYPE_NONE:
		break;
	}

	return FALSE;
}
Esempio n. 3
0
/**
 * Retrieve value associated with an IP address, i.e. that of the range
 * containing it.
 *
 * @param db	the IP range database
 * @param ha	the IP address to lookup
 *
 * @return The data associated with the IP address or 0 if not found.
 */
uint16
iprange_get_addr(const struct iprange_db *idb, const host_addr_t ha)
{
	host_addr_t to;

	if (
		host_addr_convert(ha, &to, NET_TYPE_IPV4) ||
		host_addr_tunnel_client(ha, &to)
	) {
		return iprange_get(idb, host_addr_ipv4(to));
	} else if (host_addr_is_ipv6(ha)) {
		return iprange_get6(idb, host_addr_ipv6(&ha));
	}
	return 0;
}
Esempio n. 4
0
/**
 * Prints the host address ``ha'' to ``dst''. The string written to ``dst''
 * is always NUL-terminated unless ``size'' is zero. If ``size'' is too small,
 * the string will be truncated.
 *
 * @param dst the destination buffer; may be NULL iff ``size'' is zero.
 * @param ha the host address.
 * @param size the size of ``dst'' in bytes.
 *
 * @return The length of the resulting string assuming ``size'' is sufficient.
 */
size_t
host_addr_to_string_buf(const host_addr_t ha, char *dst, size_t size)
{
	switch (host_addr_net(ha)) {
	case NET_TYPE_IPV4:
		return ipv4_to_string_buf(host_addr_ipv4(ha), dst, size);
	case NET_TYPE_IPV6:
		return ipv6_to_string_buf(host_addr_ipv6(&ha), dst, size);
	case NET_TYPE_LOCAL:
		return g_strlcpy(dst, "<local>", size);
	case NET_TYPE_NONE:
		return g_strlcpy(dst, "<none>", size);
	}

	g_assert_not_reached();
	return 0;
}
Esempio n. 5
0
/**
 * Write an IPv4 or IPv6 address.
 */
void
pmsg_write_ipv4_or_ipv6_addr(pmsg_t *mb, host_addr_t addr)
{
	g_assert(pmsg_is_writable(mb));	/* Not shared, or would corrupt data */
	g_assert(pmsg_available(mb) >= 17);

	switch (host_addr_net(addr)) {
	case NET_TYPE_IPV4:
		pmsg_write_u8(mb, 4);
		pmsg_write_be32(mb, host_addr_ipv4(addr));
		break;
	case NET_TYPE_IPV6:
		pmsg_write_u8(mb, 16);
		pmsg_write(mb, host_addr_ipv6(&addr), 16);
		break;
	case NET_TYPE_LOCAL:
	case NET_TYPE_NONE:
		g_error("unexpected address in pmsg_write_ipv4_or_ipv6_addr(): %s",
			host_addr_to_string(addr));
	}
}
Esempio n. 6
0
/**
 * Add new host (identified by address and port) to the Gnutella host vector.
 */
void
gnet_host_vec_add(gnet_host_vec_t *vec, host_addr_t addr, uint16 port)
{
	g_return_if_fail(vec);

	switch (host_addr_net(addr)) {
	case NET_TYPE_IPV4:
		if (vec->n_ipv4 < 255) {
			size_t size, old_size;
			char *dest;

			old_size = vec->n_ipv4 * sizeof vec->hvec_v4[0];
			size = old_size + sizeof vec->hvec_v4[0];
			vec->hvec_v4 = wrealloc(vec->hvec_v4, old_size, size);

			dest = cast_to_pointer(&vec->hvec_v4[vec->n_ipv4++]);
			poke_be32(&dest[0], host_addr_ipv4(addr));
			poke_le16(&dest[4], port);
		}
		break;
	case NET_TYPE_IPV6:
		if (vec->n_ipv6 < 255) {
			size_t size, old_size;
			char *dest;

			old_size = vec->n_ipv6 * sizeof vec->hvec_v6[0];
			size = old_size + sizeof vec->hvec_v6[0];
			vec->hvec_v6 = wrealloc(vec->hvec_v6, old_size, size);

			dest = cast_to_pointer(&vec->hvec_v6[vec->n_ipv6++]);
			dest = mempcpy(dest, host_addr_ipv6(&addr), 16);
			poke_le16(dest, port);
		}
		break;
	case NET_TYPE_LOCAL:
	case NET_TYPE_NONE:
		break;
	}
}
Esempio n. 7
0
/**
 * Serialization convenience for IP:port.
 *
 * Write the IP:port (IP as big-endian, port as little-endian) into the
 * supplied buffer, whose length MUST be 18 bytes at least.
 *
 * If len is non-NULL, it is written with the length of the serialized data.
 *
 * @return pointer following serialization data.
 */
void *
host_ip_port_poke(void *p, const host_addr_t addr, uint16 port, size_t *len)
{
	void *q = p;

	switch (host_addr_net(addr)) {
	case NET_TYPE_IPV4:
		q = poke_be32(q, host_addr_ipv4(addr));
		break;
	case NET_TYPE_IPV6:
		q = mempcpy(q, host_addr_ipv6(&addr), sizeof addr.addr.ipv6);
		break;
	case NET_TYPE_LOCAL:
	case NET_TYPE_NONE:
		g_assert_not_reached();
	}

	q = poke_le16(q, port);

	if (len != NULL)
		*len = ptr_diff(q, p);

	return q;
}
Esempio n. 8
0
/**
 * Create a security token from host address and port using specified key.
 *
 * Optionally, extra contextual data may be given (i.e. the token is not
 * only based on the address and port) to make the token more unique to
 * a specific context.
 *
 * @param stg		the security token generator
 * @param n			key index to use
 * @param tok		where security token is written
 * @param addr		address of the host for which we're generating a token
 * @param port		port of the host for which we're generating a token
 * @param data		optional contextual data
 * @param len		length of contextual data
 */
static void
sectoken_generate_n(sectoken_gen_t *stg, size_t n,
	sectoken_t *tok, host_addr_t addr, uint16 port,
	const void *data, size_t len)
{
	char block[8];
	char enc[8];
	char *p = block;

	sectoken_gen_check(stg);
	g_assert(tok != NULL);
	g_assert(size_is_non_negative(n));
	g_assert(n < stg->keycnt);
	g_assert((NULL != data) == (len != 0));

	switch (host_addr_net(addr)) {
	case NET_TYPE_IPV4:
		p = poke_be32(p, host_addr_ipv4(addr));
		break;
	case NET_TYPE_IPV6:
		{
			uint val;

			val = binary_hash(host_addr_ipv6(&addr), 16);
			p = poke_be32(p, val);
		}
		break;
	case NET_TYPE_LOCAL:
	case NET_TYPE_NONE:
		g_error("unexpected address for security token generation: %s",
			host_addr_to_string(addr));
	}

	p = poke_be16(p, port);
	p = poke_be16(p, 0);		/* Filler */

	g_assert(p == &block[8]);

	STATIC_ASSERT(sizeof(tok->v) == sizeof(uint32));
	STATIC_ASSERT(sizeof(block) == sizeof(enc));

	tea_encrypt(&stg->keys[n], enc, block, sizeof block);

	/*
	 * If they gave contextual data, encrypt them by block of 8 bytes,
	 * filling the last partial block with zeroes if needed.
	 */

	if (data != NULL) {
		const void *q = data;
		size_t remain = len;
		char denc[8];

		STATIC_ASSERT(sizeof(denc) == sizeof(enc));

		while (remain != 0) {
			size_t fill = MIN(remain, 8U);
			unsigned i;

			if (fill != 8U)
				ZERO(&block);

			memcpy(block, q, fill);
			remain -= fill;
			q = const_ptr_add_offset(q, fill);

			/*
			 * Encrypt block of contextual data (possibly filled with trailing
			 * zeroes) and merge back the result into the main encryption
			 * output with XOR.
			 */

			tea_encrypt(&stg->keys[n], denc, block, sizeof block);

			for (i = 0; i < sizeof denc; i++)
				enc[i] ^= denc[i];
		}
	}

	poke_be32(tok->v, tea_squeeze(enc, sizeof enc));
}
Esempio n. 9
0
/**
 * Create a new Gnutella host vector out of a sequence of gnet_host_t items.
 */
static gnet_host_vec_t *
gnet_host_vec_from_sequence(sequence_t *s)
{
	sequence_iter_t *iter;
	gnet_host_vec_t *vec;
	uint n_ipv6 = 0, n_ipv4 = 0, hcnt;

	if (sequence_is_empty(s))
		return NULL;

	hcnt = 0;
	iter = sequence_forward_iterator(s);
	while (sequence_iter_has_next(iter)) {
		const gnet_host_t *host = sequence_iter_next(iter);

		switch (gnet_host_get_net(host)) {
		case NET_TYPE_IPV4:
			n_ipv4++;
			hcnt++;
			break;
		case NET_TYPE_IPV6:
			n_ipv6++;
			hcnt++;
			break;
		case NET_TYPE_LOCAL:
		case NET_TYPE_NONE:
			break;
		}
	}
	sequence_iterator_release(&iter);
	if (0 == hcnt)
		return NULL;

	vec = gnet_host_vec_alloc();
	vec->n_ipv4 = MIN(n_ipv4, 255);
	vec->n_ipv6 = MIN(n_ipv6, 255);

	if (vec->n_ipv4 > 0)
		WALLOC_ARRAY(vec->hvec_v4, vec->n_ipv4);
	if (vec->n_ipv6 > 0)
		WALLOC_ARRAY(vec->hvec_v6, vec->n_ipv6);

	n_ipv4 = 0;
	n_ipv6 = 0;

	iter = sequence_forward_iterator(s);
	while (sequence_iter_has_next(iter)) {
		const gnet_host_t *host = sequence_iter_next(iter);
		host_addr_t addr = gnet_host_get_addr(host);
		uint16 port = gnet_host_get_port(host);

		switch (gnet_host_get_net(host)) {
		case NET_TYPE_IPV4:
			if (n_ipv4 < vec->n_ipv4) {
				char *dest = cast_to_pointer(&vec->hvec_v4[n_ipv4++]);
				poke_be32(&dest[0], host_addr_ipv4(addr));
				poke_le16(&dest[4], port);
			}
			break;
		case NET_TYPE_IPV6:
			if (n_ipv6 < vec->n_ipv6) {
				char *dest = cast_to_pointer(&vec->hvec_v6[n_ipv6++]);
				dest = mempcpy(dest, host_addr_ipv6(&addr), 16);
				poke_le16(dest, port);
			}
			break;
		case NET_TYPE_LOCAL:
		case NET_TYPE_NONE:
			break;
		}
	}
	sequence_iterator_release(&iter);
	return vec;
}