xref: /haiku/src/add-ons/kernel/network/stack/interfaces.cpp (revision 910ffb32fee4d6e04cd47f915a0e4e5292e05e0e)
1c22d69bfSAxel Dörfler /*
261729d93SAxel Dörfler  * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3c22d69bfSAxel Dörfler  * Distributed under the terms of the MIT License.
4c22d69bfSAxel Dörfler  *
5c22d69bfSAxel Dörfler  * Authors:
6c22d69bfSAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
7c22d69bfSAxel Dörfler  */
8c22d69bfSAxel Dörfler 
9c22d69bfSAxel Dörfler 
10c22d69bfSAxel Dörfler #include "interfaces.h"
11c22d69bfSAxel Dörfler 
12c22d69bfSAxel Dörfler #include <net/if_dl.h>
13c22d69bfSAxel Dörfler #include <new>
14a1deb55eSHugo Santos #include <stdio.h>
15c22d69bfSAxel Dörfler #include <stdlib.h>
16c22d69bfSAxel Dörfler #include <string.h>
1761729d93SAxel Dörfler #include <sys/sockio.h>
1861729d93SAxel Dörfler 
1961729d93SAxel Dörfler #include <KernelExport.h>
2061729d93SAxel Dörfler 
2161729d93SAxel Dörfler #include <net_device.h>
22b0cf274aSAxel Dörfler #include <NetUtilities.h>
2361729d93SAxel Dörfler 
2461729d93SAxel Dörfler #include "device_interfaces.h"
2561729d93SAxel Dörfler #include "domains.h"
2661729d93SAxel Dörfler #include "stack_private.h"
2761729d93SAxel Dörfler #include "utility.h"
28c22d69bfSAxel Dörfler 
29c22d69bfSAxel Dörfler 
3061729d93SAxel Dörfler //#define TRACE_INTERFACES
31c22d69bfSAxel Dörfler #ifdef TRACE_INTERFACES
3261729d93SAxel Dörfler #	define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x)
33c22d69bfSAxel Dörfler #else
3461729d93SAxel Dörfler #	define TRACE(x...) ;
35c22d69bfSAxel Dörfler #endif
36c22d69bfSAxel Dörfler 
3761729d93SAxel Dörfler 
3861729d93SAxel Dörfler struct AddressHashDefinition {
3961729d93SAxel Dörfler 	typedef const sockaddr* KeyType;
4061729d93SAxel Dörfler 	typedef InterfaceAddress ValueType;
4161729d93SAxel Dörfler 
4261729d93SAxel Dörfler 	AddressHashDefinition()
4361729d93SAxel Dörfler 	{
4461729d93SAxel Dörfler 	}
4561729d93SAxel Dörfler 
4661729d93SAxel Dörfler 	size_t HashKey(const KeyType& key) const
4761729d93SAxel Dörfler 	{
4861729d93SAxel Dörfler 		net_domain* domain = get_domain(key->sa_family);
4961729d93SAxel Dörfler 		if (domain == NULL)
5061729d93SAxel Dörfler 			return 0;
5161729d93SAxel Dörfler 
5261729d93SAxel Dörfler 		return domain->address_module->hash_address(key, false);
5361729d93SAxel Dörfler 	}
5461729d93SAxel Dörfler 
5561729d93SAxel Dörfler 	size_t Hash(InterfaceAddress* address) const
5661729d93SAxel Dörfler 	{
5761729d93SAxel Dörfler 		return address->domain->address_module->hash_address(address->local, false);
5861729d93SAxel Dörfler 	}
5961729d93SAxel Dörfler 
6061729d93SAxel Dörfler 	bool Compare(const KeyType& key, InterfaceAddress* address) const
6161729d93SAxel Dörfler 	{
6261729d93SAxel Dörfler 		if (address->local == NULL)
6361729d93SAxel Dörfler 			return key->sa_family == AF_UNSPEC;
6461729d93SAxel Dörfler 
6561729d93SAxel Dörfler 		if (address->local->sa_family != key->sa_family)
6661729d93SAxel Dörfler 			return false;
6761729d93SAxel Dörfler 
6861729d93SAxel Dörfler 		return address->domain->address_module->equal_addresses(key,
6961729d93SAxel Dörfler 			address->local);
7061729d93SAxel Dörfler 	}
7161729d93SAxel Dörfler 
7261729d93SAxel Dörfler 	InterfaceAddress*& GetLink(InterfaceAddress* address) const
7361729d93SAxel Dörfler 	{
7461729d93SAxel Dörfler 		return address->HashTableLink();
7561729d93SAxel Dörfler 	}
7661729d93SAxel Dörfler };
7761729d93SAxel Dörfler 
7861729d93SAxel Dörfler typedef BOpenHashTable<AddressHashDefinition, true, true> AddressTable;
79a3ec278aSAxel Dörfler 
80c22d69bfSAxel Dörfler 
8161729d93SAxel Dörfler static mutex sLock;
8261729d93SAxel Dörfler static InterfaceList sInterfaces;
8361729d93SAxel Dörfler static mutex sHashLock;
8461729d93SAxel Dörfler static AddressTable sAddressTable;
85c22d69bfSAxel Dörfler static uint32 sInterfaceIndex;
869261b129SHugo Santos 
879261b129SHugo Santos 
88a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
89a3ec278aSAxel Dörfler 
90a3ec278aSAxel Dörfler 
91a3ec278aSAxel Dörfler static int
92a3ec278aSAxel Dörfler dump_interface(int argc, char** argv)
93a3ec278aSAxel Dörfler {
94a3ec278aSAxel Dörfler 	if (argc != 2) {
95a3ec278aSAxel Dörfler 		kprintf("usage: %s [address]\n", argv[0]);
96a3ec278aSAxel Dörfler 		return 0;
97a3ec278aSAxel Dörfler 	}
98a3ec278aSAxel Dörfler 
9961729d93SAxel Dörfler 	Interface* interface = (Interface*)parse_expression(argv[1]);
10061729d93SAxel Dörfler 	interface->Dump();
101a3ec278aSAxel Dörfler 
102a3ec278aSAxel Dörfler 	return 0;
103a3ec278aSAxel Dörfler }
104a3ec278aSAxel Dörfler 
105a3ec278aSAxel Dörfler 
106a3ec278aSAxel Dörfler static int
10761729d93SAxel Dörfler dump_interfaces(int argc, char** argv)
10861729d93SAxel Dörfler {
10961729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
11061729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
11161729d93SAxel Dörfler 		kprintf("%p  %s\n", interface, interface->name);
11261729d93SAxel Dörfler 	}
11361729d93SAxel Dörfler 	return 0;
11461729d93SAxel Dörfler }
11561729d93SAxel Dörfler 
11661729d93SAxel Dörfler 
11761729d93SAxel Dörfler static int
11861729d93SAxel Dörfler dump_local(int argc, char** argv)
11961729d93SAxel Dörfler {
12061729d93SAxel Dörfler 	AddressTable::Iterator iterator = sAddressTable.GetIterator();
12161729d93SAxel Dörfler 	size_t i = 0;
12261729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
12361729d93SAxel Dörfler 		address->Dump(++i);
12461729d93SAxel Dörfler 		dprintf("    hash:          %lu\n",
12561729d93SAxel Dörfler 			address->domain->address_module->hash_address(address->local,
12661729d93SAxel Dörfler 				false));
12761729d93SAxel Dörfler 	}
12861729d93SAxel Dörfler 	return 0;
12961729d93SAxel Dörfler }
13061729d93SAxel Dörfler 
13161729d93SAxel Dörfler 
13261729d93SAxel Dörfler static int
13361729d93SAxel Dörfler dump_route(int argc, char** argv)
134a3ec278aSAxel Dörfler {
135a3ec278aSAxel Dörfler 	if (argc != 2) {
136a3ec278aSAxel Dörfler 		kprintf("usage: %s [address]\n", argv[0]);
137a3ec278aSAxel Dörfler 		return 0;
138a3ec278aSAxel Dörfler 	}
139a3ec278aSAxel Dörfler 
14061729d93SAxel Dörfler 	net_route* route = (net_route*)parse_expression(argv[1]);
14161729d93SAxel Dörfler 	kprintf("destination:       %p\n", route->destination);
14261729d93SAxel Dörfler 	kprintf("mask:              %p\n", route->mask);
14361729d93SAxel Dörfler 	kprintf("gateway:           %p\n", route->gateway);
14461729d93SAxel Dörfler 	kprintf("flags:             %" B_PRIx32 "\n", route->flags);
14561729d93SAxel Dörfler 	kprintf("mtu:               %" B_PRIu32 "\n", route->mtu);
14661729d93SAxel Dörfler 	kprintf("interface address: %p\n", route->interface_address);
147a3ec278aSAxel Dörfler 
14861729d93SAxel Dörfler 	if (route->interface_address != NULL) {
14961729d93SAxel Dörfler 		((InterfaceAddress*)route->interface_address)->Dump();
150a3ec278aSAxel Dörfler 	}
151a3ec278aSAxel Dörfler 
152a3ec278aSAxel Dörfler 	return 0;
153a3ec278aSAxel Dörfler }
154a3ec278aSAxel Dörfler 
155a3ec278aSAxel Dörfler 
156a3ec278aSAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
157a3ec278aSAxel Dörfler 
158a3ec278aSAxel Dörfler 
15961729d93SAxel Dörfler InterfaceAddress::InterfaceAddress()
160c22d69bfSAxel Dörfler {
16161729d93SAxel Dörfler 	_Init(NULL, NULL);
16261729d93SAxel Dörfler }
163c22d69bfSAxel Dörfler 
16461729d93SAxel Dörfler 
16561729d93SAxel Dörfler InterfaceAddress::InterfaceAddress(net_interface* netInterface,
16661729d93SAxel Dörfler 	net_domain* netDomain)
16761729d93SAxel Dörfler {
16861729d93SAxel Dörfler 	_Init(netInterface, netDomain);
16961729d93SAxel Dörfler }
17061729d93SAxel Dörfler 
17161729d93SAxel Dörfler 
17261729d93SAxel Dörfler InterfaceAddress::~InterfaceAddress()
17361729d93SAxel Dörfler {
1742b1c0755SAxel Dörfler 	TRACE("InterfaceAddress %p: destructor\n", this);
1752b1c0755SAxel Dörfler 
1762b1c0755SAxel Dörfler 	if (interface != NULL && (flags & IFAF_DIRECT_ADDRESS) == 0)
1772b1c0755SAxel Dörfler 		((Interface*)interface)->ReleaseReference();
17861729d93SAxel Dörfler }
17961729d93SAxel Dörfler 
18061729d93SAxel Dörfler 
18161729d93SAxel Dörfler status_t
18261729d93SAxel Dörfler InterfaceAddress::SetTo(const ifaliasreq& request)
18361729d93SAxel Dörfler {
18461729d93SAxel Dörfler 	status_t status = SetLocal((const sockaddr*)&request.ifra_addr);
18561729d93SAxel Dörfler 	if (status == B_OK)
18661729d93SAxel Dörfler 		status = SetDestination((const sockaddr*)&request.ifra_broadaddr);
18761729d93SAxel Dörfler 	if (status == B_OK)
18861729d93SAxel Dörfler 		status = SetMask((const sockaddr*)&request.ifra_mask);
18961729d93SAxel Dörfler 
19061729d93SAxel Dörfler 	return status;
19161729d93SAxel Dörfler }
19261729d93SAxel Dörfler 
19361729d93SAxel Dörfler 
19461729d93SAxel Dörfler status_t
19561729d93SAxel Dörfler InterfaceAddress::SetLocal(const sockaddr* to)
19661729d93SAxel Dörfler {
19761729d93SAxel Dörfler 	return Set(&local, to);
19861729d93SAxel Dörfler }
19961729d93SAxel Dörfler 
20061729d93SAxel Dörfler 
20161729d93SAxel Dörfler status_t
20261729d93SAxel Dörfler InterfaceAddress::SetDestination(const sockaddr* to)
20361729d93SAxel Dörfler {
20461729d93SAxel Dörfler 	return Set(&destination, to);
20561729d93SAxel Dörfler }
20661729d93SAxel Dörfler 
20761729d93SAxel Dörfler 
20861729d93SAxel Dörfler status_t
20961729d93SAxel Dörfler InterfaceAddress::SetMask(const sockaddr* to)
21061729d93SAxel Dörfler {
21161729d93SAxel Dörfler 	return Set(&mask, to);
21261729d93SAxel Dörfler }
21361729d93SAxel Dörfler 
21461729d93SAxel Dörfler 
21561729d93SAxel Dörfler sockaddr**
21661729d93SAxel Dörfler InterfaceAddress::AddressFor(int32 option)
21761729d93SAxel Dörfler {
21861729d93SAxel Dörfler 	switch (option) {
21961729d93SAxel Dörfler 		case SIOCSIFADDR:
22061729d93SAxel Dörfler 		case SIOCGIFADDR:
2212b1c0755SAxel Dörfler 		case SIOCDIFADDR:
22261729d93SAxel Dörfler 			return &local;
22361729d93SAxel Dörfler 
22461729d93SAxel Dörfler 		case SIOCSIFNETMASK:
22561729d93SAxel Dörfler 		case SIOCGIFNETMASK:
22661729d93SAxel Dörfler 			return &mask;
22761729d93SAxel Dörfler 
22861729d93SAxel Dörfler 		case SIOCSIFBRDADDR:
22961729d93SAxel Dörfler 		case SIOCSIFDSTADDR:
23061729d93SAxel Dörfler 		case SIOCGIFBRDADDR:
23161729d93SAxel Dörfler 		case SIOCGIFDSTADDR:
23261729d93SAxel Dörfler 			return &destination;
23361729d93SAxel Dörfler 
23461729d93SAxel Dörfler 		default:
23561729d93SAxel Dörfler 			return NULL;
23661729d93SAxel Dörfler 	}
23761729d93SAxel Dörfler }
23861729d93SAxel Dörfler 
23961729d93SAxel Dörfler 
2402b1c0755SAxel Dörfler /*!	Adds the default routes that every interface address needs, ie. the local
2412b1c0755SAxel Dörfler 	host route, and one for the subnet (if set).
2422b1c0755SAxel Dörfler */
2432b1c0755SAxel Dörfler void
2442b1c0755SAxel Dörfler InterfaceAddress::AddDefaultRoutes(int32 option)
2452b1c0755SAxel Dörfler {
2462b1c0755SAxel Dörfler 	net_route route;
2472b1c0755SAxel Dörfler 	route.destination = local;
2482b1c0755SAxel Dörfler 	route.gateway = NULL;
2492b1c0755SAxel Dörfler 	route.interface_address = this;
2502b1c0755SAxel Dörfler 
2512b1c0755SAxel Dörfler 	if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
2522b1c0755SAxel Dörfler 		route.mask = mask;
2532b1c0755SAxel Dörfler 		route.flags = 0;
2542b1c0755SAxel Dörfler 		add_route(domain, &route);
2552b1c0755SAxel Dörfler 	}
2562b1c0755SAxel Dörfler 
2572b1c0755SAxel Dörfler 	if (option == SIOCSIFADDR) {
2582b1c0755SAxel Dörfler 		route.mask = NULL;
2592b1c0755SAxel Dörfler 		route.flags = RTF_LOCAL | RTF_HOST;
2602b1c0755SAxel Dörfler 		add_route(domain, &route);
2612b1c0755SAxel Dörfler 	}
2622b1c0755SAxel Dörfler }
2632b1c0755SAxel Dörfler 
2642b1c0755SAxel Dörfler 
2652b1c0755SAxel Dörfler /*!	Removes the default routes as set by AddDefaultRoutes() again. */
2662b1c0755SAxel Dörfler void
2672b1c0755SAxel Dörfler InterfaceAddress::RemoveDefaultRoutes(int32 option)
2682b1c0755SAxel Dörfler {
2692b1c0755SAxel Dörfler 	net_route route;
2702b1c0755SAxel Dörfler 	route.destination = local;
2712b1c0755SAxel Dörfler 	route.gateway = NULL;
2722b1c0755SAxel Dörfler 	route.interface_address = this;
2732b1c0755SAxel Dörfler 
2742b1c0755SAxel Dörfler 	if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
2752b1c0755SAxel Dörfler 		route.mask = mask;
2762b1c0755SAxel Dörfler 		route.flags = 0;
2772b1c0755SAxel Dörfler 		remove_route(domain, &route);
2782b1c0755SAxel Dörfler 	}
2792b1c0755SAxel Dörfler 
2802b1c0755SAxel Dörfler 	if (option == SIOCSIFADDR) {
2812b1c0755SAxel Dörfler 		route.mask = NULL;
2822b1c0755SAxel Dörfler 		route.flags = RTF_LOCAL | RTF_HOST;
2832b1c0755SAxel Dörfler 		remove_route(domain, &route);
2842b1c0755SAxel Dörfler 	}
2852b1c0755SAxel Dörfler }
2862b1c0755SAxel Dörfler 
2872b1c0755SAxel Dörfler 
28861729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
28961729d93SAxel Dörfler 
29061729d93SAxel Dörfler 
29161729d93SAxel Dörfler void
29261729d93SAxel Dörfler InterfaceAddress::Dump(size_t index, bool hideInterface)
29361729d93SAxel Dörfler {
29461729d93SAxel Dörfler 	if (index)
29561729d93SAxel Dörfler 		kprintf("%2zu. ", index);
29661729d93SAxel Dörfler 	else
29761729d93SAxel Dörfler 		kprintf("    ");
29861729d93SAxel Dörfler 
29961729d93SAxel Dörfler 	if (!hideInterface) {
30061729d93SAxel Dörfler 		kprintf("interface:   %p (%s)\n    ", interface,
30161729d93SAxel Dörfler 			interface != NULL ? interface->name : "-");
30261729d93SAxel Dörfler 	}
30361729d93SAxel Dörfler 
30461729d93SAxel Dörfler 	kprintf("domain:      %p (family %u)\n", domain,
30561729d93SAxel Dörfler 		domain != NULL ? domain->family : AF_UNSPEC);
30661729d93SAxel Dörfler 
30761729d93SAxel Dörfler 	char buffer[64];
30861729d93SAxel Dörfler 	if (local != NULL && domain != NULL) {
30961729d93SAxel Dörfler 		domain->address_module->print_address_buffer(local, buffer,
31061729d93SAxel Dörfler 			sizeof(buffer), false);
31161729d93SAxel Dörfler 	} else
31261729d93SAxel Dörfler 		strcpy(buffer, "-");
31361729d93SAxel Dörfler 	kprintf("    local:       %s\n", buffer);
31461729d93SAxel Dörfler 
31561729d93SAxel Dörfler 	if (mask != NULL && domain != NULL) {
31661729d93SAxel Dörfler 		domain->address_module->print_address_buffer(mask, buffer,
31761729d93SAxel Dörfler 			sizeof(buffer), false);
31861729d93SAxel Dörfler 	} else
31961729d93SAxel Dörfler 		strcpy(buffer, "-");
32061729d93SAxel Dörfler 	kprintf("    mask:        %s\n", buffer);
32161729d93SAxel Dörfler 
32261729d93SAxel Dörfler 	if (destination != NULL && domain != NULL) {
32361729d93SAxel Dörfler 		domain->address_module->print_address_buffer(destination, buffer,
32461729d93SAxel Dörfler 			sizeof(buffer), false);
32561729d93SAxel Dörfler 	} else
32661729d93SAxel Dörfler 		strcpy(buffer, "-");
32761729d93SAxel Dörfler 	kprintf("    destination: %s\n", buffer);
3284af124a1SAxel Dörfler 
3294af124a1SAxel Dörfler 	kprintf("    ref count:   %" B_PRId32 "\n", CountReferences());
33061729d93SAxel Dörfler }
33161729d93SAxel Dörfler 
33261729d93SAxel Dörfler 
33361729d93SAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
33461729d93SAxel Dörfler 
33561729d93SAxel Dörfler 
33661729d93SAxel Dörfler /*static*/ status_t
33761729d93SAxel Dörfler InterfaceAddress::Set(sockaddr** _address, const sockaddr* to)
33861729d93SAxel Dörfler {
33961729d93SAxel Dörfler 	sockaddr* address = *_address;
34061729d93SAxel Dörfler 
34161729d93SAxel Dörfler 	if (to == NULL || to->sa_family == AF_UNSPEC) {
34261729d93SAxel Dörfler 		// Clear address
34361729d93SAxel Dörfler 		free(address);
34461729d93SAxel Dörfler 		*_address = NULL;
34561729d93SAxel Dörfler 		return B_OK;
34661729d93SAxel Dörfler 	}
34761729d93SAxel Dörfler 
34861729d93SAxel Dörfler 	// Set address
34961729d93SAxel Dörfler 
35061729d93SAxel Dörfler 	size_t size = max_c(to->sa_len, sizeof(sockaddr));
35161729d93SAxel Dörfler 	if (size > sizeof(sockaddr_storage))
35261729d93SAxel Dörfler 		size = sizeof(sockaddr_storage);
35361729d93SAxel Dörfler 
35461729d93SAxel Dörfler 	address = Prepare(_address, size);
35561729d93SAxel Dörfler 	if (address == NULL)
35661729d93SAxel Dörfler 		return B_NO_MEMORY;
35761729d93SAxel Dörfler 
35861729d93SAxel Dörfler 	memcpy(address, to, size);
35961729d93SAxel Dörfler 	address->sa_len = size;
36061729d93SAxel Dörfler 
36161729d93SAxel Dörfler 	return B_OK;
36261729d93SAxel Dörfler }
36361729d93SAxel Dörfler 
36461729d93SAxel Dörfler 
36561729d93SAxel Dörfler /*static*/ sockaddr*
36661729d93SAxel Dörfler InterfaceAddress::Prepare(sockaddr** _address, size_t size)
36761729d93SAxel Dörfler {
36861729d93SAxel Dörfler 	size = max_c(size, sizeof(sockaddr));
36961729d93SAxel Dörfler 	if (size > sizeof(sockaddr_storage))
37061729d93SAxel Dörfler 		size = sizeof(sockaddr_storage);
37161729d93SAxel Dörfler 
37261729d93SAxel Dörfler 	sockaddr* address = *_address;
37361729d93SAxel Dörfler 
37461729d93SAxel Dörfler 	if (address == NULL || size > address->sa_len) {
37561729d93SAxel Dörfler 		address = (sockaddr*)realloc(address, size);
37661729d93SAxel Dörfler 		if (address == NULL)
37761729d93SAxel Dörfler 			return NULL;
37861729d93SAxel Dörfler 	}
37961729d93SAxel Dörfler 
38061729d93SAxel Dörfler 	address->sa_len = size;
38161729d93SAxel Dörfler 
38261729d93SAxel Dörfler 	*_address = address;
38361729d93SAxel Dörfler 	return address;
38461729d93SAxel Dörfler }
38561729d93SAxel Dörfler 
38661729d93SAxel Dörfler 
38761729d93SAxel Dörfler void
38861729d93SAxel Dörfler InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain)
38961729d93SAxel Dörfler {
3902b1c0755SAxel Dörfler 	TRACE("InterfaceAddress %p: init interface %p, domain %p\n", this,
3912b1c0755SAxel Dörfler 		netInterface, netDomain);
3922b1c0755SAxel Dörfler 
39361729d93SAxel Dörfler 	interface = netInterface;
39461729d93SAxel Dörfler 	domain = netDomain;
39561729d93SAxel Dörfler 	local = NULL;
39661729d93SAxel Dörfler 	destination = NULL;
39761729d93SAxel Dörfler 	mask = NULL;
3982b1c0755SAxel Dörfler 	flags = 0;
3992b1c0755SAxel Dörfler 
4002b1c0755SAxel Dörfler 	if (interface != NULL)
4012b1c0755SAxel Dörfler 		((Interface*)interface)->AcquireReference();
40261729d93SAxel Dörfler }
40361729d93SAxel Dörfler 
40461729d93SAxel Dörfler 
40561729d93SAxel Dörfler // #pragma mark -
40661729d93SAxel Dörfler 
40761729d93SAxel Dörfler 
40861729d93SAxel Dörfler Interface::Interface(const char* interfaceName,
40961729d93SAxel Dörfler 	net_device_interface* deviceInterface)
41061729d93SAxel Dörfler {
41161729d93SAxel Dörfler 	TRACE("Interface %p: new \"%s\", device interface %p\n", this,
41261729d93SAxel Dörfler 		interfaceName, deviceInterface);
41361729d93SAxel Dörfler 
414b0cf274aSAxel Dörfler 	int written = strlcpy(name, interfaceName, IF_NAMESIZE);
415b0cf274aSAxel Dörfler 	memset(name + written, 0, IF_NAMESIZE - written);
416b0cf274aSAxel Dörfler 		// Clear remaining space
417b0cf274aSAxel Dörfler 
41861729d93SAxel Dörfler 	device = deviceInterface->device;
41961729d93SAxel Dörfler 
42061729d93SAxel Dörfler 	index = ++sInterfaceIndex;
42161729d93SAxel Dörfler 	flags = 0;
42261729d93SAxel Dörfler 	type = 0;
42361729d93SAxel Dörfler 	mtu = deviceInterface->device->mtu;
42461729d93SAxel Dörfler 	metric = 0;
42561729d93SAxel Dörfler 
42661729d93SAxel Dörfler 	fDeviceInterface = acquire_device_interface(deviceInterface);
42761729d93SAxel Dörfler 
42861729d93SAxel Dörfler 	recursive_lock_init(&fLock, name);
42961729d93SAxel Dörfler 
43061729d93SAxel Dörfler 	// Grab a reference to the networking stack, to make sure it won't be
43161729d93SAxel Dörfler 	// unloaded as long as an interface exists
43261729d93SAxel Dörfler 	module_info* module;
43361729d93SAxel Dörfler 	get_module(gNetStackInterfaceModule.info.name, &module);
43461729d93SAxel Dörfler }
43561729d93SAxel Dörfler 
43661729d93SAxel Dörfler 
43761729d93SAxel Dörfler Interface::~Interface()
43861729d93SAxel Dörfler {
4392b1c0755SAxel Dörfler 	TRACE("Interface %p: destructor\n", this);
4402b1c0755SAxel Dörfler 
4412b1c0755SAxel Dörfler 	put_device_interface(fDeviceInterface);
4422b1c0755SAxel Dörfler 
4432b1c0755SAxel Dörfler 	// Uninitialize the domain datalink protocols
4442b1c0755SAxel Dörfler 
4452b1c0755SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
4462b1c0755SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
4472b1c0755SAxel Dörfler 		put_domain_datalink_protocols(this, datalink->domain);
4482b1c0755SAxel Dörfler 	}
4492b1c0755SAxel Dörfler 
4502b1c0755SAxel Dörfler 	// Free domain datalink objects
4512b1c0755SAxel Dörfler 
4522b1c0755SAxel Dörfler 	domain_datalink* next = fDatalinkTable.Clear(true);
4532b1c0755SAxel Dörfler 	while (next != NULL) {
4542b1c0755SAxel Dörfler 		domain_datalink* datalink = next;
4552b1c0755SAxel Dörfler 		next = next->hash_link;
4562b1c0755SAxel Dörfler 
4572b1c0755SAxel Dörfler 		delete datalink;
4582b1c0755SAxel Dörfler 	}
4592b1c0755SAxel Dörfler 
46061729d93SAxel Dörfler 	recursive_lock_destroy(&fLock);
46161729d93SAxel Dörfler 
46261729d93SAxel Dörfler 	// Release reference of the stack - at this point, our stack may be unloaded
46361729d93SAxel Dörfler 	// if no other interfaces or sockets are left
46461729d93SAxel Dörfler 	put_module(gNetStackInterfaceModule.info.name);
46561729d93SAxel Dörfler }
46661729d93SAxel Dörfler 
46761729d93SAxel Dörfler 
46861729d93SAxel Dörfler /*!	Returns a reference to the first InterfaceAddress that is from the same
46961729d93SAxel Dörfler 	as the specified \a family.
47061729d93SAxel Dörfler */
47161729d93SAxel Dörfler InterfaceAddress*
47261729d93SAxel Dörfler Interface::FirstForFamily(int family)
47361729d93SAxel Dörfler {
47461729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
47561729d93SAxel Dörfler 
47661729d93SAxel Dörfler 	InterfaceAddress* address = _FirstForFamily(family);
47761729d93SAxel Dörfler 	if (address != NULL) {
47861729d93SAxel Dörfler 		address->AcquireReference();
47961729d93SAxel Dörfler 		return address;
48061729d93SAxel Dörfler 	}
48161729d93SAxel Dörfler 
48261729d93SAxel Dörfler 	return NULL;
48361729d93SAxel Dörfler }
48461729d93SAxel Dörfler 
48561729d93SAxel Dörfler 
48661729d93SAxel Dörfler /*!	Returns a reference to the first unconfigured address of this interface
48761729d93SAxel Dörfler 	for the specified \a family.
48861729d93SAxel Dörfler */
48961729d93SAxel Dörfler InterfaceAddress*
49061729d93SAxel Dörfler Interface::FirstUnconfiguredForFamily(int family)
49161729d93SAxel Dörfler {
49261729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
49361729d93SAxel Dörfler 
49461729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
49561729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
49661729d93SAxel Dörfler 		if (address->domain->family == family
49761729d93SAxel Dörfler 			&& (address->local == NULL
49861729d93SAxel Dörfler 				// TODO: this has to be solved differently!!
49961729d93SAxel Dörfler 				|| (flags & IFF_CONFIGURING) != 0)) {
50061729d93SAxel Dörfler 			address->AcquireReference();
50161729d93SAxel Dörfler 			return address;
50261729d93SAxel Dörfler 		}
50361729d93SAxel Dörfler 	}
50461729d93SAxel Dörfler 
50561729d93SAxel Dörfler 	return NULL;
50661729d93SAxel Dörfler }
50761729d93SAxel Dörfler 
50861729d93SAxel Dörfler 
50961729d93SAxel Dörfler /*!	Returns a reference to the InterfaceAddress that has the specified
51061729d93SAxel Dörfler 	\a destination address.
51161729d93SAxel Dörfler */
51261729d93SAxel Dörfler InterfaceAddress*
51361729d93SAxel Dörfler Interface::AddressForDestination(net_domain* domain,
51461729d93SAxel Dörfler 	const sockaddr* destination)
51561729d93SAxel Dörfler {
51661729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
51761729d93SAxel Dörfler 
51861729d93SAxel Dörfler 	if ((device->flags & IFF_BROADCAST) == 0) {
51961729d93SAxel Dörfler 		// The device does not support broadcasting
52061729d93SAxel Dörfler 		return NULL;
52161729d93SAxel Dörfler 	}
52261729d93SAxel Dörfler 
52361729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
52461729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
52561729d93SAxel Dörfler 		if (address->domain == domain
52661729d93SAxel Dörfler 			&& address->destination != NULL
52761729d93SAxel Dörfler 			&& domain->address_module->equal_addresses(address->destination,
52861729d93SAxel Dörfler 					destination)) {
52961729d93SAxel Dörfler 			address->AcquireReference();
53061729d93SAxel Dörfler 			return address;
53161729d93SAxel Dörfler 		}
53261729d93SAxel Dörfler 	}
53361729d93SAxel Dörfler 
53461729d93SAxel Dörfler 	return NULL;
53561729d93SAxel Dörfler }
53661729d93SAxel Dörfler 
53761729d93SAxel Dörfler 
538*910ffb32SAxel Dörfler /*!	Returns a reference to the InterfaceAddress that has the specified
539*910ffb32SAxel Dörfler 	\a local address.
540*910ffb32SAxel Dörfler */
541*910ffb32SAxel Dörfler InterfaceAddress*
542*910ffb32SAxel Dörfler Interface::AddressForLocal(net_domain* domain, const sockaddr* local)
543*910ffb32SAxel Dörfler {
544*910ffb32SAxel Dörfler 	RecursiveLocker locker(fLock);
545*910ffb32SAxel Dörfler 
546*910ffb32SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
547*910ffb32SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
548*910ffb32SAxel Dörfler 		if (address->domain == domain
549*910ffb32SAxel Dörfler 			&& address->local != NULL
550*910ffb32SAxel Dörfler 			&& domain->address_module->equal_addresses(address->local, local)) {
551*910ffb32SAxel Dörfler 			address->AcquireReference();
552*910ffb32SAxel Dörfler 			return address;
553*910ffb32SAxel Dörfler 		}
554*910ffb32SAxel Dörfler 	}
555*910ffb32SAxel Dörfler 
556*910ffb32SAxel Dörfler 	return NULL;
557*910ffb32SAxel Dörfler }
558*910ffb32SAxel Dörfler 
559*910ffb32SAxel Dörfler 
56061729d93SAxel Dörfler status_t
56161729d93SAxel Dörfler Interface::AddAddress(InterfaceAddress* address)
56261729d93SAxel Dörfler {
56361729d93SAxel Dörfler 	net_domain* domain = address->domain;
56461729d93SAxel Dörfler 	if (domain == NULL)
56561729d93SAxel Dörfler 		return B_BAD_VALUE;
56661729d93SAxel Dörfler 
56761729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
56861729d93SAxel Dörfler 	fAddresses.Add(address);
56961729d93SAxel Dörfler 	locker.Unlock();
57061729d93SAxel Dörfler 
57161729d93SAxel Dörfler 	MutexLocker hashLocker(sHashLock);
57261729d93SAxel Dörfler 	sAddressTable.Insert(address);
57361729d93SAxel Dörfler 	return B_OK;
57461729d93SAxel Dörfler }
57561729d93SAxel Dörfler 
57661729d93SAxel Dörfler 
57761729d93SAxel Dörfler void
57861729d93SAxel Dörfler Interface::RemoveAddress(InterfaceAddress* address)
57961729d93SAxel Dörfler {
58061729d93SAxel Dörfler 	net_domain* domain = address->domain;
58161729d93SAxel Dörfler 	if (domain == NULL)
58261729d93SAxel Dörfler 		return;
58361729d93SAxel Dörfler 
58461729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
58561729d93SAxel Dörfler 
58661729d93SAxel Dörfler 	fAddresses.Remove(address);
58761729d93SAxel Dörfler 	address->GetDoublyLinkedListLink()->next = NULL;
58861729d93SAxel Dörfler 
58961729d93SAxel Dörfler 	locker.Unlock();
59061729d93SAxel Dörfler 
59161729d93SAxel Dörfler 	MutexLocker hashLocker(sHashLock);
59261729d93SAxel Dörfler 	sAddressTable.Remove(address);
59361729d93SAxel Dörfler }
59461729d93SAxel Dörfler 
59561729d93SAxel Dörfler 
59661729d93SAxel Dörfler bool
59761729d93SAxel Dörfler Interface::GetNextAddress(InterfaceAddress** _address)
59861729d93SAxel Dörfler {
59961729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
60061729d93SAxel Dörfler 
60161729d93SAxel Dörfler 	InterfaceAddress* address = *_address;
60261729d93SAxel Dörfler 	if (address == NULL) {
60361729d93SAxel Dörfler 		// get first address
60461729d93SAxel Dörfler 		address = fAddresses.First();
60561729d93SAxel Dörfler 	} else {
60661729d93SAxel Dörfler 		// get next, if possible
60761729d93SAxel Dörfler 		InterfaceAddress* next = fAddresses.GetNext(address);
60861729d93SAxel Dörfler 		address->ReleaseReference();
60961729d93SAxel Dörfler 		address = next;
61061729d93SAxel Dörfler 	}
61161729d93SAxel Dörfler 
61261729d93SAxel Dörfler 	*_address = address;
61361729d93SAxel Dörfler 
61461729d93SAxel Dörfler 	if (address == NULL)
61561729d93SAxel Dörfler 		return false;
61661729d93SAxel Dörfler 
61761729d93SAxel Dörfler 	address->AcquireReference();
61861729d93SAxel Dörfler 	return true;
61961729d93SAxel Dörfler }
62061729d93SAxel Dörfler 
62161729d93SAxel Dörfler 
6229d771afbSAxel Dörfler InterfaceAddress*
6239d771afbSAxel Dörfler Interface::AddressAt(size_t index)
6249d771afbSAxel Dörfler {
6259d771afbSAxel Dörfler 	RecursiveLocker locker(fLock);
6269d771afbSAxel Dörfler 
6279d771afbSAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
6289d771afbSAxel Dörfler 	size_t i = 0;
6299d771afbSAxel Dörfler 
6309d771afbSAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
6319d771afbSAxel Dörfler 		if (i++ == index) {
6329d771afbSAxel Dörfler 			address->AcquireReference();
6339d771afbSAxel Dörfler 			return address;
6349d771afbSAxel Dörfler 		}
6359d771afbSAxel Dörfler 	}
6369d771afbSAxel Dörfler 
6379d771afbSAxel Dörfler 	return NULL;
6389d771afbSAxel Dörfler }
6399d771afbSAxel Dörfler 
6409d771afbSAxel Dörfler 
6419d771afbSAxel Dörfler size_t
6429d771afbSAxel Dörfler Interface::CountAddresses()
6439d771afbSAxel Dörfler {
6449d771afbSAxel Dörfler 	RecursiveLocker locker(fLock);
6459d771afbSAxel Dörfler 	return fAddresses.Count();
6469d771afbSAxel Dörfler }
6479d771afbSAxel Dörfler 
6489d771afbSAxel Dörfler 
6492b1c0755SAxel Dörfler void
6502b1c0755SAxel Dörfler Interface::RemoveAddresses()
6512b1c0755SAxel Dörfler {
6522b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
6532b1c0755SAxel Dörfler 
6542b1c0755SAxel Dörfler 	while (InterfaceAddress* address = fAddresses.RemoveHead()) {
6552b1c0755SAxel Dörfler 		address->ReleaseReference();
6562b1c0755SAxel Dörfler 	}
6572b1c0755SAxel Dörfler }
6582b1c0755SAxel Dörfler 
6592b1c0755SAxel Dörfler 
6609d771afbSAxel Dörfler /*!	This is called in order to call the correct methods of the datalink
6619d771afbSAxel Dörfler 	protocols, ie. it will translate address changes to
6629d771afbSAxel Dörfler 	net_datalink_protocol::change_address(), and IFF_UP changes to
6639d771afbSAxel Dörfler 	net_datalink_protocol::interface_up(), and interface_down().
6649d771afbSAxel Dörfler 
6659d771afbSAxel Dörfler 	Everything else is passed unchanged to net_datalink_protocol::control().
6669d771afbSAxel Dörfler */
66761729d93SAxel Dörfler status_t
66861729d93SAxel Dörfler Interface::Control(net_domain* domain, int32 option, ifreq& request,
66961729d93SAxel Dörfler 	ifreq* userRequest, size_t length)
67061729d93SAxel Dörfler {
67161729d93SAxel Dörfler 	switch (option) {
67261729d93SAxel Dörfler 		case SIOCSIFFLAGS:
67361729d93SAxel Dörfler 		{
674e8802e49SAxel Dörfler 			if (length != sizeof(ifreq))
675e8802e49SAxel Dörfler 				return B_BAD_VALUE;
676e8802e49SAxel Dörfler 
67761729d93SAxel Dörfler 			uint32 requestFlags = request.ifr_flags;
67861729d93SAxel Dörfler 			uint32 oldFlags = flags;
67961729d93SAxel Dörfler 			status_t status = B_OK;
68061729d93SAxel Dörfler 
68161729d93SAxel Dörfler 			request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST);
68261729d93SAxel Dörfler 
68361729d93SAxel Dörfler 			if ((requestFlags & IFF_UP) != (flags & IFF_UP)) {
68461729d93SAxel Dörfler 				if ((requestFlags & IFF_UP) != 0)
68561729d93SAxel Dörfler 					status = _SetUp();
68661729d93SAxel Dörfler 				else
6872b1c0755SAxel Dörfler 					SetDown();
68861729d93SAxel Dörfler 			}
68961729d93SAxel Dörfler 
69061729d93SAxel Dörfler 			if (status == B_OK) {
69161729d93SAxel Dörfler 				// TODO: maybe allow deleting IFF_BROADCAST on the interface
69261729d93SAxel Dörfler 				// level?
69361729d93SAxel Dörfler 				flags &= IFF_UP | IFF_LINK | IFF_BROADCAST;
69461729d93SAxel Dörfler 				flags |= request.ifr_flags;
69561729d93SAxel Dörfler 			}
69661729d93SAxel Dörfler 
69761729d93SAxel Dörfler 			if (oldFlags != flags)
69861729d93SAxel Dörfler 				notify_interface_changed(this, oldFlags, flags);
69961729d93SAxel Dörfler 
70061729d93SAxel Dörfler 			return status;
70161729d93SAxel Dörfler 		}
70261729d93SAxel Dörfler 
7032b1c0755SAxel Dörfler 		case B_SOCKET_SET_ALIAS:
7049d771afbSAxel Dörfler 		{
705e8802e49SAxel Dörfler 			if (length != sizeof(ifaliasreq))
706e8802e49SAxel Dörfler 				return B_BAD_VALUE;
707e8802e49SAxel Dörfler 
7089d771afbSAxel Dörfler 			RecursiveLocker locker(fLock);
7099d771afbSAxel Dörfler 
7109d771afbSAxel Dörfler 			ifaliasreq aliasRequest;
7119d771afbSAxel Dörfler 			if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq))
7129d771afbSAxel Dörfler 					!= B_OK)
7139d771afbSAxel Dörfler 				return B_BAD_ADDRESS;
7149d771afbSAxel Dörfler 
715*910ffb32SAxel Dörfler 			InterfaceAddress* address = NULL;
716*910ffb32SAxel Dörfler 			if (aliasRequest.ifra_index < 0) {
717*910ffb32SAxel Dörfler 				if (!domain->address_module->is_empty_address(
718*910ffb32SAxel Dörfler 						(const sockaddr*)&aliasRequest.ifra_addr, false)) {
719*910ffb32SAxel Dörfler 					// Find first address that matches the local address
720*910ffb32SAxel Dörfler 					address = AddressForLocal(domain,
721*910ffb32SAxel Dörfler 						(const sockaddr*)&aliasRequest.ifra_addr);
722*910ffb32SAxel Dörfler 				}
723*910ffb32SAxel Dörfler 				if (address == NULL) {
724*910ffb32SAxel Dörfler 					// Find first address for family
725*910ffb32SAxel Dörfler 					address = FirstForFamily(domain->family);
726*910ffb32SAxel Dörfler 				}
727*910ffb32SAxel Dörfler 			} else
728*910ffb32SAxel Dörfler 				address = AddressAt(aliasRequest.ifra_index);
729*910ffb32SAxel Dörfler 
7309d771afbSAxel Dörfler 			if (address == NULL)
7319d771afbSAxel Dörfler 				return B_BAD_VALUE;
7329d771afbSAxel Dörfler 
7339d771afbSAxel Dörfler 			status_t status = B_OK;
7349d771afbSAxel Dörfler 			address->AcquireReference();
7359d771afbSAxel Dörfler 				// _ChangeAddress() currently unlocks, so we need another
7369d771afbSAxel Dörfler 				// reference to make sure "address" is not going away.
7379d771afbSAxel Dörfler 
7389d771afbSAxel Dörfler 			if (!domain->address_module->equal_addresses(
7399d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_addr, address->local)) {
7409d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address, SIOCSIFADDR,
7419d771afbSAxel Dörfler 					address->local, (sockaddr*)&aliasRequest.ifra_addr);
7429d771afbSAxel Dörfler 			}
7439d771afbSAxel Dörfler 
7449d771afbSAxel Dörfler 			if (status == B_OK && !domain->address_module->equal_addresses(
745*910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_mask, address->mask)
746*910ffb32SAxel Dörfler 				&& !domain->address_module->is_empty_address(
747*910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_mask, false)) {
7489d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address, SIOCSIFNETMASK,
7499d771afbSAxel Dörfler 					address->mask, (sockaddr*)&aliasRequest.ifra_mask);
7509d771afbSAxel Dörfler 			}
7519d771afbSAxel Dörfler 
7529d771afbSAxel Dörfler 			if (status == B_OK && !domain->address_module->equal_addresses(
7539d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination,
754*910ffb32SAxel Dörfler 					address->destination)
755*910ffb32SAxel Dörfler 				&& !domain->address_module->is_empty_address(
756*910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination, false)) {
7579d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address,
7589d771afbSAxel Dörfler 					(domain->address_module->flags
7599d771afbSAxel Dörfler 						& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0
7609d771afbSAxel Dörfler 							? SIOCSIFBRDADDR : SIOCSIFDSTADDR,
7619d771afbSAxel Dörfler 					address->destination,
7629d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination);
7639d771afbSAxel Dörfler 			}
7649d771afbSAxel Dörfler 
7659d771afbSAxel Dörfler 			address->ReleaseReference();
7669d771afbSAxel Dörfler 			return status;
7679d771afbSAxel Dörfler 		}
7689d771afbSAxel Dörfler 
76961729d93SAxel Dörfler 		case SIOCSIFADDR:
77061729d93SAxel Dörfler 		case SIOCSIFNETMASK:
77161729d93SAxel Dörfler 		case SIOCSIFBRDADDR:
77261729d93SAxel Dörfler 		case SIOCSIFDSTADDR:
77361729d93SAxel Dörfler 		case SIOCDIFADDR:
77461729d93SAxel Dörfler 		{
775e8802e49SAxel Dörfler 			if (length != sizeof(ifreq))
776e8802e49SAxel Dörfler 				return B_BAD_VALUE;
777e8802e49SAxel Dörfler 
77861729d93SAxel Dörfler 			RecursiveLocker locker(fLock);
77961729d93SAxel Dörfler 
78061729d93SAxel Dörfler 			InterfaceAddress* address = NULL;
78161729d93SAxel Dörfler 			sockaddr_storage newAddress;
78261729d93SAxel Dörfler 
78361729d93SAxel Dörfler 			size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr));
78461729d93SAxel Dörfler 			if (size > sizeof(sockaddr_storage))
78561729d93SAxel Dörfler 				size = sizeof(sockaddr_storage);
78661729d93SAxel Dörfler 
78761729d93SAxel Dörfler 			if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK)
78861729d93SAxel Dörfler 				return B_BAD_ADDRESS;
78961729d93SAxel Dörfler 
79061729d93SAxel Dörfler 			if (option == SIOCDIFADDR) {
79161729d93SAxel Dörfler 				// Find referring address - we can't use the hash, as another
79261729d93SAxel Dörfler 				// interface might use the same address.
79361729d93SAxel Dörfler 				AddressList::Iterator iterator = fAddresses.GetIterator();
79461729d93SAxel Dörfler 				while ((address = iterator.Next()) != NULL) {
79561729d93SAxel Dörfler 					if (address->domain == domain
79661729d93SAxel Dörfler 						&& domain->address_module->equal_addresses(
79761729d93SAxel Dörfler 							address->local, (sockaddr*)&newAddress))
79861729d93SAxel Dörfler 						break;
79961729d93SAxel Dörfler 				}
80061729d93SAxel Dörfler 
80161729d93SAxel Dörfler 				if (address == NULL)
80261729d93SAxel Dörfler 					return B_BAD_VALUE;
80378abd727SAxel Dörfler 			} else {
80478abd727SAxel Dörfler 				// Just use the first address for this family
80578abd727SAxel Dörfler 				address = _FirstForFamily(domain->family);
80678abd727SAxel Dörfler 				if (address == NULL) {
80778abd727SAxel Dörfler 					// Create new on the fly
80878abd727SAxel Dörfler 					address = new(std::nothrow) InterfaceAddress(this, domain);
80978abd727SAxel Dörfler 					if (address == NULL)
81078abd727SAxel Dörfler 						return B_NO_MEMORY;
81178abd727SAxel Dörfler 
81278abd727SAxel Dörfler 					status_t status = AddAddress(address);
81378abd727SAxel Dörfler 					if (status != B_OK)
81478abd727SAxel Dörfler 						return status;
81578abd727SAxel Dörfler 
81678abd727SAxel Dörfler 					// Note, even if setting the address failed, the empty
81778abd727SAxel Dörfler 					// address added here will still be added to the interface.
81878abd727SAxel Dörfler 				}
81978abd727SAxel Dörfler 			}
82061729d93SAxel Dörfler 
8219d771afbSAxel Dörfler 			return _ChangeAddress(locker, address, option,
8229d771afbSAxel Dörfler 				*address->AddressFor(option),
82361729d93SAxel Dörfler 				option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL);
82461729d93SAxel Dörfler 		}
82561729d93SAxel Dörfler 
82661729d93SAxel Dörfler 		default:
82761729d93SAxel Dörfler 			// pass the request into the datalink protocol stack
82861729d93SAxel Dörfler 			domain_datalink* datalink = DomainDatalink(domain->family);
82961729d93SAxel Dörfler 			if (datalink->first_info != NULL) {
83061729d93SAxel Dörfler 				return datalink->first_info->control(
83161729d93SAxel Dörfler 					datalink->first_protocol, option, userRequest, length);
83261729d93SAxel Dörfler 			}
83361729d93SAxel Dörfler 			break;
83461729d93SAxel Dörfler 	}
83561729d93SAxel Dörfler 
83661729d93SAxel Dörfler 	return B_BAD_VALUE;
83761729d93SAxel Dörfler }
83861729d93SAxel Dörfler 
83961729d93SAxel Dörfler 
8402b1c0755SAxel Dörfler void
8412b1c0755SAxel Dörfler Interface::SetDown()
8422b1c0755SAxel Dörfler {
8432b1c0755SAxel Dörfler 	if ((flags & IFF_UP) == 0)
8442b1c0755SAxel Dörfler 		return;
8452b1c0755SAxel Dörfler 
8462b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
8472b1c0755SAxel Dörfler 
8482b1c0755SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
8492b1c0755SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
8502b1c0755SAxel Dörfler 		datalink->first_info->interface_down(datalink->first_protocol);
8512b1c0755SAxel Dörfler 	}
8522b1c0755SAxel Dörfler 
8532b1c0755SAxel Dörfler 	flags &= ~IFF_UP;
8542b1c0755SAxel Dörfler }
8552b1c0755SAxel Dörfler 
8562b1c0755SAxel Dörfler 
8572b1c0755SAxel Dörfler /*!	Called when a device lost its IFF_UP status. We will invalidate all
8582b1c0755SAxel Dörfler 	interface routes here.
8592b1c0755SAxel Dörfler */
8602b1c0755SAxel Dörfler void
8612b1c0755SAxel Dörfler Interface::WentDown()
8622b1c0755SAxel Dörfler {
8632b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
8642b1c0755SAxel Dörfler 
8652b1c0755SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
8662b1c0755SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
8672b1c0755SAxel Dörfler 		if (address->domain != NULL)
8682b1c0755SAxel Dörfler 			invalidate_routes(address->domain, this);
8692b1c0755SAxel Dörfler 	}
8702b1c0755SAxel Dörfler }
8712b1c0755SAxel Dörfler 
8722b1c0755SAxel Dörfler 
87361729d93SAxel Dörfler status_t
87461729d93SAxel Dörfler Interface::CreateDomainDatalinkIfNeeded(net_domain* domain)
87561729d93SAxel Dörfler {
87661729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
87761729d93SAxel Dörfler 
87861729d93SAxel Dörfler 	if (fDatalinkTable.Lookup(domain->family) != NULL)
87961729d93SAxel Dörfler 		return B_OK;
88061729d93SAxel Dörfler 
88161729d93SAxel Dörfler 	TRACE("Interface %p: create domain datalink for domain %p\n", this, domain);
88261729d93SAxel Dörfler 
88361729d93SAxel Dörfler 	domain_datalink* datalink = new(std::nothrow) domain_datalink;
88461729d93SAxel Dörfler 	if (datalink == NULL)
88561729d93SAxel Dörfler 		return B_NO_MEMORY;
88661729d93SAxel Dörfler 
88761729d93SAxel Dörfler 	datalink->domain = domain;
88861729d93SAxel Dörfler 
88961729d93SAxel Dörfler 	// setup direct route for bound devices
89061729d93SAxel Dörfler 	datalink->direct_route.destination = NULL;
89161729d93SAxel Dörfler 	datalink->direct_route.mask = NULL;
89261729d93SAxel Dörfler 	datalink->direct_route.gateway = NULL;
89361729d93SAxel Dörfler 	datalink->direct_route.flags = 0;
89461729d93SAxel Dörfler 	datalink->direct_route.mtu = 0;
89561729d93SAxel Dörfler 	datalink->direct_route.interface_address = &datalink->direct_address;
89661729d93SAxel Dörfler 	datalink->direct_route.ref_count = 1;
89761729d93SAxel Dörfler 		// make sure this doesn't get deleted accidently
89861729d93SAxel Dörfler 
89961729d93SAxel Dörfler 	// provide its link back to the interface
90061729d93SAxel Dörfler 	datalink->direct_address.local = NULL;
90161729d93SAxel Dörfler 	datalink->direct_address.destination = NULL;
90261729d93SAxel Dörfler 	datalink->direct_address.mask = NULL;
90361729d93SAxel Dörfler 	datalink->direct_address.domain = domain;
90461729d93SAxel Dörfler 	datalink->direct_address.interface = this;
9052b1c0755SAxel Dörfler 	datalink->direct_address.flags = IFAF_DIRECT_ADDRESS;
90661729d93SAxel Dörfler 
90761729d93SAxel Dörfler 	fDatalinkTable.Insert(datalink);
90861729d93SAxel Dörfler 
90961729d93SAxel Dörfler 	status_t status = get_domain_datalink_protocols(this, domain);
91061729d93SAxel Dörfler 	if (status == B_OK)
91161729d93SAxel Dörfler 		return B_OK;
91261729d93SAxel Dörfler 
91361729d93SAxel Dörfler 	fDatalinkTable.Remove(datalink);
91461729d93SAxel Dörfler 	delete datalink;
91561729d93SAxel Dörfler 
91661729d93SAxel Dörfler 	return status;
91761729d93SAxel Dörfler }
91861729d93SAxel Dörfler 
91961729d93SAxel Dörfler 
92061729d93SAxel Dörfler domain_datalink*
92161729d93SAxel Dörfler Interface::DomainDatalink(uint8 family)
92261729d93SAxel Dörfler {
92361729d93SAxel Dörfler 	// Note: domain datalinks cannot be removed while the interface is alive,
92461729d93SAxel Dörfler 	// since this would require us either to hold the lock while calling this
92561729d93SAxel Dörfler 	// function, or introduce reference counting for the domain_datalink
92661729d93SAxel Dörfler 	// structure.
92761729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
92861729d93SAxel Dörfler 	return fDatalinkTable.Lookup(family);
92961729d93SAxel Dörfler }
93061729d93SAxel Dörfler 
93161729d93SAxel Dörfler 
93261729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
93361729d93SAxel Dörfler 
93461729d93SAxel Dörfler 
93561729d93SAxel Dörfler void
93661729d93SAxel Dörfler Interface::Dump() const
93761729d93SAxel Dörfler {
93861729d93SAxel Dörfler 	kprintf("name:                %s\n", name);
93961729d93SAxel Dörfler 	kprintf("device:              %p\n", device);
94061729d93SAxel Dörfler 	kprintf("device_interface:    %p\n", fDeviceInterface);
94161729d93SAxel Dörfler 	kprintf("index:               %" B_PRIu32 "\n", index);
94261729d93SAxel Dörfler 	kprintf("flags:               %#" B_PRIx32 "\n", flags);
94361729d93SAxel Dörfler 	kprintf("type:                %u\n", type);
94461729d93SAxel Dörfler 	kprintf("mtu:                 %" B_PRIu32 "\n", mtu);
94561729d93SAxel Dörfler 	kprintf("metric:              %" B_PRIu32 "\n", metric);
94661729d93SAxel Dörfler 
94761729d93SAxel Dörfler 	kprintf("datalink protocols:\n");
94861729d93SAxel Dörfler 
94961729d93SAxel Dörfler 	DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator();
95061729d93SAxel Dörfler 	size_t i = 0;
95161729d93SAxel Dörfler 	while (domain_datalink* datalink = datalinkIterator.Next()) {
95261729d93SAxel Dörfler 		kprintf("%2zu. domain:          %p\n", ++i, datalink->domain);
95361729d93SAxel Dörfler 		kprintf("    first_protocol:  %p\n", datalink->first_protocol);
95461729d93SAxel Dörfler 		kprintf("    first_info:      %p\n", datalink->first_info);
95561729d93SAxel Dörfler 		kprintf("    direct_route:    %p\n", &datalink->direct_route);
95661729d93SAxel Dörfler 	}
95761729d93SAxel Dörfler 
95861729d93SAxel Dörfler 	kprintf("addresses:\n");
95961729d93SAxel Dörfler 
96061729d93SAxel Dörfler 	AddressList::ConstIterator iterator = fAddresses.GetIterator();
96161729d93SAxel Dörfler 	i = 0;
96261729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
96361729d93SAxel Dörfler 		address->Dump(++i, true);
96461729d93SAxel Dörfler 	}
96561729d93SAxel Dörfler }
96661729d93SAxel Dörfler 
96761729d93SAxel Dörfler 
96861729d93SAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
96961729d93SAxel Dörfler 
97061729d93SAxel Dörfler 
97161729d93SAxel Dörfler status_t
97261729d93SAxel Dörfler Interface::_SetUp()
97361729d93SAxel Dörfler {
97461729d93SAxel Dörfler 	status_t status = up_device_interface(fDeviceInterface);
97561729d93SAxel Dörfler 	if (status != B_OK)
97661729d93SAxel Dörfler 		return status;
97761729d93SAxel Dörfler 
9782b1c0755SAxel Dörfler 	// Propagate flag to all datalink protocols
97961729d93SAxel Dörfler 
98061729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
98161729d93SAxel Dörfler 
98261729d93SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
98361729d93SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
98461729d93SAxel Dörfler 		status = datalink->first_info->interface_up(datalink->first_protocol);
98561729d93SAxel Dörfler 		if (status != B_OK) {
98661729d93SAxel Dörfler 			// Revert "up" status
98761729d93SAxel Dörfler 			DatalinkTable::Iterator secondIterator
98861729d93SAxel Dörfler 				= fDatalinkTable.GetIterator();
98961729d93SAxel Dörfler 			while (secondIterator.HasNext()) {
99061729d93SAxel Dörfler 				domain_datalink* secondDatalink = secondIterator.Next();
99161729d93SAxel Dörfler 				if (secondDatalink == NULL || secondDatalink == datalink)
992c22d69bfSAxel Dörfler 					break;
993c22d69bfSAxel Dörfler 
99461729d93SAxel Dörfler 				secondDatalink->first_info->interface_down(
99561729d93SAxel Dörfler 					secondDatalink->first_protocol);
99661729d93SAxel Dörfler 			}
99761729d93SAxel Dörfler 
99861729d93SAxel Dörfler 			down_device_interface(fDeviceInterface);
99961729d93SAxel Dörfler 			return status;
100061729d93SAxel Dörfler 		}
100161729d93SAxel Dörfler 	}
100261729d93SAxel Dörfler 
10032b1c0755SAxel Dörfler 	// Add default routes for the existing addresses
10042b1c0755SAxel Dörfler 
10052b1c0755SAxel Dörfler 	AddressList::Iterator addressIterator = fAddresses.GetIterator();
10062b1c0755SAxel Dörfler 	while (InterfaceAddress* address = addressIterator.Next()) {
10072b1c0755SAxel Dörfler 		address->AddDefaultRoutes(SIOCSIFADDR);
10082b1c0755SAxel Dörfler 	}
10092b1c0755SAxel Dörfler 
101061729d93SAxel Dörfler 	flags |= IFF_UP;
101161729d93SAxel Dörfler 	return B_OK;
101261729d93SAxel Dörfler }
101361729d93SAxel Dörfler 
101461729d93SAxel Dörfler 
101561729d93SAxel Dörfler InterfaceAddress*
101661729d93SAxel Dörfler Interface::_FirstForFamily(int family)
101761729d93SAxel Dörfler {
101861729d93SAxel Dörfler 	ASSERT_LOCKED_RECURSIVE(&fLock);
101961729d93SAxel Dörfler 
102061729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
102161729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
102261729d93SAxel Dörfler 		if (address->domain != NULL && address->domain->family == family)
102361729d93SAxel Dörfler 			return address;
102461729d93SAxel Dörfler 	}
102561729d93SAxel Dörfler 
102661729d93SAxel Dörfler 	return NULL;
102761729d93SAxel Dörfler }
102861729d93SAxel Dörfler 
102961729d93SAxel Dörfler 
10309d771afbSAxel Dörfler status_t
10319d771afbSAxel Dörfler Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address,
1032b0cf274aSAxel Dörfler 	int32 option, const sockaddr* originalAddress,
1033b0cf274aSAxel Dörfler 	const sockaddr* requestedAddress)
10349d771afbSAxel Dörfler {
1035b0cf274aSAxel Dörfler 	// Copy old address
10369d771afbSAxel Dörfler 	sockaddr_storage oldAddress;
10379d771afbSAxel Dörfler 	if (address->domain->address_module->set_to((sockaddr*)&oldAddress,
10389d771afbSAxel Dörfler 			originalAddress) != B_OK)
10399d771afbSAxel Dörfler 		oldAddress.ss_family = AF_UNSPEC;
10409d771afbSAxel Dörfler 
1041b0cf274aSAxel Dörfler 	// Copy new address (this also makes sure that sockaddr::sa_len is set
1042b0cf274aSAxel Dörfler 	// correctly)
1043b0cf274aSAxel Dörfler 	sockaddr_storage newAddress;
1044b0cf274aSAxel Dörfler 	if (address->domain->address_module->set_to((sockaddr*)&newAddress,
1045b0cf274aSAxel Dörfler 			requestedAddress) != B_OK)
1046b0cf274aSAxel Dörfler 		newAddress.ss_family = AF_UNSPEC;
1047b0cf274aSAxel Dörfler 
10486b1e1488SAxel Dörfler 	// Test if anything changed for real
1049b0cf274aSAxel Dörfler 	if (address->domain->address_module->equal_addresses(
1050b0cf274aSAxel Dörfler 			(sockaddr*)&oldAddress, (sockaddr*)&newAddress)) {
10516b1e1488SAxel Dörfler 		// Nothing to do
1052b0cf274aSAxel Dörfler 		TRACE("  option %" B_PRId32 " addresses are equal!\n", option);
10536b1e1488SAxel Dörfler 		return B_OK;
10546b1e1488SAxel Dörfler 	}
10556b1e1488SAxel Dörfler 
10569d771afbSAxel Dörfler 	// TODO: mark this address busy or call while holding the lock!
10579d771afbSAxel Dörfler 	address->AcquireReference();
10589d771afbSAxel Dörfler 	locker.Unlock();
10599d771afbSAxel Dörfler 
10609d771afbSAxel Dörfler 	domain_datalink* datalink = DomainDatalink(address->domain);
10619d771afbSAxel Dörfler 	status_t status = datalink->first_protocol->module->change_address(
10629d771afbSAxel Dörfler 		datalink->first_protocol, address, option,
10639d771afbSAxel Dörfler 		oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL,
1064b0cf274aSAxel Dörfler 		newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL);
10659d771afbSAxel Dörfler 
10669d771afbSAxel Dörfler 	locker.Lock();
10679d771afbSAxel Dörfler 	address->ReleaseReference();
10689d771afbSAxel Dörfler 	return status;
10699d771afbSAxel Dörfler }
10709d771afbSAxel Dörfler 
10719d771afbSAxel Dörfler 
107261729d93SAxel Dörfler // #pragma mark -
107361729d93SAxel Dörfler 
107461729d93SAxel Dörfler 
107561729d93SAxel Dörfler /*!	Searches for a specific interface by name.
107661729d93SAxel Dörfler 	You need to have the interface list's lock hold when calling this function.
107761729d93SAxel Dörfler */
107861729d93SAxel Dörfler static struct Interface*
107961729d93SAxel Dörfler find_interface(const char* name)
108061729d93SAxel Dörfler {
108161729d93SAxel Dörfler 	ASSERT_LOCKED_MUTEX(&sLock);
108261729d93SAxel Dörfler 
108361729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
108461729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1085c22d69bfSAxel Dörfler 		if (!strcmp(interface->name, name))
1086c22d69bfSAxel Dörfler 			return interface;
1087c22d69bfSAxel Dörfler 	}
1088c22d69bfSAxel Dörfler 
1089c22d69bfSAxel Dörfler 	return NULL;
1090c22d69bfSAxel Dörfler }
1091c22d69bfSAxel Dörfler 
1092c22d69bfSAxel Dörfler 
109361729d93SAxel Dörfler /*!	Searches for a specific interface by index.
109461729d93SAxel Dörfler 	You need to have the interface list's lock hold when calling this function.
1095c22d69bfSAxel Dörfler */
109661729d93SAxel Dörfler static struct Interface*
109761729d93SAxel Dörfler find_interface(uint32 index)
1098c22d69bfSAxel Dörfler {
109961729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
110061729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1101c22d69bfSAxel Dörfler 		if (interface->index == index)
1102c22d69bfSAxel Dörfler 			return interface;
1103c22d69bfSAxel Dörfler 	}
1104c22d69bfSAxel Dörfler 
1105c22d69bfSAxel Dörfler 	return NULL;
1106c22d69bfSAxel Dörfler }
1107c22d69bfSAxel Dörfler 
1108c22d69bfSAxel Dörfler 
110961729d93SAxel Dörfler // #pragma mark -
111061729d93SAxel Dörfler 
111161729d93SAxel Dörfler 
111261729d93SAxel Dörfler status_t
111361729d93SAxel Dörfler add_interface(const char* name, net_domain_private* domain,
111461729d93SAxel Dörfler 	const ifaliasreq& request, net_device_interface* deviceInterface)
111561729d93SAxel Dörfler {
111661729d93SAxel Dörfler 	MutexLocker locker(sLock);
111761729d93SAxel Dörfler 
111861729d93SAxel Dörfler 	if (find_interface(name) != NULL)
111961729d93SAxel Dörfler 		return B_NAME_IN_USE;
112061729d93SAxel Dörfler 
112161729d93SAxel Dörfler 	Interface* interface
112261729d93SAxel Dörfler 		= new(std::nothrow) Interface(name, deviceInterface);
1123c22d69bfSAxel Dörfler 	if (interface == NULL)
1124c22d69bfSAxel Dörfler 		return B_NO_MEMORY;
1125c22d69bfSAxel Dörfler 
112661729d93SAxel Dörfler 	sInterfaces.Add(interface);
112761729d93SAxel Dörfler 	interface->AcquireReference();
112861729d93SAxel Dörfler 		// We need another reference to be able to use the interface without
112961729d93SAxel Dörfler 		// holding sLock.
1130c22d69bfSAxel Dörfler 
113161729d93SAxel Dörfler 	locker.Unlock();
1132c22d69bfSAxel Dörfler 
113361729d93SAxel Dörfler 	notify_interface_added(interface);
113461729d93SAxel Dörfler 	add_interface_address(interface, domain, request);
1135c22d69bfSAxel Dörfler 
113661729d93SAxel Dörfler 	interface->ReleaseReference();
113727e0dea9SAxel Dörfler 
1138c22d69bfSAxel Dörfler 	return B_OK;
1139c22d69bfSAxel Dörfler }
1140c22d69bfSAxel Dörfler 
1141c22d69bfSAxel Dörfler 
114261729d93SAxel Dörfler /*!	Removes the interface from the list, and puts the stack's reference to it.
114361729d93SAxel Dörfler */
11447aa2819cSAxel Dörfler void
114561729d93SAxel Dörfler remove_interface(Interface* interface)
1146c64feccaSHugo Santos {
11472b1c0755SAxel Dörfler 	interface->SetDown();
11482b1c0755SAxel Dörfler 	interface->RemoveAddresses();
1149c64feccaSHugo Santos 
11502b1c0755SAxel Dörfler 	MutexLocker locker(sLock);
11512b1c0755SAxel Dörfler 	sInterfaces.Remove(interface);
11522b1c0755SAxel Dörfler 	locker.Unlock();
1153f6d219a1SAxel Dörfler 
115461729d93SAxel Dörfler 	notify_interface_removed(interface);
1155c22d69bfSAxel Dörfler 
11562b1c0755SAxel Dörfler 	interface->ReleaseReference();
11577aa2819cSAxel Dörfler }
11587aa2819cSAxel Dörfler 
11597aa2819cSAxel Dörfler 
11607aa2819cSAxel Dörfler /*!	This is called whenever a device interface is being removed. We will get
11617aa2819cSAxel Dörfler 	the corresponding Interface, and remove it.
11627aa2819cSAxel Dörfler */
11637aa2819cSAxel Dörfler void
11647aa2819cSAxel Dörfler interface_removed_device_interface(net_device_interface* deviceInterface)
11657aa2819cSAxel Dörfler {
11667aa2819cSAxel Dörfler 	MutexLocker locker(sLock);
11677aa2819cSAxel Dörfler 
11687aa2819cSAxel Dörfler 	Interface* interface = find_interface(deviceInterface->device->name);
11697aa2819cSAxel Dörfler 	if (interface != NULL)
11707aa2819cSAxel Dörfler 		remove_interface(interface);
1171c22d69bfSAxel Dörfler }
1172c22d69bfSAxel Dörfler 
1173c22d69bfSAxel Dörfler 
117461729d93SAxel Dörfler status_t
117561729d93SAxel Dörfler add_interface_address(Interface* interface, net_domain_private* domain,
117661729d93SAxel Dörfler 	const ifaliasreq& request)
1177c22d69bfSAxel Dörfler {
117861729d93SAxel Dörfler 	// Make sure the family of the provided addresses is valid
117961729d93SAxel Dörfler 	if ((request.ifra_addr.ss_family != domain->family
118061729d93SAxel Dörfler 			&& request.ifra_addr.ss_family != AF_UNSPEC)
118161729d93SAxel Dörfler 		|| (request.ifra_mask.ss_family != domain->family
118261729d93SAxel Dörfler 			&& request.ifra_mask.ss_family != AF_UNSPEC)
118361729d93SAxel Dörfler 		|| (request.ifra_broadaddr.ss_family != domain->family
118461729d93SAxel Dörfler 			&& request.ifra_broadaddr.ss_family != AF_UNSPEC))
118561729d93SAxel Dörfler 		return B_BAD_VALUE;
1186c22d69bfSAxel Dörfler 
118761729d93SAxel Dörfler 	RecursiveLocker locker(interface->Lock());
118861729d93SAxel Dörfler 
118961729d93SAxel Dörfler 	InterfaceAddress* address
119061729d93SAxel Dörfler 		= new(std::nothrow) InterfaceAddress(interface, domain);
119161729d93SAxel Dörfler 	if (address == NULL)
119261729d93SAxel Dörfler 		return B_NO_MEMORY;
119361729d93SAxel Dörfler 
119461729d93SAxel Dörfler 	status_t status = address->SetTo(request);
119561729d93SAxel Dörfler 	if (status == B_OK)
119661729d93SAxel Dörfler 		status = interface->CreateDomainDatalinkIfNeeded(domain);
119761729d93SAxel Dörfler 	if (status == B_OK)
119861729d93SAxel Dörfler 		status = interface->AddAddress(address);
119961729d93SAxel Dörfler 
120061729d93SAxel Dörfler 	if (status == B_OK && address->local != NULL) {
120161729d93SAxel Dörfler 		// update the datalink protocols
120261729d93SAxel Dörfler 		domain_datalink* datalink = interface->DomainDatalink(domain->family);
120361729d93SAxel Dörfler 
120461729d93SAxel Dörfler 		status = datalink->first_protocol->module->change_address(
120561729d93SAxel Dörfler 			datalink->first_protocol, address, SIOCAIFADDR, NULL,
120661729d93SAxel Dörfler 			address->local);
120761729d93SAxel Dörfler 		if (status != B_OK)
120861729d93SAxel Dörfler 			interface->RemoveAddress(address);
120961729d93SAxel Dörfler 	}
121061729d93SAxel Dörfler 	if (status == B_OK)
121161729d93SAxel Dörfler 		notify_interface_changed(interface);
121261729d93SAxel Dörfler 	else
121361729d93SAxel Dörfler 		delete address;
121461729d93SAxel Dörfler 
121561729d93SAxel Dörfler 	return status;
121661729d93SAxel Dörfler }
121761729d93SAxel Dörfler 
121861729d93SAxel Dörfler 
121961729d93SAxel Dörfler status_t
122061729d93SAxel Dörfler update_interface_address(InterfaceAddress* interfaceAddress, int32 option,
122161729d93SAxel Dörfler 	const sockaddr* oldAddress, const sockaddr* newAddress)
122261729d93SAxel Dörfler {
1223b0cf274aSAxel Dörfler 	TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress "
1224b0cf274aSAxel Dörfler 		"%s)\n", __FUNCTION__, interfaceAddress, option,
1225b0cf274aSAxel Dörfler 		AddressString(interfaceAddress->domain, oldAddress).Data(),
1226b0cf274aSAxel Dörfler 		AddressString(interfaceAddress->domain, newAddress).Data());
1227b0cf274aSAxel Dörfler 
122861729d93SAxel Dörfler 	MutexLocker locker(sHashLock);
122961729d93SAxel Dörfler 
123061729d93SAxel Dörfler 	// set logical interface address
123161729d93SAxel Dörfler 	sockaddr** _address = interfaceAddress->AddressFor(option);
123261729d93SAxel Dörfler 	if (_address == NULL)
123361729d93SAxel Dörfler 		return B_BAD_VALUE;
123461729d93SAxel Dörfler 
12352b1c0755SAxel Dörfler 	Interface* interface = (Interface*)interfaceAddress->interface;
12362b1c0755SAxel Dörfler 
12372b1c0755SAxel Dörfler 	interfaceAddress->RemoveDefaultRoutes(option);
12382b1c0755SAxel Dörfler 
12392b1c0755SAxel Dörfler 	if (option == SIOCDIFADDR) {
12402b1c0755SAxel Dörfler 		// Remove address, and release its reference (causing our caller to
12412b1c0755SAxel Dörfler 		// delete it)
12422b1c0755SAxel Dörfler 		locker.Unlock();
12432b1c0755SAxel Dörfler 
12442b1c0755SAxel Dörfler 		invalidate_routes(interfaceAddress);
12452b1c0755SAxel Dörfler 
12462b1c0755SAxel Dörfler 		interface->RemoveAddress(interfaceAddress);
12472b1c0755SAxel Dörfler 		interfaceAddress->ReleaseReference();
12482b1c0755SAxel Dörfler 		return B_OK;
12492b1c0755SAxel Dörfler 	}
12502b1c0755SAxel Dörfler 
125161729d93SAxel Dörfler 	sAddressTable.Remove(interfaceAddress);
125261729d93SAxel Dörfler 
125361729d93SAxel Dörfler 	// Copy new address over
125461729d93SAxel Dörfler 	status_t status = InterfaceAddress::Set(_address, newAddress);
125561729d93SAxel Dörfler 	if (status == B_OK) {
125661729d93SAxel Dörfler 		sockaddr* address = *_address;
125761729d93SAxel Dörfler 
12581ebd87f4SAxel Dörfler 		if (option == SIOCSIFADDR) {
125961729d93SAxel Dörfler 			// Reset netmask and broadcast addresses to defaults
126061729d93SAxel Dörfler 			net_domain* domain = interfaceAddress->domain;
126161729d93SAxel Dörfler 			sockaddr* netmask = NULL;
126261729d93SAxel Dörfler 			const sockaddr* oldNetmask = NULL;
126361729d93SAxel Dörfler 			if (option == SIOCSIFADDR) {
126461729d93SAxel Dörfler 				netmask = InterfaceAddress::Prepare(
126561729d93SAxel Dörfler 					&interfaceAddress->mask, address->sa_len);
126661729d93SAxel Dörfler 			} else {
126761729d93SAxel Dörfler 				oldNetmask = oldAddress;
126861729d93SAxel Dörfler 				netmask = interfaceAddress->mask;
126961729d93SAxel Dörfler 			}
127061729d93SAxel Dörfler 
127161729d93SAxel Dörfler 			// Reset the broadcast address if the address family has
127261729d93SAxel Dörfler 			// such
127361729d93SAxel Dörfler 			sockaddr* broadcast = NULL;
127461729d93SAxel Dörfler 			if ((domain->address_module->flags
127561729d93SAxel Dörfler 					& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) {
127661729d93SAxel Dörfler 				broadcast = InterfaceAddress::Prepare(
127761729d93SAxel Dörfler 					&interfaceAddress->destination, address->sa_len);
127861729d93SAxel Dörfler 			} else
127961729d93SAxel Dörfler 				InterfaceAddress::Set(&interfaceAddress->destination, NULL);
128061729d93SAxel Dörfler 
128161729d93SAxel Dörfler 			domain->address_module->set_to_defaults(netmask, broadcast,
128261729d93SAxel Dörfler 				interfaceAddress->local, oldNetmask);
128361729d93SAxel Dörfler 		}
128461729d93SAxel Dörfler 
12852b1c0755SAxel Dörfler 		interfaceAddress->AddDefaultRoutes(option);
12862b1c0755SAxel Dörfler 		notify_interface_changed(interface);
128761729d93SAxel Dörfler 	}
128861729d93SAxel Dörfler 
128961729d93SAxel Dörfler 	sAddressTable.Insert(interfaceAddress);
129061729d93SAxel Dörfler 	return status;
129161729d93SAxel Dörfler }
129261729d93SAxel Dörfler 
129361729d93SAxel Dörfler 
129461729d93SAxel Dörfler Interface*
129561729d93SAxel Dörfler get_interface(net_domain* domain, uint32 index)
129661729d93SAxel Dörfler {
129761729d93SAxel Dörfler 	MutexLocker locker(sLock);
129861729d93SAxel Dörfler 
129961729d93SAxel Dörfler 	if (index == 0)
130061729d93SAxel Dörfler 		return sInterfaces.First();
130161729d93SAxel Dörfler 
130261729d93SAxel Dörfler 	Interface* interface = find_interface(index);
1303c22d69bfSAxel Dörfler 	if (interface == NULL)
130461729d93SAxel Dörfler 		return NULL;
1305c22d69bfSAxel Dörfler 
130661729d93SAxel Dörfler 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
130761729d93SAxel Dörfler 		return NULL;
130861729d93SAxel Dörfler 
130961729d93SAxel Dörfler 	interface->AcquireReference();
1310c22d69bfSAxel Dörfler 	return interface;
1311c22d69bfSAxel Dörfler }
1312c22d69bfSAxel Dörfler 
131361729d93SAxel Dörfler 
131461729d93SAxel Dörfler Interface*
131561729d93SAxel Dörfler get_interface(net_domain* domain, const char* name)
131661729d93SAxel Dörfler {
131761729d93SAxel Dörfler 	MutexLocker locker(sLock);
131861729d93SAxel Dörfler 
131961729d93SAxel Dörfler 	Interface* interface = find_interface(name);
132061729d93SAxel Dörfler 	if (interface == NULL)
132161729d93SAxel Dörfler 		return NULL;
132261729d93SAxel Dörfler 
132361729d93SAxel Dörfler 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
132461729d93SAxel Dörfler 		return NULL;
132561729d93SAxel Dörfler 
132661729d93SAxel Dörfler 	interface->AcquireReference();
132761729d93SAxel Dörfler 	return interface;
132861729d93SAxel Dörfler }
132961729d93SAxel Dörfler 
133061729d93SAxel Dörfler 
133161729d93SAxel Dörfler Interface*
133261729d93SAxel Dörfler get_interface_for_device(net_domain* domain, uint32 index)
133361729d93SAxel Dörfler {
133461729d93SAxel Dörfler 	MutexLocker locker(sLock);
133561729d93SAxel Dörfler 
133661729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
133761729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
133861729d93SAxel Dörfler 		if (interface->device->index == index) {
133961729d93SAxel Dörfler 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
134061729d93SAxel Dörfler 				return NULL;
134161729d93SAxel Dörfler 
134261729d93SAxel Dörfler 			interface->AcquireReference();
134361729d93SAxel Dörfler 			return interface;
134461729d93SAxel Dörfler 		}
134561729d93SAxel Dörfler 	}
134661729d93SAxel Dörfler 
1347c22d69bfSAxel Dörfler 	return NULL;
1348c22d69bfSAxel Dörfler }
1349c22d69bfSAxel Dörfler 
1350c22d69bfSAxel Dörfler 
1351cd08b9f7SAxel Dörfler /*!	Returns a reference to an Interface that matches the given \a linkAddress.
1352cd08b9f7SAxel Dörfler 	The link address is checked against its hardware address, or its interface
1353cd08b9f7SAxel Dörfler 	name, or finally the interface index.
1354cd08b9f7SAxel Dörfler */
1355cd08b9f7SAxel Dörfler Interface*
1356cd08b9f7SAxel Dörfler get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress)
1357cd08b9f7SAxel Dörfler {
1358cd08b9f7SAxel Dörfler 	sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress;
1359cd08b9f7SAxel Dörfler 
1360cd08b9f7SAxel Dörfler 	MutexLocker locker(sLock);
1361cd08b9f7SAxel Dörfler 
1362cd08b9f7SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1363cd08b9f7SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1364cd08b9f7SAxel Dörfler 		// Test if the hardware address matches, or if the given interface
1365cd08b9f7SAxel Dörfler 		// matches, or if at least the index matches.
1366cd08b9f7SAxel Dörfler 		if ((linkAddress.sdl_alen == interface->device->address.length
1367cd08b9f7SAxel Dörfler 				&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
1368cd08b9f7SAxel Dörfler 					linkAddress.sdl_alen) == 0)
1369cd08b9f7SAxel Dörfler 			|| (linkAddress.sdl_nlen > 0
1370cd08b9f7SAxel Dörfler 				&& !strcmp(interface->name, (const char*)linkAddress.sdl_data))
1371cd08b9f7SAxel Dörfler 			|| (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0
1372cd08b9f7SAxel Dörfler 				&& linkAddress.sdl_index == interface->index)) {
1373cd08b9f7SAxel Dörfler 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
1374cd08b9f7SAxel Dörfler 				return NULL;
1375cd08b9f7SAxel Dörfler 
1376cd08b9f7SAxel Dörfler 			interface->AcquireReference();
1377cd08b9f7SAxel Dörfler 			return interface;
1378cd08b9f7SAxel Dörfler 		}
1379cd08b9f7SAxel Dörfler 	}
1380cd08b9f7SAxel Dörfler 
1381cd08b9f7SAxel Dörfler 	return NULL;
1382cd08b9f7SAxel Dörfler }
1383cd08b9f7SAxel Dörfler 
1384cd08b9f7SAxel Dörfler 
138561729d93SAxel Dörfler InterfaceAddress*
138661729d93SAxel Dörfler get_interface_address(const sockaddr* local)
1387c22d69bfSAxel Dörfler {
138861729d93SAxel Dörfler 	if (local->sa_family == AF_UNSPEC)
138961729d93SAxel Dörfler 		return NULL;
1390c22d69bfSAxel Dörfler 
139161729d93SAxel Dörfler 	MutexLocker locker(sHashLock);
1392c22d69bfSAxel Dörfler 
139361729d93SAxel Dörfler 	InterfaceAddress* address = sAddressTable.Lookup(local);
139461729d93SAxel Dörfler 	if (address == NULL)
139561729d93SAxel Dörfler 		return NULL;
1396c22d69bfSAxel Dörfler 
139761729d93SAxel Dörfler 	address->AcquireReference();
139861729d93SAxel Dörfler 	return address;
139961729d93SAxel Dörfler }
140061729d93SAxel Dörfler 
140161729d93SAxel Dörfler 
140261729d93SAxel Dörfler InterfaceAddress*
140361729d93SAxel Dörfler get_interface_address_for_destination(net_domain* domain,
1404cd08b9f7SAxel Dörfler 	const sockaddr* destination)
140561729d93SAxel Dörfler {
140661729d93SAxel Dörfler 	MutexLocker locker(sLock);
140761729d93SAxel Dörfler 
140861729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
140961729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
141061729d93SAxel Dörfler 		InterfaceAddress* address
141161729d93SAxel Dörfler 			= interface->AddressForDestination(domain, destination);
141261729d93SAxel Dörfler 		if (address != NULL)
141361729d93SAxel Dörfler 			return address;
141461729d93SAxel Dörfler 	}
141561729d93SAxel Dörfler 
141661729d93SAxel Dörfler 	return NULL;
141761729d93SAxel Dörfler }
141861729d93SAxel Dörfler 
141961729d93SAxel Dörfler 
1420cd08b9f7SAxel Dörfler /*!	Returns a reference to an InterfaceAddress of the specified \a domain that
1421cd08b9f7SAxel Dörfler 	belongs to the interface identified via \a linkAddress. Only the hardware
1422cd08b9f7SAxel Dörfler 	address is matched.
1423cd08b9f7SAxel Dörfler 
1424cd08b9f7SAxel Dörfler 	If \a unconfiguredOnly is set, the interface address must not yet be
1425cd08b9f7SAxel Dörfler 	configured, or must currently be in the process of being configured.
1426cd08b9f7SAxel Dörfler */
142761729d93SAxel Dörfler InterfaceAddress*
1428cd08b9f7SAxel Dörfler get_interface_address_for_link(net_domain* domain, const sockaddr* address,
1429cd08b9f7SAxel Dörfler 	bool unconfiguredOnly)
143061729d93SAxel Dörfler {
1431cd08b9f7SAxel Dörfler 	sockaddr_dl& linkAddress = *(sockaddr_dl*)address;
143261729d93SAxel Dörfler 
143361729d93SAxel Dörfler 	MutexLocker locker(sLock);
143461729d93SAxel Dörfler 
143561729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
143661729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1437cd08b9f7SAxel Dörfler 		// Test if the hardware address matches, or if the given interface
1438cd08b9f7SAxel Dörfler 		// matches, or if at least the index matches.
143961729d93SAxel Dörfler 		if (linkAddress.sdl_alen == interface->device->address.length
144061729d93SAxel Dörfler 			&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
144161729d93SAxel Dörfler 				linkAddress.sdl_alen) == 0) {
1442b0cf274aSAxel Dörfler 			TRACE("  %s matches\n", interface->name);
144361729d93SAxel Dörfler 			// link address matches
144461729d93SAxel Dörfler 			if (unconfiguredOnly)
144561729d93SAxel Dörfler 				return interface->FirstUnconfiguredForFamily(domain->family);
144661729d93SAxel Dörfler 
144761729d93SAxel Dörfler 			return interface->FirstForFamily(domain->family);
144861729d93SAxel Dörfler 		}
144961729d93SAxel Dörfler 	}
145061729d93SAxel Dörfler 
145161729d93SAxel Dörfler 	return NULL;
1452c22d69bfSAxel Dörfler }
1453c22d69bfSAxel Dörfler 
1454c22d69bfSAxel Dörfler 
1455c22d69bfSAxel Dörfler uint32
145661729d93SAxel Dörfler count_interfaces()
1457c22d69bfSAxel Dörfler {
145861729d93SAxel Dörfler 	MutexLocker locker(sLock);
1459c22d69bfSAxel Dörfler 
146061729d93SAxel Dörfler 	return sInterfaces.Count();
1461c22d69bfSAxel Dörfler }
1462c22d69bfSAxel Dörfler 
1463c22d69bfSAxel Dörfler 
14643c13a5f5SAxel Dörfler /*!	Dumps a list of all interfaces into the supplied userland buffer.
1465c22d69bfSAxel Dörfler 	If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
1466c22d69bfSAxel Dörfler 	returned.
1467c22d69bfSAxel Dörfler */
1468c22d69bfSAxel Dörfler status_t
146961729d93SAxel Dörfler list_interfaces(int family, void* _buffer, size_t* bufferSize)
1470c22d69bfSAxel Dörfler {
147161729d93SAxel Dörfler 	MutexLocker locker(sLock);
1472c22d69bfSAxel Dörfler 
1473409b1fc0SHugo Santos 	UserBuffer buffer(_buffer, *bufferSize);
1474c22d69bfSAxel Dörfler 
147561729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
147661729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1477715fed44SAxel Dörfler 		// Copy name
1478715fed44SAxel Dörfler 		buffer.Push(interface->name, IF_NAMESIZE);
1479c22d69bfSAxel Dörfler 
1480715fed44SAxel Dörfler 		// Copy address
148161729d93SAxel Dörfler 		InterfaceAddress* address = interface->FirstForFamily(family);
14821f9c8c45SAxel Dörfler 		size_t length = 0;
1483715fed44SAxel Dörfler 
148461729d93SAxel Dörfler 		if (address != NULL && address->local != NULL) {
1485715fed44SAxel Dörfler 			// Actual address
14861f9c8c45SAxel Dörfler 			buffer.Push(address->local, length = address->local->sa_len);
148761729d93SAxel Dörfler 		} else {
1488715fed44SAxel Dörfler 			// Empty address
14891f9c8c45SAxel Dörfler 			sockaddr empty;
14901f9c8c45SAxel Dörfler 			empty.sa_len = 2;
14911f9c8c45SAxel Dörfler 			empty.sa_family = AF_UNSPEC;
14921f9c8c45SAxel Dörfler 			buffer.Push(&empty, length = empty.sa_len);
1493715fed44SAxel Dörfler 		}
1494715fed44SAxel Dörfler 
149561729d93SAxel Dörfler 		if (address != NULL)
149661729d93SAxel Dörfler 			address->ReleaseReference();
149761729d93SAxel Dörfler 
14981f9c8c45SAxel Dörfler 		if (IF_NAMESIZE + length < sizeof(ifreq)) {
14991f9c8c45SAxel Dörfler 			// Make sure at least sizeof(ifreq) bytes are written for each
15001f9c8c45SAxel Dörfler 			// interface for compatibility with other platforms
15011f9c8c45SAxel Dörfler 			buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length);
15021f9c8c45SAxel Dörfler 		}
15031f9c8c45SAxel Dörfler 
15041f9c8c45SAxel Dörfler 		if (buffer.Status() != B_OK)
1505409b1fc0SHugo Santos 			return buffer.Status();
1506c22d69bfSAxel Dörfler 	}
1507c22d69bfSAxel Dörfler 
1508715fed44SAxel Dörfler 	*bufferSize = buffer.BytesConsumed();
1509c22d69bfSAxel Dörfler 	return B_OK;
1510c22d69bfSAxel Dörfler }
1511c22d69bfSAxel Dörfler 
1512c22d69bfSAxel Dörfler 
1513c22d69bfSAxel Dörfler //	#pragma mark -
1514c22d69bfSAxel Dörfler 
1515c22d69bfSAxel Dörfler 
1516c22d69bfSAxel Dörfler status_t
1517c22d69bfSAxel Dörfler init_interfaces()
1518c22d69bfSAxel Dörfler {
151961729d93SAxel Dörfler 	mutex_init(&sLock, "net interfaces");
152061729d93SAxel Dörfler 	mutex_init(&sHashLock, "net local addresses");
1521c22d69bfSAxel Dörfler 
152261729d93SAxel Dörfler 	new (&sInterfaces) InterfaceList;
152361729d93SAxel Dörfler 	new (&sAddressTable) AddressTable;
15249206bb37SAxel Dörfler 		// static C++ objects are not initialized in the module startup
1525a3ec278aSAxel Dörfler 
1526a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1527a3ec278aSAxel Dörfler 	add_debugger_command("net_interface", &dump_interface,
1528a3ec278aSAxel Dörfler 		"Dump the given network interface");
152961729d93SAxel Dörfler 	add_debugger_command("net_interfaces", &dump_interfaces,
153061729d93SAxel Dörfler 		"Dump all network interfaces");
153161729d93SAxel Dörfler 	add_debugger_command("net_local", &dump_local,
153261729d93SAxel Dörfler 		"Dump all local interface addresses");
153361729d93SAxel Dörfler 	add_debugger_command("net_route", &dump_route,
153461729d93SAxel Dörfler 		"Dump the given network route");
1535a3ec278aSAxel Dörfler #endif
1536c22d69bfSAxel Dörfler 	return B_OK;
1537c22d69bfSAxel Dörfler }
1538c22d69bfSAxel Dörfler 
1539c22d69bfSAxel Dörfler 
1540c22d69bfSAxel Dörfler status_t
1541c22d69bfSAxel Dörfler uninit_interfaces()
1542c22d69bfSAxel Dörfler {
1543a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1544a3ec278aSAxel Dörfler 	remove_debugger_command("net_interface", &dump_interface);
1545a3ec278aSAxel Dörfler #endif
1546a3ec278aSAxel Dörfler 
154761729d93SAxel Dörfler 	mutex_destroy(&sLock);
154861729d93SAxel Dörfler 	mutex_destroy(&sHashLock);
1549c22d69bfSAxel Dörfler 	return B_OK;
1550c22d69bfSAxel Dörfler }
1551c22d69bfSAxel Dörfler 
1552