示例#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;
}
示例#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;
}
示例#3
0
/**
 * Parses IPv4 and IPv6 addresses. The latter requires IPv6 support to be
 * enabled.
 *
 * For convenience, if the first character is '[' then the address is parsed
 * as an IPv6 one and the trailing ']' is both expected and swallowed.  This
 * allows the routine to be used when parsing "ipv4:port" or "[ipv6]:port"
 * strings.
 *
 * @param s The string to parse.
 * @param endptr This will point to the first character after the parsed
 *        address.
 * @param addr_ptr If not NULL, it is set to the parsed host address or
 *        ``zero_host_addr'' on failure.
 * @return Returns TRUE on success; otherwise FALSE.
 */
bool
string_to_host_addr(const char *s, const char **endptr, host_addr_t *addr_ptr)
{
	uint32 ip;
	bool brackets = FALSE;

	g_assert(s);

	if ('[' == *s) {
		brackets = TRUE;
		s++;
	}

	if (!brackets && string_to_ip_strict(s, &ip, endptr)) {
		if (addr_ptr) {
			*addr_ptr = host_addr_get_ipv4(ip);
		}
		return TRUE;
	} else {
		uint8 ipv6[16];
		const char *end;
		bool ok;

		ok = parse_ipv6_addr(s, ipv6, &end);
		if (ok) {
			if (addr_ptr) {
				*addr_ptr = host_addr_peek_ipv6(ipv6);
			}
			if (brackets) {
				if (']' == *end) {
					end++;
				} else {
					ok = FALSE;		/* Trailing ']' required if we had '[' */
				}
			}
		}

		if (endptr != NULL)
			*endptr = end;
		if (ok)
			return TRUE;

		/* FALL THROUGH */
	}

	if (addr_ptr)
		*addr_ptr = zero_host_addr;
	return FALSE;
}
示例#4
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);
}