Ejemplo n.º 1
0
/**
 * Fill `p_addr' with the socket's local address/port information.
 */
int
socket_addr_getsockname(socket_addr_t *p_addr, int fd)
{
	struct sockaddr_in sin4;
	socklen_t len;
	host_addr_t addr = zero_host_addr;
	uint16 port = 0;
	bool success = FALSE;

	len = sizeof sin4;
	if (-1 != getsockname(fd, cast_to_pointer(&sin4), &len)) {
		addr = host_addr_peek_ipv4(&sin4.sin_addr.s_addr);
		port = ntohs(sin4.sin_port);
		success = TRUE;
	}

#ifdef HAS_IPV6
	if (!success) {
		struct sockaddr_in6 sin6;

		len = sizeof sin6;
		if (-1 != getsockname(fd, cast_to_pointer(&sin6), &len)) {
			addr = host_addr_peek_ipv6(sin6.sin6_addr.s6_addr);
			port = ntohs(sin6.sin6_port);
			success = TRUE;
		}
	}
#endif	/* HAS_IPV6 */

	if (success) {
		socket_addr_set(p_addr, addr, port);
	}
	return success ? 0 : -1;
}
Ejemplo n.º 2
0
host_addr_t
addrinfo_to_addr(const struct addrinfo *ai)
{
	host_addr_t addr = zero_host_addr;

	switch (ai->ai_family) {
	case PF_INET:
		if (ai->ai_addrlen >= 4) {
			const struct sockaddr_in *sin4;

			sin4 = cast_to_constpointer(ai->ai_addr);
			addr = host_addr_peek_ipv4(&sin4->sin_addr.s_addr);
		}
		break;

#ifdef HAS_IPV6
	case PF_INET6:
		if (ai->ai_addrlen >= 16) {
			const struct sockaddr_in6 *sin6;

			sin6 = cast_to_constpointer(ai->ai_addr);
			addr = host_addr_peek_ipv6(cast_to_constpointer(
						sin6->sin6_addr.s6_addr));
		}
		break;
#endif /* HAS_IPV6 */
	}

	return addr;
}
Ejemplo n.º 3
0
/**
 * Extract the IP and port number from the GUID of queries marked for OOB
 * query hit delivery.
 *
 * Bytes 0 to 3 of the guid are the 4 octet bytes of the IP address.
 * Bytes 13 and 14 are the little endian representation of the port.
 */
void
guid_oob_get_addr_port(const guid_t *guid, host_addr_t *addr, uint16 *port)
{
	if (addr) {
		/*
		 * IPv6-Ready: this is always 4 bytes, even if the final address is
		 * an IPv6 one because the GGEP "6" key will supply us the IPv6
		 * address should the IPv4 one be 127.0.0.0.
		 */
		*addr = host_addr_peek_ipv4(&guid->v[0]);
	}
	if (port) {
		*port = peek_le16(&guid->v[13]);
	}
}
Ejemplo n.º 4
0
/**
 * Tries to convert the host address "from" to the network type "to_net"
 * and stores the converted address in "*to". If conversion is not possible,
 * FALSE is returned and "*to" is set to zero_host_addr.
 *
 * @param from The address to convert.
 * @param to Will hold the converted address.
 * @param to_net The network type to convert the address to.
 * 
 * @return TRUE if the address could be converted, FALSE otherwise.
 */
bool
host_addr_convert(const host_addr_t from, host_addr_t *to,
	enum net_type to_net)
{
	if (from.net == to_net) {
		*to = from;
		return TRUE;
	}

	switch (to_net) {
	case NET_TYPE_IPV4:
		switch (from.net) {
		case NET_TYPE_IPV6:
			if (host_addr_can_convert(from, NET_TYPE_IPV4)) {
				*to = host_addr_peek_ipv4(&from.addr.ipv6[12]);
				return TRUE;
			}
			break;
		case NET_TYPE_LOCAL:
		case NET_TYPE_NONE:
			break;
		}
		break;

	case NET_TYPE_IPV6:
		switch (from.net) {
		case NET_TYPE_IPV4:
			to->net = to_net;
			memset(to->addr.ipv6, 0, 10);
			to->addr.ipv6[10] = 0xff;
			to->addr.ipv6[11] = 0xff;
			poke_be32(&to->addr.ipv6[12], host_addr_ipv4(from));
			return TRUE;
		case NET_TYPE_NONE:
			break;
		}
		break;

	case NET_TYPE_LOCAL:
	case NET_TYPE_NONE:
		break;
	}

