Ejemplo n.º 1
0
static struct intf_config *if_addr_parse(char *s) {
	str name;
	char *c;
	sockaddr_t addr, adv;
	struct intf_config *ifa;

	/* name */
	c = strchr(s, '/');
	if (c) {
		*c++ = 0;
		str_init(&name, s);
		s = c;
	}
	else
		str_init(&name, "default");

	/* advertised address */
	c = strchr(s, '!');
	if (c)
		*c++ = 0;

	/* address */
	if (sockaddr_parse_any(&addr, s))
		return NULL;

	adv = addr;
	if (c) {
		if (sockaddr_parse_any(&adv, c))
			return NULL;
	}

	ifa = g_slice_alloc0(sizeof(*ifa));
	ifa->name = name;
	ifa->address.addr = addr;
	ifa->address.advertised = adv;
	ifa->port_min = port_min;
	ifa->port_max = port_max;

	return ifa;
}
Ejemplo n.º 2
0
static int if_addr_parse(GQueue *q, char *s, struct ifaddrs *ifas) {
	str name;
	char *c;
	sockaddr_t *addr, adv;
	GQueue addrs = G_QUEUE_INIT;
	struct intf_config *ifa;

	/* name */
	c = strchr(s, '/');
	if (c) {
		*c++ = 0;
		str_init(&name, s);
		s = c;
	}
	else
		str_init(&name, "default");

	/* advertised address */
	c = strchr(s, '!');
	if (c)
		*c++ = 0;

	/* address */
	addr = g_slice_alloc(sizeof(*addr));
	if (!sockaddr_parse_any(addr, s)) {
		if (is_addr_unspecified(addr))
			return -1;
		g_queue_push_tail(&addrs, addr);
	}
	else {
		// could be an interface name?
		ilog(LOG_DEBUG, "Could not parse '%s' as network address, checking to see if "
				"it's an interface", s);
		for (struct ifaddrs *ifa = ifas; ifa; ifa = ifa->ifa_next) {
			if (strcmp(ifa->ifa_name, s))
				continue;
			if (!(ifa->ifa_flags & IFF_UP))
				continue;
			if (!ifa->ifa_addr)
				continue;
			if (ifa->ifa_addr->sa_family == AF_INET) {
				struct sockaddr_in *sin = (void *) ifa->ifa_addr;
				addr->family = __get_socket_family_enum(SF_IP4);
				addr->u.ipv4 = sin->sin_addr;
			}
			else if (ifa->ifa_addr->sa_family == AF_INET6) {
				struct sockaddr_in6 *sin = (void *) ifa->ifa_addr;
				if (sin->sin6_scope_id)
					continue; // link-local
				addr->family = __get_socket_family_enum(SF_IP6);
				addr->u.ipv6 = sin->sin6_addr;
			}
			else
				continue;

			// got one
			ilog(LOG_DEBUG, "Determined address %s for interface '%s'",
					sockaddr_print_buf(addr), s);
			g_queue_push_tail(&addrs, addr);
			addr = g_slice_alloc(sizeof(*addr));
		}

		// free last unused entry
		g_slice_free1(sizeof(*addr), addr);
	}

	if (!addrs.length) // nothing found
		return -1;

	ZERO(adv);
	if (c) {
		if (sockaddr_parse_any(&adv, c))
			return -1;
		if (is_addr_unspecified(&adv))
			return -1;
	}

	while ((addr = g_queue_pop_head(&addrs))) {
		ifa = g_slice_alloc0(sizeof(*ifa));
		ifa->name = name;
		ifa->local_address.addr = *addr;
		ifa->local_address.type = socktype_udp;
		ifa->advertised_address.addr = adv;
		if (is_addr_unspecified(&ifa->advertised_address.addr))
			ifa->advertised_address.addr = *addr;
		ifa->advertised_address.type = ifa->local_address.type;
		ifa->port_min = rtpe_config.port_min;
		ifa->port_max = rtpe_config.port_max;

		// handle "base:suffix" separation for round-robin selection
		ifa->name_rr_spec = ifa->name;
		str_token(&ifa->name_base, &ifa->name_rr_spec, ':'); // sets name_rr_spec to null string if no ':' found

		g_queue_push_tail(q, ifa);

		g_slice_free1(sizeof(*addr), addr);
	}

	return 0;
}