示例#1
0
static int
iprange_net4_collision(const void *p, const void *q)
{
	const struct iprange_net4 *a = p, *b = q;

	g_warning("iprange_sync(): %s/%u overlaps with %s/%u",
		ip_to_string(a->ip), a->bits,
		host_addr_to_string(host_addr_get_ipv4(b->ip)), b->bits);

	return a->bits < b->bits ? 1 : -1;
}
示例#2
0
static inline int
iprange_net_collision(const void *p, const void *q)
{
	const struct iprange_net *a = p, *b = q;

	g_warning("iprange_sync(): %s/0x%x overlaps with %s/0x%x",
		ip_to_string(a->ip), a->mask,
		host_addr_to_string(host_addr_get_ipv4(b->ip)), b->mask);

	return a->mask < b->mask ? 1 : -1;
}
示例#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
bool
host_addr_teredo_client(const host_addr_t from, host_addr_t *to)
{
	if (host_addr_is_teredo(from)) {
		if (to) {
			*to = host_addr_get_ipv4(host_addr_teredo_client_ipv4(from));
		}
		return TRUE;
	} else {
		if (to) {
			*to = zero_host_addr;
		}
		return FALSE;
	}
}
示例#5
0
/**
 * Default implementation to get the default gateway by parsing the
 * output of the "netstat -rn" command.
 *
 * @param addrp		where gateway address is to be written
 *
 * @return 0 on success, -1 on failure with errno set.
 */
static G_GNUC_COLD int
parse_netstat(host_addr_t *addrp)
#ifdef HAS_POPEN
{
	FILE *f = NULL;
	char tmp[80];
	uint32 gate = 0;

	/*
	 * This implementation should be a safe default on UNIX platforms, but
	 * it is inefficient and as such can only constitute a fallback.
	 */

	if (-1 != access("/bin/netstat", X_OK)) {
		f = popen("/bin/netstat -rn", "r");
	} else if (-1 != access("/usr/bin/netstat", X_OK)) {
		f = popen("/usr/bin/netstat -rn", "r");
	}

	if (NULL == f) {
		errno = ENOENT;		/* netstat not found */
		return -1;
	}

	/*
	 * Typical netstat -rn output:
	 *
	 * Destination        Gateway            Flags .....
	 * 0.0.0.0            192.168.0.200      UG
	 * default            192.168.0.200      UG
	 *
	 * Some systems like linux display "0.0.0.0", but traditional UNIX
	 * output is "default" for the default route.
	 */

	while (fgets(tmp, sizeof tmp, f)) {
		char *p;
		uint32 ip;

		p = is_strprefix(tmp, "default");
		if (NULL == p)
			p = is_strprefix(tmp, "0.0.0.0");

		if (NULL == p || !is_ascii_space(*p))
			continue;

		ip = string_to_ip(p);
		if (ip != 0) {
			gate = ip;
			break;
		}
	}

	pclose(f);

	if (0 == gate) {
		errno = ENETUNREACH;
		return -1;
	}

	*addrp = host_addr_get_ipv4(gate);
	return 0;
}
示例#6
0
/**
 * Handle reply to a discovery request.
 *
 * @param payload		the received reply
 * @param len			length of reply
 * @param rd			the RPC request descriptor
 *
 * @return TRUE if we successfully processed the reply and notified the
 * user code about the outcome of the request, FALSE if we need to resend
 * the request.
 */
static bool
natpmp_handle_discovery_reply(
	const void *payload, size_t len, struct natpmp_rpc *rd)
{
	bstr_t *bs;
	uint8 version;
	uint8 code;
	uint16 result;
	uint32 ip;
	host_addr_t wan_ip;
	natpmp_t *np;

	natpmp_rpc_check(rd);

	/**
	 * A NAT gateway will reply with the following message:
	 *
     *    0                   1                   2                   3
     *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     *   | Vers = 0      | OP = 128 + 0  | Result Code                   |
     *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     *   | Seconds Since Start of Epoch                                  |
     *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     *   | External IP Address (a.b.c.d)                                 |
     *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *
	 * The first 32-bits are always present, the remaining of the packet
	 * may or may not be there depending on the result code.
	 */

	bs = bstr_open(payload, len,
			GNET_PROPERTY(natpmp_debug) ? BSTR_F_ERROR : 0);

	/*
	 * Make sure we got a valid reply.
	 */

	bstr_read_u8(bs, &version);
	bstr_read_u8(bs, &code);
	bstr_read_be16(bs, &result);

	if (bstr_has_error(bs))
		goto error;

	if (GNET_PROPERTY(natpmp_debug) > 5) {
		g_debug("NATPMP version=%u, code=%u, result_code=%u (%s)",
			version, code, result, natpmp_strerror(result));
	}

	if (version != NATPMP_VERSION || code != NATPMP_REPLY_OFF + rd->op)
		goto error;

	if (NATPMP_E_OK != result)
		goto failed;

	bstr_read_be32(bs, &rd->sssoe);
	bstr_read_be32(bs, &ip);

	if (bstr_has_error(bs))
		goto error;

	wan_ip = host_addr_get_ipv4(ip);

	if (GNET_PROPERTY(natpmp_debug) > 5) {
		g_debug("NATPMP SSSOE=%u, WAN IP is %s",
			rd->sssoe, host_addr_to_string(wan_ip));
	}

	if (!host_addr_is_routable(wan_ip))
		goto failed;

	/*
	 * Good, we got a valid reply from the gateway, with a routable WAN IP.
	 */

	if (rd->np != NULL) {
		natpmp_check(rd->np);
		np = rd->np;
		natpmp_update(np, rd->sssoe);
		np->wan_ip = wan_ip;
	} else {
		np = natpmp_alloc(rd->gateway, rd->sssoe, wan_ip);
	}

	(*rd->cb.discovery)(TRUE, np, rd->arg);

	bstr_free(&bs);
	return TRUE;		/* OK */

failed:
	if (GNET_PROPERTY(natpmp_debug))
		g_warning("NATPMP did not find any suitable NAT-PMP gateway");

	(*rd->cb.discovery)(FALSE, rd->np, rd->arg);
	return TRUE;		/* We're done for now */

error:
	if (GNET_PROPERTY(natpmp_debug)) {
		if (bstr_has_error(bs)) {
			g_warning("NATPMP parsing error while processing discovery reply "
				"(%zu byte%s): %s",
				len, 1 == len ? "" : "s", bstr_error(bs));
		} else {
			g_warning("NATPMP inconsistent discovery reply (%zu byte%s)",
				len, 1 == len ? "" : "s");
		}
	}
	bstr_free(&bs);
	return FALSE;
}