	*to = zero_host_addr;
	return FALSE;
}
Ejemplo n.º 5
0
/**
 * Deserialization convenience for IP:port.
 *
 * The supplied buffer must hold either 6 or 18 more bytes of data, depending
 * on the address type we want to deserialize.
 */
void
host_ip_port_peek(const void *p, enum net_type nt,
	host_addr_t *addr, uint16 *port)
{
	const void *q = p;

	if (NET_TYPE_IPV4 == nt) {
		*addr = host_addr_peek_ipv4(q);
		q = const_ptr_add_offset(q, 4);
	} else if (NET_TYPE_IPV6 == nt) {
		*addr = host_addr_peek_ipv6(q);
		q = const_ptr_add_offset(q, 16);
	} else {
		/* Can only deserialize IPv4:port or IPv6:port */
		g_assert_not_reached();
	}
	*port = peek_le16(q);
}
Ejemplo n.º 6
0
/**
 * Extract the UDP IP:port from a /Q2/UDP and populate the search request info
 * if we have a valid address.
 */
static void
g2_node_extract_udp(const g2_tree_t *t, search_request_info_t *sri,
	const gnutella_node_t *n)
{
	const char *p;
	size_t paylen;

	p = g2_tree_node_payload(t, &paylen);

	/*
	 * Only handle if we have an IP:port entry.
	 * We only handle IPv4 because G2 does not support IPv6.
	 *
	 * We don't care about the presence of the query key because as G2 leaf,
	 * we only process /Q2 coming from our TCP-connected hubs, and they
	 * are in charge of validating it.  Now hubs may forward us /Q2 coming
	 * from neighbouring hubs and those won't have a query key, hence we
	 * need to handle payloads with no trailing 32-bit QK.
	 */

	if (6 == paylen || 10 == paylen) {	/* IPv4 + port (+ QK usually) */
		host_addr_t addr = host_addr_peek_ipv4(p);
		uint16 port = peek_le16(&p[4]);

		if (host_is_valid(addr, port)) {
			sri->addr = addr;
			sri->port = port;

			/*
			 * If the address is that of the node sending us the query,
			 * and it is not a UDP node, then we can deliver the hit
			 * back via the TCP connection we have, so no need to use OOB.
			 */

			if (n->port == port && host_addr_equiv(addr, n->gnet_addr))
				sri->oob = NODE_IS_UDP(n);
			else
				sri->oob = TRUE;
		}
	}
}
Ejemplo n.º 7
0
/**
 * Parse the payload of given node to extract a node address + port.
 *
 * @param t		the tree node whose payload we wish to parse
 * @param addr	where to write the address part
 * @param port	where to write the port part
 *
 * @return TRUE if OK, FALSE if we could not extract anything.
 */
bool
g2_node_parse_address(const g2_tree_t *t, host_addr_t *addr, uint16 *port)
{
	const char *payload;
	size_t paylen;

	payload = g2_tree_node_payload(t, &paylen);

	/*
	 * Only handle if we have an IP:port entry.
	 * We only handle IPv4 because G2 does not support IPv6.
	 */

	if (6 == paylen) {		/* IPv4 + port */
		*addr = host_addr_peek_ipv4(payload);
		*port = peek_le16(&payload[4]);
		return TRUE;
	}

	return FALSE;		/* Unrecognized payload length */
}
Ejemplo n.º 8
0
/**
 * Tree message iterator to handle "CH" nodes and extract their IP:port.
 */
static void
g2_node_extract_ch(void *data, void *udata)
{
	const g2_tree_t *t = data;

	(void) udata;

	if (0 == strcmp("CH", g2_tree_name(t))) {
		const char *payload;
		size_t paylen;

		payload = g2_tree_node_payload(t, &paylen);

		if (10 == paylen) {		/* IPv4:port + 32-bit timestamp */
			host_addr_t addr = host_addr_peek_ipv4(payload);
			uint16 port = peek_le16(&payload[4]);

			if (host_is_valid(addr, port) && !hostiles_is_bad(addr))
				guess_add_hub(addr, port);
		}
	}
}