Example #1
0
static int
dump_domains(int argc, char** argv)
{
	DomainList::Iterator iterator = sDomains.GetIterator();
	while (net_domain_private* domain = iterator.Next()) {
		kprintf("domain: %p, %s, %d\n", domain, domain->name, domain->family);
		kprintf("  module:         %p\n", domain->module);
		kprintf("  address_module: %p\n", domain->address_module);

		if (!domain->routes.IsEmpty())
			kprintf("  routes:\n");
	
		RouteList::Iterator routeIterator = domain->routes.GetIterator();
		while (net_route_private* route = routeIterator.Next()) {
			kprintf("    %p: dest %s, mask %s, gw %s, flags %" B_PRIx32 ", "
				"address %p\n", route, AddressString(domain, route->destination
					? route->destination : NULL).Data(),
				AddressString(domain, route->mask ? route->mask : NULL).Data(),
				AddressString(domain, route->gateway
					? route->gateway : NULL).Data(),
				route->flags, route->interface_address);
		}

		if (!domain->route_infos.IsEmpty())
			kprintf("  route infos:\n");
	
		RouteInfoList::Iterator infoIterator = domain->route_infos.GetIterator();
		while (net_route_info* info = infoIterator.Next()) {
			kprintf("    %p\n", info);
		}
	}

	return 0;
}
Example #2
0
static struct net_route*
get_route_internal(struct net_domain_private* domain,
	const struct sockaddr* address)
{
	ASSERT_LOCKED_RECURSIVE(&domain->lock);
	net_route_private* route = NULL;

	if (address->sa_family == AF_LINK) {
		// special address to find an interface directly
		RouteList::Iterator iterator = domain->routes.GetIterator();
		const sockaddr_dl* link = (const sockaddr_dl*)address;

		while (iterator.HasNext()) {
			route = iterator.Next();

			net_device* device = route->interface_address->interface->device;

			if ((link->sdl_nlen > 0
					&& !strncmp(device->name, (const char*)link->sdl_data,
							IF_NAMESIZE))
				|| (link->sdl_nlen == 0 && link->sdl_alen > 0
					&& !memcmp(LLADDR(link), device->address.data,
							device->address.length)))
				break;
		}
	} else
		route = find_route(domain, address);

	if (route != NULL && atomic_add(&route->ref_count, 1) == 0) {
		// route has been deleted already
		route = NULL;
	}

	return route;
}
Example #3
0
static net_route_private*
find_route(struct net_domain* _domain, const net_route* description)
{
	struct net_domain_private* domain = (net_domain_private*)_domain;
	RouteList::Iterator iterator = domain->routes.GetIterator();

	while (iterator.HasNext()) {
		net_route_private* route = iterator.Next();

		if ((route->flags & RTF_DEFAULT) != 0
			&& (description->flags & RTF_DEFAULT) != 0) {
			// there can only be one default route per interface address family
			// TODO: check this better
			if (route->interface_address == description->interface_address)
				return route;

			continue;
		}

		if ((route->flags & (RTF_GATEWAY | RTF_HOST | RTF_LOCAL | RTF_DEFAULT))
				== (description->flags
					& (RTF_GATEWAY | RTF_HOST | RTF_LOCAL | RTF_DEFAULT))
			&& domain->address_module->equal_masked_addresses(
				route->destination, description->destination, description->mask)
			&& domain->address_module->equal_addresses(route->mask,
				description->mask)
			&& domain->address_module->equal_addresses(route->gateway,
				description->gateway)
			&& (description->interface_address == NULL
				|| description->interface_address == route->interface_address))
			return route;
	}

	return NULL;
}
Example #4
0
static net_route_private*
find_route(net_domain* _domain, const sockaddr* address)
{
	net_domain_private* domain = (net_domain_private*)_domain;

	// find last matching route

	RouteList::Iterator iterator = domain->routes.GetIterator();
	net_route_private* candidate = NULL;

	TRACE("test address %s for routes...\n",
		AddressString(domain, address).Data());

	// TODO: alternate equal default routes

	while (iterator.HasNext()) {
		net_route_private* route = iterator.Next();

		if (route->mask) {
			sockaddr maskedAddress;
			domain->address_module->mask_address(address, route->mask,
				&maskedAddress);
			if (!domain->address_module->equal_addresses(&maskedAddress,
					route->destination))
				continue;
		} else if (!domain->address_module->equal_addresses(address,
				route->destination))
			continue;

		// neglect routes that point to devices that have no link
		if ((route->interface_address->interface->device->flags & IFF_LINK)
				== 0) {
			if (candidate == NULL) {
				TRACE("  found candidate: %s, flags %lx\n", AddressString(
					domain, route->destination).Data(), route->flags);
				candidate = route;
			}
			continue;
		}

		TRACE("  found route: %s, flags %lx\n",
			AddressString(domain, route->destination).Data(), route->flags);

		return route;
	}

	return candidate;
}
Example #5
0
void
invalidate_routes(net_domain* _domain, net_interface* interface)
{
	net_domain_private* domain = (net_domain_private*)_domain;
	RecursiveLocker locker(domain->lock);

	TRACE("invalidate_routes(%i, %s)\n", domain->family, interface->name);

	RouteList::Iterator iterator = domain->routes.GetIterator();
	while (iterator.HasNext()) {
		net_route* route = iterator.Next();

		if (route->interface_address->interface == interface)
			remove_route(domain, route);
	}
}
Example #6
0
void
invalidate_routes(InterfaceAddress* address)
{
	net_domain_private* domain = (net_domain_private*)address->domain;

	TRACE("invalidate_routes(%s)\n",
		AddressString(domain, address->local).Data());

	RecursiveLocker locker(domain->lock);

	RouteList::Iterator iterator = domain->routes.GetIterator();
	while (iterator.HasNext()) {
		net_route* route = iterator.Next();

		if (route->interface_address == address)
			remove_route(domain, route);
	}
}
Example #7
0
static int
dump_domains(int argc, char** argv)
{
	DomainList::Iterator iterator = sDomains.GetIterator();
	while (net_domain_private* domain = iterator.Next()) {
		kprintf("domain: %p, %s, %d\n", domain, domain->name, domain->family);
		kprintf("  module:         %p\n", domain->module);
		kprintf("  address_module: %p\n", domain->address_module);
		
		if (!list_is_empty(&domain->interfaces))
			kprintf("  interfaces:\n");

		net_interface* interface = NULL;
		while (true) {
			interface = (net_interface*)list_get_next_item(&domain->interfaces,
				interface);
			if (interface == NULL)
				break;

			kprintf("    %p\n", interface);
		}

		if (!domain->routes.IsEmpty())
			kprintf("  routes:\n");
	
		RouteList::Iterator routeIterator = domain->routes.GetIterator();
		while (net_route* route = routeIterator.Next()) {
			kprintf("    %p\n", route);
		}

		if (!domain->route_infos.IsEmpty())
			kprintf("  route infos:\n");
	
		RouteInfoList::Iterator infoIterator = domain->route_infos.GetIterator();
		while (net_route_info* info = infoIterator.Next()) {
			kprintf("    %p\n", info);
		}
	}

	return 0;
}
Example #8
0
/*!	Determines the size of a buffer large enough to contain the whole
	routing table.
*/
uint32
route_table_size(net_domain_private* domain)
{
	RecursiveLocker locker(domain->lock);
	uint32 size = 0;

	RouteList::Iterator iterator = domain->routes.GetIterator();
	while (iterator.HasNext()) {
		net_route_private* route = iterator.Next();
		size += IF_NAMESIZE + sizeof(route_entry);

		if (route->destination)
			size += route->destination->sa_len;
		if (route->mask)
			size += route->mask->sa_len;
		if (route->gateway)
			size += route->gateway->sa_len;
	}

	return size;
}
Example #9
0
status_t
add_route(struct net_domain* _domain, const struct net_route* newRoute)
{
	struct net_domain_private* domain = (net_domain_private*)_domain;

	TRACE("add route to domain %s: dest %s, mask %s, gw %s, flags %lx\n",
		domain->name,
		AddressString(domain, newRoute->destination
			? newRoute->destination : NULL).Data(),
		AddressString(domain, newRoute->mask ? newRoute->mask : NULL).Data(),
		AddressString(domain, newRoute->gateway
			? newRoute->gateway : NULL).Data(),
		newRoute->flags);

	if (domain == NULL || newRoute == NULL
		|| newRoute->interface_address == NULL
		|| ((newRoute->flags & RTF_HOST) != 0 && newRoute->mask != NULL)
		|| ((newRoute->flags & RTF_DEFAULT) == 0
			&& newRoute->destination == NULL)
		|| ((newRoute->flags & RTF_GATEWAY) != 0 && newRoute->gateway == NULL)
		|| !domain->address_module->check_mask(newRoute->mask))
		return B_BAD_VALUE;

	RecursiveLocker _(domain->lock);

	net_route_private* route = find_route(domain, newRoute);
	if (route != NULL)
		return B_FILE_EXISTS;

	route = new (std::nothrow) net_route_private;
	if (route == NULL)
		return B_NO_MEMORY;

	if (domain->address_module->copy_address(newRoute->destination,
			&route->destination, (newRoute->flags & RTF_DEFAULT) != 0,
			newRoute->mask) != B_OK
		|| domain->address_module->copy_address(newRoute->mask, &route->mask,
			(newRoute->flags & RTF_DEFAULT) != 0, NULL) != B_OK
		|| domain->address_module->copy_address(newRoute->gateway,
			&route->gateway, false, NULL) != B_OK) {
		delete route;
		return B_NO_MEMORY;
	}

	route->flags = newRoute->flags;
	route->interface_address = newRoute->interface_address;
	((InterfaceAddress*)route->interface_address)->AcquireReference();
	route->mtu = 0;
	route->ref_count = 1;

	// Insert the route sorted by completeness of its mask

	RouteList::Iterator iterator = domain->routes.GetIterator();
	net_route_private* before = NULL;

	while ((before = iterator.Next()) != NULL) {
		// if the before mask is less specific than the one of the route,
		// we can insert it before that route.
		if (domain->address_module->first_mask_bit(before->mask)
				> domain->address_module->first_mask_bit(route->mask))
			break;

		if ((route->flags & RTF_DEFAULT) != 0
			&& (before->flags & RTF_DEFAULT) != 0) {
			// both routes are equal - let the link speed decide the
			// order
			if (before->interface_address->interface->device->link_speed
					< route->interface_address->interface->device->link_speed)
				break;
		}
	}

	domain->routes.Insert(before, route);
	update_route_infos(domain);

	return B_OK;
}
Example #10
0
/*!	Dumps a list of all routes into the supplied userland buffer.
	If the routes don't fit into the buffer, an error (\c ENOBUFS) is
	returned.
*/
status_t
list_routes(net_domain_private* domain, void* buffer, size_t size)
{
	RecursiveLocker _(domain->lock);

	RouteList::Iterator iterator = domain->routes.GetIterator();
	size_t spaceLeft = size;

	sockaddr zeros;
	memset(&zeros, 0, sizeof(sockaddr));
	zeros.sa_family = domain->family;
	zeros.sa_len = sizeof(sockaddr);

	while (iterator.HasNext()) {
		net_route* route = iterator.Next();

		size = IF_NAMESIZE + sizeof(route_entry);

		sockaddr* destination = NULL;
		sockaddr* mask = NULL;
		sockaddr* gateway = NULL;
		uint8* next = (uint8*)buffer + size;

		if (route->destination != NULL) {
			destination = (sockaddr*)next;
			next += route->destination->sa_len;
			size += route->destination->sa_len;
		}
		if (route->mask != NULL) {
			mask = (sockaddr*)next;
			next += route->mask->sa_len;
			size += route->mask->sa_len;
		}
		if (route->gateway != NULL) {
			gateway = (sockaddr*)next;
			next += route->gateway->sa_len;
			size += route->gateway->sa_len;
		}

		if (spaceLeft < size)
			return ENOBUFS;

		ifreq request;
		strlcpy(request.ifr_name, route->interface_address->interface->name,
			IF_NAMESIZE);
		request.ifr_route.destination = destination;
		request.ifr_route.mask = mask;
		request.ifr_route.gateway = gateway;
		request.ifr_route.mtu = route->mtu;
		request.ifr_route.flags = route->flags;

		// copy data into userland buffer
		if (user_memcpy(buffer, &request, size) < B_OK
			|| (route->destination != NULL
				&& user_memcpy(request.ifr_route.destination,
					route->destination, route->destination->sa_len) < B_OK)
			|| (route->mask != NULL && user_memcpy(request.ifr_route.mask,
					route->mask, route->mask->sa_len) < B_OK)
			|| (route->gateway != NULL && user_memcpy(request.ifr_route.gateway,
					route->gateway, route->gateway->sa_len) < B_OK))
			return B_BAD_ADDRESS;

		buffer = (void*)next;
		spaceLeft -= size;
	}

	return B_OK;
}