xref: /haiku/src/add-ons/kernel/network/stack/interfaces.cpp (revision 8dcde8b12874429cc7f0f21fdb1d9339b6574cc7)
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 
538910ffb32SAxel Dörfler /*!	Returns a reference to the InterfaceAddress that has the specified
539910ffb32SAxel Dörfler 	\a local address.
540910ffb32SAxel Dörfler */
541910ffb32SAxel Dörfler InterfaceAddress*
542910ffb32SAxel Dörfler Interface::AddressForLocal(net_domain* domain, const sockaddr* local)
543910ffb32SAxel Dörfler {
544910ffb32SAxel Dörfler 	RecursiveLocker locker(fLock);
545910ffb32SAxel Dörfler 
546910ffb32SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
547910ffb32SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
548910ffb32SAxel Dörfler 		if (address->domain == domain
549910ffb32SAxel Dörfler 			&& address->local != NULL
550910ffb32SAxel Dörfler 			&& domain->address_module->equal_addresses(address->local, local)) {
551910ffb32SAxel Dörfler 			address->AcquireReference();
552910ffb32SAxel Dörfler 			return address;
553910ffb32SAxel Dörfler 		}
554910ffb32SAxel Dörfler 	}
555910ffb32SAxel Dörfler 
556910ffb32SAxel Dörfler 	return NULL;
557910ffb32SAxel Dörfler }
558910ffb32SAxel Dörfler 
559910ffb32SAxel 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 
6412c12b8a3SAxel Dörfler int32
6422c12b8a3SAxel Dörfler Interface::IndexOfAddress(InterfaceAddress* address)
6432c12b8a3SAxel Dörfler {
6442c12b8a3SAxel Dörfler 	RecursiveLocker locker(fLock);
6452c12b8a3SAxel Dörfler 
6462c12b8a3SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
6472c12b8a3SAxel Dörfler 	int32 index = 0;
6482c12b8a3SAxel Dörfler 
6492c12b8a3SAxel Dörfler 	while (iterator.HasNext()) {
6502c12b8a3SAxel Dörfler 		if (address == iterator.Next())
6512c12b8a3SAxel Dörfler 			return index;
6522c12b8a3SAxel Dörfler 
6532c12b8a3SAxel Dörfler 		index++;
6542c12b8a3SAxel Dörfler 	}
6552c12b8a3SAxel Dörfler 
6562c12b8a3SAxel Dörfler 	return -1;
6572c12b8a3SAxel Dörfler }
6582c12b8a3SAxel Dörfler 
6592c12b8a3SAxel Dörfler 
6609d771afbSAxel Dörfler size_t
6619d771afbSAxel Dörfler Interface::CountAddresses()
6629d771afbSAxel Dörfler {
6639d771afbSAxel Dörfler 	RecursiveLocker locker(fLock);
6649d771afbSAxel Dörfler 	return fAddresses.Count();
6659d771afbSAxel Dörfler }
6669d771afbSAxel Dörfler 
6679d771afbSAxel Dörfler 
6682b1c0755SAxel Dörfler void
6692b1c0755SAxel Dörfler Interface::RemoveAddresses()
6702b1c0755SAxel Dörfler {
6712b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
6722b1c0755SAxel Dörfler 
6732b1c0755SAxel Dörfler 	while (InterfaceAddress* address = fAddresses.RemoveHead()) {
6742b1c0755SAxel Dörfler 		address->ReleaseReference();
6752b1c0755SAxel Dörfler 	}
6762b1c0755SAxel Dörfler }
6772b1c0755SAxel Dörfler 
6782b1c0755SAxel Dörfler 
6799d771afbSAxel Dörfler /*!	This is called in order to call the correct methods of the datalink
6809d771afbSAxel Dörfler 	protocols, ie. it will translate address changes to
6819d771afbSAxel Dörfler 	net_datalink_protocol::change_address(), and IFF_UP changes to
6829d771afbSAxel Dörfler 	net_datalink_protocol::interface_up(), and interface_down().
6839d771afbSAxel Dörfler 
6849d771afbSAxel Dörfler 	Everything else is passed unchanged to net_datalink_protocol::control().
6859d771afbSAxel Dörfler */
68661729d93SAxel Dörfler status_t
68761729d93SAxel Dörfler Interface::Control(net_domain* domain, int32 option, ifreq& request,
68861729d93SAxel Dörfler 	ifreq* userRequest, size_t length)
68961729d93SAxel Dörfler {
69061729d93SAxel Dörfler 	switch (option) {
69161729d93SAxel Dörfler 		case SIOCSIFFLAGS:
69261729d93SAxel Dörfler 		{
693e8802e49SAxel Dörfler 			if (length != sizeof(ifreq))
694e8802e49SAxel Dörfler 				return B_BAD_VALUE;
695e8802e49SAxel Dörfler 
69661729d93SAxel Dörfler 			uint32 requestFlags = request.ifr_flags;
69761729d93SAxel Dörfler 			uint32 oldFlags = flags;
69861729d93SAxel Dörfler 			status_t status = B_OK;
69961729d93SAxel Dörfler 
70061729d93SAxel Dörfler 			request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST);
70161729d93SAxel Dörfler 
70261729d93SAxel Dörfler 			if ((requestFlags & IFF_UP) != (flags & IFF_UP)) {
70361729d93SAxel Dörfler 				if ((requestFlags & IFF_UP) != 0)
70461729d93SAxel Dörfler 					status = _SetUp();
70561729d93SAxel Dörfler 				else
7062b1c0755SAxel Dörfler 					SetDown();
70761729d93SAxel Dörfler 			}
70861729d93SAxel Dörfler 
70961729d93SAxel Dörfler 			if (status == B_OK) {
71061729d93SAxel Dörfler 				// TODO: maybe allow deleting IFF_BROADCAST on the interface
71161729d93SAxel Dörfler 				// level?
71261729d93SAxel Dörfler 				flags &= IFF_UP | IFF_LINK | IFF_BROADCAST;
71361729d93SAxel Dörfler 				flags |= request.ifr_flags;
71461729d93SAxel Dörfler 			}
71561729d93SAxel Dörfler 
71661729d93SAxel Dörfler 			if (oldFlags != flags)
71761729d93SAxel Dörfler 				notify_interface_changed(this, oldFlags, flags);
71861729d93SAxel Dörfler 
71961729d93SAxel Dörfler 			return status;
72061729d93SAxel Dörfler 		}
72161729d93SAxel Dörfler 
7222b1c0755SAxel Dörfler 		case B_SOCKET_SET_ALIAS:
7239d771afbSAxel Dörfler 		{
724e8802e49SAxel Dörfler 			if (length != sizeof(ifaliasreq))
725e8802e49SAxel Dörfler 				return B_BAD_VALUE;
726e8802e49SAxel Dörfler 
7279d771afbSAxel Dörfler 			RecursiveLocker locker(fLock);
7289d771afbSAxel Dörfler 
7299d771afbSAxel Dörfler 			ifaliasreq aliasRequest;
7309d771afbSAxel Dörfler 			if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq))
7319d771afbSAxel Dörfler 					!= B_OK)
7329d771afbSAxel Dörfler 				return B_BAD_ADDRESS;
7339d771afbSAxel Dörfler 
734910ffb32SAxel Dörfler 			InterfaceAddress* address = NULL;
735910ffb32SAxel Dörfler 			if (aliasRequest.ifra_index < 0) {
736910ffb32SAxel Dörfler 				if (!domain->address_module->is_empty_address(
737910ffb32SAxel Dörfler 						(const sockaddr*)&aliasRequest.ifra_addr, false)) {
738910ffb32SAxel Dörfler 					// Find first address that matches the local address
739910ffb32SAxel Dörfler 					address = AddressForLocal(domain,
740910ffb32SAxel Dörfler 						(const sockaddr*)&aliasRequest.ifra_addr);
741910ffb32SAxel Dörfler 				}
742910ffb32SAxel Dörfler 				if (address == NULL) {
743910ffb32SAxel Dörfler 					// Find first address for family
744910ffb32SAxel Dörfler 					address = FirstForFamily(domain->family);
745910ffb32SAxel Dörfler 				}
746a271028eSAxel Dörfler 				if (address == NULL) {
747a271028eSAxel Dörfler 					// Create new on the fly
748a271028eSAxel Dörfler 					address = new(std::nothrow) InterfaceAddress(this, domain);
749a271028eSAxel Dörfler 					if (address == NULL)
750a271028eSAxel Dörfler 						return B_NO_MEMORY;
751a271028eSAxel Dörfler 
752a271028eSAxel Dörfler 					status_t status = AddAddress(address);
753095f97a6SAxel Dörfler 					if (status != B_OK) {
754095f97a6SAxel Dörfler 						delete address;
755a271028eSAxel Dörfler 						return status;
756095f97a6SAxel Dörfler 					}
757a271028eSAxel Dörfler 
758a271028eSAxel Dörfler 					// Note, even if setting the address failed, the empty
759a271028eSAxel Dörfler 					// address added here will still be added to the interface.
760*8dcde8b1SAxel Dörfler 					address->AcquireReference();
761a271028eSAxel Dörfler 				}
762910ffb32SAxel Dörfler 			} else
763910ffb32SAxel Dörfler 				address = AddressAt(aliasRequest.ifra_index);
764910ffb32SAxel Dörfler 
7659d771afbSAxel Dörfler 			if (address == NULL)
7669d771afbSAxel Dörfler 				return B_BAD_VALUE;
7679d771afbSAxel Dörfler 
7689d771afbSAxel Dörfler 			status_t status = B_OK;
7699d771afbSAxel Dörfler 
7709d771afbSAxel Dörfler 			if (!domain->address_module->equal_addresses(
7719d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_addr, address->local)) {
7729d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address, SIOCSIFADDR,
7739d771afbSAxel Dörfler 					address->local, (sockaddr*)&aliasRequest.ifra_addr);
7749d771afbSAxel Dörfler 			}
7759d771afbSAxel Dörfler 
7769d771afbSAxel Dörfler 			if (status == B_OK && !domain->address_module->equal_addresses(
777910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_mask, address->mask)
778910ffb32SAxel Dörfler 				&& !domain->address_module->is_empty_address(
779910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_mask, false)) {
7809d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address, SIOCSIFNETMASK,
7819d771afbSAxel Dörfler 					address->mask, (sockaddr*)&aliasRequest.ifra_mask);
7829d771afbSAxel Dörfler 			}
7839d771afbSAxel Dörfler 
7849d771afbSAxel Dörfler 			if (status == B_OK && !domain->address_module->equal_addresses(
7859d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination,
786910ffb32SAxel Dörfler 					address->destination)
787910ffb32SAxel Dörfler 				&& !domain->address_module->is_empty_address(
788910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination, false)) {
7899d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address,
7909d771afbSAxel Dörfler 					(domain->address_module->flags
7919d771afbSAxel Dörfler 						& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0
7929d771afbSAxel Dörfler 							? SIOCSIFBRDADDR : SIOCSIFDSTADDR,
7939d771afbSAxel Dörfler 					address->destination,
7949d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination);
7959d771afbSAxel Dörfler 			}
7969d771afbSAxel Dörfler 
7979d771afbSAxel Dörfler 			address->ReleaseReference();
7989d771afbSAxel Dörfler 			return status;
7999d771afbSAxel Dörfler 		}
8009d771afbSAxel Dörfler 
80161729d93SAxel Dörfler 		case SIOCSIFADDR:
80261729d93SAxel Dörfler 		case SIOCSIFNETMASK:
80361729d93SAxel Dörfler 		case SIOCSIFBRDADDR:
80461729d93SAxel Dörfler 		case SIOCSIFDSTADDR:
80561729d93SAxel Dörfler 		case SIOCDIFADDR:
80661729d93SAxel Dörfler 		{
807e8802e49SAxel Dörfler 			if (length != sizeof(ifreq))
808e8802e49SAxel Dörfler 				return B_BAD_VALUE;
809e8802e49SAxel Dörfler 
81061729d93SAxel Dörfler 			RecursiveLocker locker(fLock);
81161729d93SAxel Dörfler 
81261729d93SAxel Dörfler 			InterfaceAddress* address = NULL;
81361729d93SAxel Dörfler 			sockaddr_storage newAddress;
81461729d93SAxel Dörfler 
81561729d93SAxel Dörfler 			size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr));
81661729d93SAxel Dörfler 			if (size > sizeof(sockaddr_storage))
81761729d93SAxel Dörfler 				size = sizeof(sockaddr_storage);
81861729d93SAxel Dörfler 
81961729d93SAxel Dörfler 			if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK)
82061729d93SAxel Dörfler 				return B_BAD_ADDRESS;
82161729d93SAxel Dörfler 
82261729d93SAxel Dörfler 			if (option == SIOCDIFADDR) {
82361729d93SAxel Dörfler 				// Find referring address - we can't use the hash, as another
82461729d93SAxel Dörfler 				// interface might use the same address.
82561729d93SAxel Dörfler 				AddressList::Iterator iterator = fAddresses.GetIterator();
82661729d93SAxel Dörfler 				while ((address = iterator.Next()) != NULL) {
82761729d93SAxel Dörfler 					if (address->domain == domain
82861729d93SAxel Dörfler 						&& domain->address_module->equal_addresses(
82961729d93SAxel Dörfler 							address->local, (sockaddr*)&newAddress))
83061729d93SAxel Dörfler 						break;
83161729d93SAxel Dörfler 				}
83261729d93SAxel Dörfler 
83361729d93SAxel Dörfler 				if (address == NULL)
83461729d93SAxel Dörfler 					return B_BAD_VALUE;
83578abd727SAxel Dörfler 			} else {
83678abd727SAxel Dörfler 				// Just use the first address for this family
83778abd727SAxel Dörfler 				address = _FirstForFamily(domain->family);
83878abd727SAxel Dörfler 				if (address == NULL) {
83978abd727SAxel Dörfler 					// Create new on the fly
84078abd727SAxel Dörfler 					address = new(std::nothrow) InterfaceAddress(this, domain);
84178abd727SAxel Dörfler 					if (address == NULL)
84278abd727SAxel Dörfler 						return B_NO_MEMORY;
84378abd727SAxel Dörfler 
84478abd727SAxel Dörfler 					status_t status = AddAddress(address);
845095f97a6SAxel Dörfler 					if (status != B_OK) {
846095f97a6SAxel Dörfler 						delete address;
84778abd727SAxel Dörfler 						return status;
848095f97a6SAxel Dörfler 					}
84978abd727SAxel Dörfler 
85078abd727SAxel Dörfler 					// Note, even if setting the address failed, the empty
85178abd727SAxel Dörfler 					// address added here will still be added to the interface.
85278abd727SAxel Dörfler 				}
85378abd727SAxel Dörfler 			}
85461729d93SAxel Dörfler 
8559d771afbSAxel Dörfler 			return _ChangeAddress(locker, address, option,
8569d771afbSAxel Dörfler 				*address->AddressFor(option),
85761729d93SAxel Dörfler 				option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL);
85861729d93SAxel Dörfler 		}
85961729d93SAxel Dörfler 
86061729d93SAxel Dörfler 		default:
86161729d93SAxel Dörfler 			// pass the request into the datalink protocol stack
86261729d93SAxel Dörfler 			domain_datalink* datalink = DomainDatalink(domain->family);
86361729d93SAxel Dörfler 			if (datalink->first_info != NULL) {
86461729d93SAxel Dörfler 				return datalink->first_info->control(
86561729d93SAxel Dörfler 					datalink->first_protocol, option, userRequest, length);
86661729d93SAxel Dörfler 			}
86761729d93SAxel Dörfler 			break;
86861729d93SAxel Dörfler 	}
86961729d93SAxel Dörfler 
87061729d93SAxel Dörfler 	return B_BAD_VALUE;
87161729d93SAxel Dörfler }
87261729d93SAxel Dörfler 
87361729d93SAxel Dörfler 
8742b1c0755SAxel Dörfler void
8752b1c0755SAxel Dörfler Interface::SetDown()
8762b1c0755SAxel Dörfler {
8772b1c0755SAxel Dörfler 	if ((flags & IFF_UP) == 0)
8782b1c0755SAxel Dörfler 		return;
8792b1c0755SAxel Dörfler 
8802b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
8812b1c0755SAxel Dörfler 
8822b1c0755SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
8832b1c0755SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
8842b1c0755SAxel Dörfler 		datalink->first_info->interface_down(datalink->first_protocol);
8852b1c0755SAxel Dörfler 	}
8862b1c0755SAxel Dörfler 
8872b1c0755SAxel Dörfler 	flags &= ~IFF_UP;
8882b1c0755SAxel Dörfler }
8892b1c0755SAxel Dörfler 
8902b1c0755SAxel Dörfler 
8912b1c0755SAxel Dörfler /*!	Called when a device lost its IFF_UP status. We will invalidate all
8922b1c0755SAxel Dörfler 	interface routes here.
8932b1c0755SAxel Dörfler */
8942b1c0755SAxel Dörfler void
8952b1c0755SAxel Dörfler Interface::WentDown()
8962b1c0755SAxel Dörfler {
8972b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
8982b1c0755SAxel Dörfler 
8992b1c0755SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
9002b1c0755SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
9012b1c0755SAxel Dörfler 		if (address->domain != NULL)
9022b1c0755SAxel Dörfler 			invalidate_routes(address->domain, this);
9032b1c0755SAxel Dörfler 	}
9042b1c0755SAxel Dörfler }
9052b1c0755SAxel Dörfler 
9062b1c0755SAxel Dörfler 
90761729d93SAxel Dörfler status_t
90861729d93SAxel Dörfler Interface::CreateDomainDatalinkIfNeeded(net_domain* domain)
90961729d93SAxel Dörfler {
91061729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
91161729d93SAxel Dörfler 
91261729d93SAxel Dörfler 	if (fDatalinkTable.Lookup(domain->family) != NULL)
91361729d93SAxel Dörfler 		return B_OK;
91461729d93SAxel Dörfler 
91561729d93SAxel Dörfler 	TRACE("Interface %p: create domain datalink for domain %p\n", this, domain);
91661729d93SAxel Dörfler 
91761729d93SAxel Dörfler 	domain_datalink* datalink = new(std::nothrow) domain_datalink;
91861729d93SAxel Dörfler 	if (datalink == NULL)
91961729d93SAxel Dörfler 		return B_NO_MEMORY;
92061729d93SAxel Dörfler 
92161729d93SAxel Dörfler 	datalink->domain = domain;
92261729d93SAxel Dörfler 
92361729d93SAxel Dörfler 	// setup direct route for bound devices
92461729d93SAxel Dörfler 	datalink->direct_route.destination = NULL;
92561729d93SAxel Dörfler 	datalink->direct_route.mask = NULL;
92661729d93SAxel Dörfler 	datalink->direct_route.gateway = NULL;
92761729d93SAxel Dörfler 	datalink->direct_route.flags = 0;
92861729d93SAxel Dörfler 	datalink->direct_route.mtu = 0;
92961729d93SAxel Dörfler 	datalink->direct_route.interface_address = &datalink->direct_address;
93061729d93SAxel Dörfler 	datalink->direct_route.ref_count = 1;
93161729d93SAxel Dörfler 		// make sure this doesn't get deleted accidently
93261729d93SAxel Dörfler 
93361729d93SAxel Dörfler 	// provide its link back to the interface
93461729d93SAxel Dörfler 	datalink->direct_address.local = NULL;
93561729d93SAxel Dörfler 	datalink->direct_address.destination = NULL;
93661729d93SAxel Dörfler 	datalink->direct_address.mask = NULL;
93761729d93SAxel Dörfler 	datalink->direct_address.domain = domain;
93861729d93SAxel Dörfler 	datalink->direct_address.interface = this;
9392b1c0755SAxel Dörfler 	datalink->direct_address.flags = IFAF_DIRECT_ADDRESS;
94061729d93SAxel Dörfler 
94161729d93SAxel Dörfler 	fDatalinkTable.Insert(datalink);
94261729d93SAxel Dörfler 
94361729d93SAxel Dörfler 	status_t status = get_domain_datalink_protocols(this, domain);
94461729d93SAxel Dörfler 	if (status == B_OK)
94561729d93SAxel Dörfler 		return B_OK;
94661729d93SAxel Dörfler 
94761729d93SAxel Dörfler 	fDatalinkTable.Remove(datalink);
94861729d93SAxel Dörfler 	delete datalink;
94961729d93SAxel Dörfler 
95061729d93SAxel Dörfler 	return status;
95161729d93SAxel Dörfler }
95261729d93SAxel Dörfler 
95361729d93SAxel Dörfler 
95461729d93SAxel Dörfler domain_datalink*
95561729d93SAxel Dörfler Interface::DomainDatalink(uint8 family)
95661729d93SAxel Dörfler {
95761729d93SAxel Dörfler 	// Note: domain datalinks cannot be removed while the interface is alive,
95861729d93SAxel Dörfler 	// since this would require us either to hold the lock while calling this
95961729d93SAxel Dörfler 	// function, or introduce reference counting for the domain_datalink
96061729d93SAxel Dörfler 	// structure.
96161729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
96261729d93SAxel Dörfler 	return fDatalinkTable.Lookup(family);
96361729d93SAxel Dörfler }
96461729d93SAxel Dörfler 
96561729d93SAxel Dörfler 
96661729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
96761729d93SAxel Dörfler 
96861729d93SAxel Dörfler 
96961729d93SAxel Dörfler void
97061729d93SAxel Dörfler Interface::Dump() const
97161729d93SAxel Dörfler {
97261729d93SAxel Dörfler 	kprintf("name:                %s\n", name);
97361729d93SAxel Dörfler 	kprintf("device:              %p\n", device);
97461729d93SAxel Dörfler 	kprintf("device_interface:    %p\n", fDeviceInterface);
97561729d93SAxel Dörfler 	kprintf("index:               %" B_PRIu32 "\n", index);
97661729d93SAxel Dörfler 	kprintf("flags:               %#" B_PRIx32 "\n", flags);
97761729d93SAxel Dörfler 	kprintf("type:                %u\n", type);
97861729d93SAxel Dörfler 	kprintf("mtu:                 %" B_PRIu32 "\n", mtu);
97961729d93SAxel Dörfler 	kprintf("metric:              %" B_PRIu32 "\n", metric);
98061729d93SAxel Dörfler 
98161729d93SAxel Dörfler 	kprintf("datalink protocols:\n");
98261729d93SAxel Dörfler 
98361729d93SAxel Dörfler 	DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator();
98461729d93SAxel Dörfler 	size_t i = 0;
98561729d93SAxel Dörfler 	while (domain_datalink* datalink = datalinkIterator.Next()) {
98661729d93SAxel Dörfler 		kprintf("%2zu. domain:          %p\n", ++i, datalink->domain);
98761729d93SAxel Dörfler 		kprintf("    first_protocol:  %p\n", datalink->first_protocol);
98861729d93SAxel Dörfler 		kprintf("    first_info:      %p\n", datalink->first_info);
98961729d93SAxel Dörfler 		kprintf("    direct_route:    %p\n", &datalink->direct_route);
99061729d93SAxel Dörfler 	}
99161729d93SAxel Dörfler 
99261729d93SAxel Dörfler 	kprintf("addresses:\n");
99361729d93SAxel Dörfler 
99461729d93SAxel Dörfler 	AddressList::ConstIterator iterator = fAddresses.GetIterator();
99561729d93SAxel Dörfler 	i = 0;
99661729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
99761729d93SAxel Dörfler 		address->Dump(++i, true);
99861729d93SAxel Dörfler 	}
99961729d93SAxel Dörfler }
100061729d93SAxel Dörfler 
100161729d93SAxel Dörfler 
100261729d93SAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
100361729d93SAxel Dörfler 
100461729d93SAxel Dörfler 
100561729d93SAxel Dörfler status_t
100661729d93SAxel Dörfler Interface::_SetUp()
100761729d93SAxel Dörfler {
100861729d93SAxel Dörfler 	status_t status = up_device_interface(fDeviceInterface);
100961729d93SAxel Dörfler 	if (status != B_OK)
101061729d93SAxel Dörfler 		return status;
101161729d93SAxel Dörfler 
10122b1c0755SAxel Dörfler 	// Propagate flag to all datalink protocols
101361729d93SAxel Dörfler 
101461729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
101561729d93SAxel Dörfler 
101661729d93SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
101761729d93SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
101861729d93SAxel Dörfler 		status = datalink->first_info->interface_up(datalink->first_protocol);
101961729d93SAxel Dörfler 		if (status != B_OK) {
102061729d93SAxel Dörfler 			// Revert "up" status
102161729d93SAxel Dörfler 			DatalinkTable::Iterator secondIterator
102261729d93SAxel Dörfler 				= fDatalinkTable.GetIterator();
102361729d93SAxel Dörfler 			while (secondIterator.HasNext()) {
102461729d93SAxel Dörfler 				domain_datalink* secondDatalink = secondIterator.Next();
102561729d93SAxel Dörfler 				if (secondDatalink == NULL || secondDatalink == datalink)
1026c22d69bfSAxel Dörfler 					break;
1027c22d69bfSAxel Dörfler 
102861729d93SAxel Dörfler 				secondDatalink->first_info->interface_down(
102961729d93SAxel Dörfler 					secondDatalink->first_protocol);
103061729d93SAxel Dörfler 			}
103161729d93SAxel Dörfler 
103261729d93SAxel Dörfler 			down_device_interface(fDeviceInterface);
103361729d93SAxel Dörfler 			return status;
103461729d93SAxel Dörfler 		}
103561729d93SAxel Dörfler 	}
103661729d93SAxel Dörfler 
10372b1c0755SAxel Dörfler 	// Add default routes for the existing addresses
10382b1c0755SAxel Dörfler 
10392b1c0755SAxel Dörfler 	AddressList::Iterator addressIterator = fAddresses.GetIterator();
10402b1c0755SAxel Dörfler 	while (InterfaceAddress* address = addressIterator.Next()) {
10412b1c0755SAxel Dörfler 		address->AddDefaultRoutes(SIOCSIFADDR);
10422b1c0755SAxel Dörfler 	}
10432b1c0755SAxel Dörfler 
104461729d93SAxel Dörfler 	flags |= IFF_UP;
104561729d93SAxel Dörfler 	return B_OK;
104661729d93SAxel Dörfler }
104761729d93SAxel Dörfler 
104861729d93SAxel Dörfler 
104961729d93SAxel Dörfler InterfaceAddress*
105061729d93SAxel Dörfler Interface::_FirstForFamily(int family)
105161729d93SAxel Dörfler {
105261729d93SAxel Dörfler 	ASSERT_LOCKED_RECURSIVE(&fLock);
105361729d93SAxel Dörfler 
105461729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
105561729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
105661729d93SAxel Dörfler 		if (address->domain != NULL && address->domain->family == family)
105761729d93SAxel Dörfler 			return address;
105861729d93SAxel Dörfler 	}
105961729d93SAxel Dörfler 
106061729d93SAxel Dörfler 	return NULL;
106161729d93SAxel Dörfler }
106261729d93SAxel Dörfler 
106361729d93SAxel Dörfler 
10649d771afbSAxel Dörfler status_t
10659d771afbSAxel Dörfler Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address,
1066b0cf274aSAxel Dörfler 	int32 option, const sockaddr* originalAddress,
1067b0cf274aSAxel Dörfler 	const sockaddr* requestedAddress)
10689d771afbSAxel Dörfler {
1069b0cf274aSAxel Dörfler 	// Copy old address
10709d771afbSAxel Dörfler 	sockaddr_storage oldAddress;
10719d771afbSAxel Dörfler 	if (address->domain->address_module->set_to((sockaddr*)&oldAddress,
10729d771afbSAxel Dörfler 			originalAddress) != B_OK)
10739d771afbSAxel Dörfler 		oldAddress.ss_family = AF_UNSPEC;
10749d771afbSAxel Dörfler 
1075b0cf274aSAxel Dörfler 	// Copy new address (this also makes sure that sockaddr::sa_len is set
1076b0cf274aSAxel Dörfler 	// correctly)
1077b0cf274aSAxel Dörfler 	sockaddr_storage newAddress;
1078b0cf274aSAxel Dörfler 	if (address->domain->address_module->set_to((sockaddr*)&newAddress,
1079b0cf274aSAxel Dörfler 			requestedAddress) != B_OK)
1080b0cf274aSAxel Dörfler 		newAddress.ss_family = AF_UNSPEC;
1081b0cf274aSAxel Dörfler 
10826b1e1488SAxel Dörfler 	// Test if anything changed for real
1083b0cf274aSAxel Dörfler 	if (address->domain->address_module->equal_addresses(
1084b0cf274aSAxel Dörfler 			(sockaddr*)&oldAddress, (sockaddr*)&newAddress)) {
10856b1e1488SAxel Dörfler 		// Nothing to do
1086b0cf274aSAxel Dörfler 		TRACE("  option %" B_PRId32 " addresses are equal!\n", option);
10876b1e1488SAxel Dörfler 		return B_OK;
10886b1e1488SAxel Dörfler 	}
10896b1e1488SAxel Dörfler 
10909d771afbSAxel Dörfler 	// TODO: mark this address busy or call while holding the lock!
10919d771afbSAxel Dörfler 	address->AcquireReference();
10929d771afbSAxel Dörfler 	locker.Unlock();
10939d771afbSAxel Dörfler 
10949d771afbSAxel Dörfler 	domain_datalink* datalink = DomainDatalink(address->domain);
10959d771afbSAxel Dörfler 	status_t status = datalink->first_protocol->module->change_address(
10969d771afbSAxel Dörfler 		datalink->first_protocol, address, option,
10979d771afbSAxel Dörfler 		oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL,
1098b0cf274aSAxel Dörfler 		newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL);
10999d771afbSAxel Dörfler 
11009d771afbSAxel Dörfler 	locker.Lock();
11019d771afbSAxel Dörfler 	address->ReleaseReference();
11029d771afbSAxel Dörfler 	return status;
11039d771afbSAxel Dörfler }
11049d771afbSAxel Dörfler 
11059d771afbSAxel Dörfler 
110661729d93SAxel Dörfler // #pragma mark -
110761729d93SAxel Dörfler 
110861729d93SAxel Dörfler 
110961729d93SAxel Dörfler /*!	Searches for a specific interface by name.
111061729d93SAxel Dörfler 	You need to have the interface list's lock hold when calling this function.
111161729d93SAxel Dörfler */
111261729d93SAxel Dörfler static struct Interface*
111361729d93SAxel Dörfler find_interface(const char* name)
111461729d93SAxel Dörfler {
111561729d93SAxel Dörfler 	ASSERT_LOCKED_MUTEX(&sLock);
111661729d93SAxel Dörfler 
111761729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
111861729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1119c22d69bfSAxel Dörfler 		if (!strcmp(interface->name, name))
1120c22d69bfSAxel Dörfler 			return interface;
1121c22d69bfSAxel Dörfler 	}
1122c22d69bfSAxel Dörfler 
1123c22d69bfSAxel Dörfler 	return NULL;
1124c22d69bfSAxel Dörfler }
1125c22d69bfSAxel Dörfler 
1126c22d69bfSAxel Dörfler 
112761729d93SAxel Dörfler /*!	Searches for a specific interface by index.
112861729d93SAxel Dörfler 	You need to have the interface list's lock hold when calling this function.
1129c22d69bfSAxel Dörfler */
113061729d93SAxel Dörfler static struct Interface*
113161729d93SAxel Dörfler find_interface(uint32 index)
1132c22d69bfSAxel Dörfler {
113361729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
113461729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1135c22d69bfSAxel Dörfler 		if (interface->index == index)
1136c22d69bfSAxel Dörfler 			return interface;
1137c22d69bfSAxel Dörfler 	}
1138c22d69bfSAxel Dörfler 
1139c22d69bfSAxel Dörfler 	return NULL;
1140c22d69bfSAxel Dörfler }
1141c22d69bfSAxel Dörfler 
1142c22d69bfSAxel Dörfler 
114361729d93SAxel Dörfler // #pragma mark -
114461729d93SAxel Dörfler 
114561729d93SAxel Dörfler 
114661729d93SAxel Dörfler status_t
114761729d93SAxel Dörfler add_interface(const char* name, net_domain_private* domain,
114861729d93SAxel Dörfler 	const ifaliasreq& request, net_device_interface* deviceInterface)
114961729d93SAxel Dörfler {
115061729d93SAxel Dörfler 	MutexLocker locker(sLock);
115161729d93SAxel Dörfler 
115261729d93SAxel Dörfler 	if (find_interface(name) != NULL)
115361729d93SAxel Dörfler 		return B_NAME_IN_USE;
115461729d93SAxel Dörfler 
115561729d93SAxel Dörfler 	Interface* interface
115661729d93SAxel Dörfler 		= new(std::nothrow) Interface(name, deviceInterface);
1157c22d69bfSAxel Dörfler 	if (interface == NULL)
1158c22d69bfSAxel Dörfler 		return B_NO_MEMORY;
1159c22d69bfSAxel Dörfler 
116061729d93SAxel Dörfler 	sInterfaces.Add(interface);
116161729d93SAxel Dörfler 	interface->AcquireReference();
116261729d93SAxel Dörfler 		// We need another reference to be able to use the interface without
116361729d93SAxel Dörfler 		// holding sLock.
1164c22d69bfSAxel Dörfler 
116561729d93SAxel Dörfler 	locker.Unlock();
1166c22d69bfSAxel Dörfler 
116761729d93SAxel Dörfler 	notify_interface_added(interface);
116861729d93SAxel Dörfler 	add_interface_address(interface, domain, request);
1169c22d69bfSAxel Dörfler 
117061729d93SAxel Dörfler 	interface->ReleaseReference();
117127e0dea9SAxel Dörfler 
1172c22d69bfSAxel Dörfler 	return B_OK;
1173c22d69bfSAxel Dörfler }
1174c22d69bfSAxel Dörfler 
1175c22d69bfSAxel Dörfler 
117661729d93SAxel Dörfler /*!	Removes the interface from the list, and puts the stack's reference to it.
117761729d93SAxel Dörfler */
11787aa2819cSAxel Dörfler void
117961729d93SAxel Dörfler remove_interface(Interface* interface)
1180c64feccaSHugo Santos {
11812b1c0755SAxel Dörfler 	interface->SetDown();
11822b1c0755SAxel Dörfler 	interface->RemoveAddresses();
1183c64feccaSHugo Santos 
11842b1c0755SAxel Dörfler 	MutexLocker locker(sLock);
11852b1c0755SAxel Dörfler 	sInterfaces.Remove(interface);
11862b1c0755SAxel Dörfler 	locker.Unlock();
1187f6d219a1SAxel Dörfler 
118861729d93SAxel Dörfler 	notify_interface_removed(interface);
1189c22d69bfSAxel Dörfler 
11902b1c0755SAxel Dörfler 	interface->ReleaseReference();
11917aa2819cSAxel Dörfler }
11927aa2819cSAxel Dörfler 
11937aa2819cSAxel Dörfler 
11947aa2819cSAxel Dörfler /*!	This is called whenever a device interface is being removed. We will get
11957aa2819cSAxel Dörfler 	the corresponding Interface, and remove it.
11967aa2819cSAxel Dörfler */
11977aa2819cSAxel Dörfler void
11987aa2819cSAxel Dörfler interface_removed_device_interface(net_device_interface* deviceInterface)
11997aa2819cSAxel Dörfler {
12007aa2819cSAxel Dörfler 	MutexLocker locker(sLock);
12017aa2819cSAxel Dörfler 
12027aa2819cSAxel Dörfler 	Interface* interface = find_interface(deviceInterface->device->name);
12037aa2819cSAxel Dörfler 	if (interface != NULL)
12047aa2819cSAxel Dörfler 		remove_interface(interface);
1205c22d69bfSAxel Dörfler }
1206c22d69bfSAxel Dörfler 
1207c22d69bfSAxel Dörfler 
120861729d93SAxel Dörfler status_t
120961729d93SAxel Dörfler add_interface_address(Interface* interface, net_domain_private* domain,
121061729d93SAxel Dörfler 	const ifaliasreq& request)
1211c22d69bfSAxel Dörfler {
121261729d93SAxel Dörfler 	// Make sure the family of the provided addresses is valid
121361729d93SAxel Dörfler 	if ((request.ifra_addr.ss_family != domain->family
121461729d93SAxel Dörfler 			&& request.ifra_addr.ss_family != AF_UNSPEC)
121561729d93SAxel Dörfler 		|| (request.ifra_mask.ss_family != domain->family
121661729d93SAxel Dörfler 			&& request.ifra_mask.ss_family != AF_UNSPEC)
121761729d93SAxel Dörfler 		|| (request.ifra_broadaddr.ss_family != domain->family
121861729d93SAxel Dörfler 			&& request.ifra_broadaddr.ss_family != AF_UNSPEC))
121961729d93SAxel Dörfler 		return B_BAD_VALUE;
1220c22d69bfSAxel Dörfler 
122161729d93SAxel Dörfler 	RecursiveLocker locker(interface->Lock());
122261729d93SAxel Dörfler 
122361729d93SAxel Dörfler 	InterfaceAddress* address
122461729d93SAxel Dörfler 		= new(std::nothrow) InterfaceAddress(interface, domain);
122561729d93SAxel Dörfler 	if (address == NULL)
122661729d93SAxel Dörfler 		return B_NO_MEMORY;
122761729d93SAxel Dörfler 
122861729d93SAxel Dörfler 	status_t status = address->SetTo(request);
122961729d93SAxel Dörfler 	if (status == B_OK)
123061729d93SAxel Dörfler 		status = interface->CreateDomainDatalinkIfNeeded(domain);
123161729d93SAxel Dörfler 	if (status == B_OK)
123261729d93SAxel Dörfler 		status = interface->AddAddress(address);
123361729d93SAxel Dörfler 
123461729d93SAxel Dörfler 	if (status == B_OK && address->local != NULL) {
123561729d93SAxel Dörfler 		// update the datalink protocols
123661729d93SAxel Dörfler 		domain_datalink* datalink = interface->DomainDatalink(domain->family);
123761729d93SAxel Dörfler 
123861729d93SAxel Dörfler 		status = datalink->first_protocol->module->change_address(
123961729d93SAxel Dörfler 			datalink->first_protocol, address, SIOCAIFADDR, NULL,
124061729d93SAxel Dörfler 			address->local);
124161729d93SAxel Dörfler 		if (status != B_OK)
124261729d93SAxel Dörfler 			interface->RemoveAddress(address);
124361729d93SAxel Dörfler 	}
124461729d93SAxel Dörfler 	if (status == B_OK)
124561729d93SAxel Dörfler 		notify_interface_changed(interface);
124661729d93SAxel Dörfler 	else
124761729d93SAxel Dörfler 		delete address;
124861729d93SAxel Dörfler 
124961729d93SAxel Dörfler 	return status;
125061729d93SAxel Dörfler }
125161729d93SAxel Dörfler 
125261729d93SAxel Dörfler 
125361729d93SAxel Dörfler status_t
125461729d93SAxel Dörfler update_interface_address(InterfaceAddress* interfaceAddress, int32 option,
125561729d93SAxel Dörfler 	const sockaddr* oldAddress, const sockaddr* newAddress)
125661729d93SAxel Dörfler {
1257b0cf274aSAxel Dörfler 	TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress "
1258b0cf274aSAxel Dörfler 		"%s)\n", __FUNCTION__, interfaceAddress, option,
1259b0cf274aSAxel Dörfler 		AddressString(interfaceAddress->domain, oldAddress).Data(),
1260b0cf274aSAxel Dörfler 		AddressString(interfaceAddress->domain, newAddress).Data());
1261b0cf274aSAxel Dörfler 
126261729d93SAxel Dörfler 	MutexLocker locker(sHashLock);
126361729d93SAxel Dörfler 
126461729d93SAxel Dörfler 	// set logical interface address
126561729d93SAxel Dörfler 	sockaddr** _address = interfaceAddress->AddressFor(option);
126661729d93SAxel Dörfler 	if (_address == NULL)
126761729d93SAxel Dörfler 		return B_BAD_VALUE;
126861729d93SAxel Dörfler 
12692b1c0755SAxel Dörfler 	Interface* interface = (Interface*)interfaceAddress->interface;
12702b1c0755SAxel Dörfler 
12712b1c0755SAxel Dörfler 	interfaceAddress->RemoveDefaultRoutes(option);
12722b1c0755SAxel Dörfler 
12732b1c0755SAxel Dörfler 	if (option == SIOCDIFADDR) {
12742b1c0755SAxel Dörfler 		// Remove address, and release its reference (causing our caller to
12752b1c0755SAxel Dörfler 		// delete it)
12762b1c0755SAxel Dörfler 		locker.Unlock();
12772b1c0755SAxel Dörfler 
12782b1c0755SAxel Dörfler 		invalidate_routes(interfaceAddress);
12792b1c0755SAxel Dörfler 
12802b1c0755SAxel Dörfler 		interface->RemoveAddress(interfaceAddress);
12812b1c0755SAxel Dörfler 		interfaceAddress->ReleaseReference();
12822b1c0755SAxel Dörfler 		return B_OK;
12832b1c0755SAxel Dörfler 	}
12842b1c0755SAxel Dörfler 
128561729d93SAxel Dörfler 	sAddressTable.Remove(interfaceAddress);
128661729d93SAxel Dörfler 
128761729d93SAxel Dörfler 	// Copy new address over
128861729d93SAxel Dörfler 	status_t status = InterfaceAddress::Set(_address, newAddress);
128961729d93SAxel Dörfler 	if (status == B_OK) {
129061729d93SAxel Dörfler 		sockaddr* address = *_address;
129161729d93SAxel Dörfler 
12921ebd87f4SAxel Dörfler 		if (option == SIOCSIFADDR) {
129361729d93SAxel Dörfler 			// Reset netmask and broadcast addresses to defaults
129461729d93SAxel Dörfler 			net_domain* domain = interfaceAddress->domain;
129561729d93SAxel Dörfler 			sockaddr* netmask = NULL;
129661729d93SAxel Dörfler 			const sockaddr* oldNetmask = NULL;
129761729d93SAxel Dörfler 			if (option == SIOCSIFADDR) {
129861729d93SAxel Dörfler 				netmask = InterfaceAddress::Prepare(
129961729d93SAxel Dörfler 					&interfaceAddress->mask, address->sa_len);
130061729d93SAxel Dörfler 			} else {
130161729d93SAxel Dörfler 				oldNetmask = oldAddress;
130261729d93SAxel Dörfler 				netmask = interfaceAddress->mask;
130361729d93SAxel Dörfler 			}
130461729d93SAxel Dörfler 
130561729d93SAxel Dörfler 			// Reset the broadcast address if the address family has
130661729d93SAxel Dörfler 			// such
130761729d93SAxel Dörfler 			sockaddr* broadcast = NULL;
130861729d93SAxel Dörfler 			if ((domain->address_module->flags
130961729d93SAxel Dörfler 					& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) {
131061729d93SAxel Dörfler 				broadcast = InterfaceAddress::Prepare(
131161729d93SAxel Dörfler 					&interfaceAddress->destination, address->sa_len);
131261729d93SAxel Dörfler 			} else
131361729d93SAxel Dörfler 				InterfaceAddress::Set(&interfaceAddress->destination, NULL);
131461729d93SAxel Dörfler 
131561729d93SAxel Dörfler 			domain->address_module->set_to_defaults(netmask, broadcast,
131661729d93SAxel Dörfler 				interfaceAddress->local, oldNetmask);
131761729d93SAxel Dörfler 		}
131861729d93SAxel Dörfler 
13192b1c0755SAxel Dörfler 		interfaceAddress->AddDefaultRoutes(option);
13202b1c0755SAxel Dörfler 		notify_interface_changed(interface);
132161729d93SAxel Dörfler 	}
132261729d93SAxel Dörfler 
132361729d93SAxel Dörfler 	sAddressTable.Insert(interfaceAddress);
132461729d93SAxel Dörfler 	return status;
132561729d93SAxel Dörfler }
132661729d93SAxel Dörfler 
132761729d93SAxel Dörfler 
132861729d93SAxel Dörfler Interface*
132961729d93SAxel Dörfler get_interface(net_domain* domain, uint32 index)
133061729d93SAxel Dörfler {
133161729d93SAxel Dörfler 	MutexLocker locker(sLock);
133261729d93SAxel Dörfler 
133361729d93SAxel Dörfler 	if (index == 0)
133461729d93SAxel Dörfler 		return sInterfaces.First();
133561729d93SAxel Dörfler 
133661729d93SAxel Dörfler 	Interface* interface = find_interface(index);
1337c22d69bfSAxel Dörfler 	if (interface == NULL)
133861729d93SAxel Dörfler 		return NULL;
1339c22d69bfSAxel Dörfler 
134061729d93SAxel Dörfler 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
134161729d93SAxel Dörfler 		return NULL;
134261729d93SAxel Dörfler 
134361729d93SAxel Dörfler 	interface->AcquireReference();
1344c22d69bfSAxel Dörfler 	return interface;
1345c22d69bfSAxel Dörfler }
1346c22d69bfSAxel Dörfler 
134761729d93SAxel Dörfler 
134861729d93SAxel Dörfler Interface*
134961729d93SAxel Dörfler get_interface(net_domain* domain, const char* name)
135061729d93SAxel Dörfler {
135161729d93SAxel Dörfler 	MutexLocker locker(sLock);
135261729d93SAxel Dörfler 
135361729d93SAxel Dörfler 	Interface* interface = find_interface(name);
135461729d93SAxel Dörfler 	if (interface == NULL)
135561729d93SAxel Dörfler 		return NULL;
135661729d93SAxel Dörfler 
135761729d93SAxel Dörfler 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
135861729d93SAxel Dörfler 		return NULL;
135961729d93SAxel Dörfler 
136061729d93SAxel Dörfler 	interface->AcquireReference();
136161729d93SAxel Dörfler 	return interface;
136261729d93SAxel Dörfler }
136361729d93SAxel Dörfler 
136461729d93SAxel Dörfler 
136561729d93SAxel Dörfler Interface*
136661729d93SAxel Dörfler get_interface_for_device(net_domain* domain, uint32 index)
136761729d93SAxel Dörfler {
136861729d93SAxel Dörfler 	MutexLocker locker(sLock);
136961729d93SAxel Dörfler 
137061729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
137161729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
137261729d93SAxel Dörfler 		if (interface->device->index == index) {
137361729d93SAxel Dörfler 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
137461729d93SAxel Dörfler 				return NULL;
137561729d93SAxel Dörfler 
137661729d93SAxel Dörfler 			interface->AcquireReference();
137761729d93SAxel Dörfler 			return interface;
137861729d93SAxel Dörfler 		}
137961729d93SAxel Dörfler 	}
138061729d93SAxel Dörfler 
1381c22d69bfSAxel Dörfler 	return NULL;
1382c22d69bfSAxel Dörfler }
1383c22d69bfSAxel Dörfler 
1384c22d69bfSAxel Dörfler 
1385cd08b9f7SAxel Dörfler /*!	Returns a reference to an Interface that matches the given \a linkAddress.
1386cd08b9f7SAxel Dörfler 	The link address is checked against its hardware address, or its interface
1387cd08b9f7SAxel Dörfler 	name, or finally the interface index.
1388cd08b9f7SAxel Dörfler */
1389cd08b9f7SAxel Dörfler Interface*
1390cd08b9f7SAxel Dörfler get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress)
1391cd08b9f7SAxel Dörfler {
1392cd08b9f7SAxel Dörfler 	sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress;
1393cd08b9f7SAxel Dörfler 
1394cd08b9f7SAxel Dörfler 	MutexLocker locker(sLock);
1395cd08b9f7SAxel Dörfler 
1396cd08b9f7SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1397cd08b9f7SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1398cd08b9f7SAxel Dörfler 		// Test if the hardware address matches, or if the given interface
1399cd08b9f7SAxel Dörfler 		// matches, or if at least the index matches.
1400cd08b9f7SAxel Dörfler 		if ((linkAddress.sdl_alen == interface->device->address.length
1401cd08b9f7SAxel Dörfler 				&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
1402cd08b9f7SAxel Dörfler 					linkAddress.sdl_alen) == 0)
1403cd08b9f7SAxel Dörfler 			|| (linkAddress.sdl_nlen > 0
1404cd08b9f7SAxel Dörfler 				&& !strcmp(interface->name, (const char*)linkAddress.sdl_data))
1405cd08b9f7SAxel Dörfler 			|| (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0
1406cd08b9f7SAxel Dörfler 				&& linkAddress.sdl_index == interface->index)) {
1407cd08b9f7SAxel Dörfler 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
1408cd08b9f7SAxel Dörfler 				return NULL;
1409cd08b9f7SAxel Dörfler 
1410cd08b9f7SAxel Dörfler 			interface->AcquireReference();
1411cd08b9f7SAxel Dörfler 			return interface;
1412cd08b9f7SAxel Dörfler 		}
1413cd08b9f7SAxel Dörfler 	}
1414cd08b9f7SAxel Dörfler 
1415cd08b9f7SAxel Dörfler 	return NULL;
1416cd08b9f7SAxel Dörfler }
1417cd08b9f7SAxel Dörfler 
1418cd08b9f7SAxel Dörfler 
141961729d93SAxel Dörfler InterfaceAddress*
142061729d93SAxel Dörfler get_interface_address(const sockaddr* local)
1421c22d69bfSAxel Dörfler {
142261729d93SAxel Dörfler 	if (local->sa_family == AF_UNSPEC)
142361729d93SAxel Dörfler 		return NULL;
1424c22d69bfSAxel Dörfler 
142561729d93SAxel Dörfler 	MutexLocker locker(sHashLock);
1426c22d69bfSAxel Dörfler 
142761729d93SAxel Dörfler 	InterfaceAddress* address = sAddressTable.Lookup(local);
142861729d93SAxel Dörfler 	if (address == NULL)
142961729d93SAxel Dörfler 		return NULL;
1430c22d69bfSAxel Dörfler 
143161729d93SAxel Dörfler 	address->AcquireReference();
143261729d93SAxel Dörfler 	return address;
143361729d93SAxel Dörfler }
143461729d93SAxel Dörfler 
143561729d93SAxel Dörfler 
143661729d93SAxel Dörfler InterfaceAddress*
143761729d93SAxel Dörfler get_interface_address_for_destination(net_domain* domain,
1438cd08b9f7SAxel Dörfler 	const sockaddr* destination)
143961729d93SAxel Dörfler {
144061729d93SAxel Dörfler 	MutexLocker locker(sLock);
144161729d93SAxel Dörfler 
144261729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
144361729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
144461729d93SAxel Dörfler 		InterfaceAddress* address
144561729d93SAxel Dörfler 			= interface->AddressForDestination(domain, destination);
144661729d93SAxel Dörfler 		if (address != NULL)
144761729d93SAxel Dörfler 			return address;
144861729d93SAxel Dörfler 	}
144961729d93SAxel Dörfler 
145061729d93SAxel Dörfler 	return NULL;
145161729d93SAxel Dörfler }
145261729d93SAxel Dörfler 
145361729d93SAxel Dörfler 
1454cd08b9f7SAxel Dörfler /*!	Returns a reference to an InterfaceAddress of the specified \a domain that
1455cd08b9f7SAxel Dörfler 	belongs to the interface identified via \a linkAddress. Only the hardware
1456cd08b9f7SAxel Dörfler 	address is matched.
1457cd08b9f7SAxel Dörfler 
1458cd08b9f7SAxel Dörfler 	If \a unconfiguredOnly is set, the interface address must not yet be
1459cd08b9f7SAxel Dörfler 	configured, or must currently be in the process of being configured.
1460cd08b9f7SAxel Dörfler */
146161729d93SAxel Dörfler InterfaceAddress*
1462cd08b9f7SAxel Dörfler get_interface_address_for_link(net_domain* domain, const sockaddr* address,
1463cd08b9f7SAxel Dörfler 	bool unconfiguredOnly)
146461729d93SAxel Dörfler {
1465cd08b9f7SAxel Dörfler 	sockaddr_dl& linkAddress = *(sockaddr_dl*)address;
146661729d93SAxel Dörfler 
146761729d93SAxel Dörfler 	MutexLocker locker(sLock);
146861729d93SAxel Dörfler 
146961729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
147061729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1471cd08b9f7SAxel Dörfler 		// Test if the hardware address matches, or if the given interface
1472cd08b9f7SAxel Dörfler 		// matches, or if at least the index matches.
147361729d93SAxel Dörfler 		if (linkAddress.sdl_alen == interface->device->address.length
147461729d93SAxel Dörfler 			&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
147561729d93SAxel Dörfler 				linkAddress.sdl_alen) == 0) {
1476b0cf274aSAxel Dörfler 			TRACE("  %s matches\n", interface->name);
147761729d93SAxel Dörfler 			// link address matches
147861729d93SAxel Dörfler 			if (unconfiguredOnly)
147961729d93SAxel Dörfler 				return interface->FirstUnconfiguredForFamily(domain->family);
148061729d93SAxel Dörfler 
148161729d93SAxel Dörfler 			return interface->FirstForFamily(domain->family);
148261729d93SAxel Dörfler 		}
148361729d93SAxel Dörfler 	}
148461729d93SAxel Dörfler 
148561729d93SAxel Dörfler 	return NULL;
1486c22d69bfSAxel Dörfler }
1487c22d69bfSAxel Dörfler 
1488c22d69bfSAxel Dörfler 
1489c22d69bfSAxel Dörfler uint32
149061729d93SAxel Dörfler count_interfaces()
1491c22d69bfSAxel Dörfler {
149261729d93SAxel Dörfler 	MutexLocker locker(sLock);
1493c22d69bfSAxel Dörfler 
149461729d93SAxel Dörfler 	return sInterfaces.Count();
1495c22d69bfSAxel Dörfler }
1496c22d69bfSAxel Dörfler 
1497c22d69bfSAxel Dörfler 
14983c13a5f5SAxel Dörfler /*!	Dumps a list of all interfaces into the supplied userland buffer.
1499c22d69bfSAxel Dörfler 	If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
1500c22d69bfSAxel Dörfler 	returned.
1501c22d69bfSAxel Dörfler */
1502c22d69bfSAxel Dörfler status_t
150361729d93SAxel Dörfler list_interfaces(int family, void* _buffer, size_t* bufferSize)
1504c22d69bfSAxel Dörfler {
150561729d93SAxel Dörfler 	MutexLocker locker(sLock);
1506c22d69bfSAxel Dörfler 
1507409b1fc0SHugo Santos 	UserBuffer buffer(_buffer, *bufferSize);
1508c22d69bfSAxel Dörfler 
150961729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
151061729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1511715fed44SAxel Dörfler 		// Copy name
1512715fed44SAxel Dörfler 		buffer.Push(interface->name, IF_NAMESIZE);
1513c22d69bfSAxel Dörfler 
1514715fed44SAxel Dörfler 		// Copy address
151561729d93SAxel Dörfler 		InterfaceAddress* address = interface->FirstForFamily(family);
15161f9c8c45SAxel Dörfler 		size_t length = 0;
1517715fed44SAxel Dörfler 
151861729d93SAxel Dörfler 		if (address != NULL && address->local != NULL) {
1519715fed44SAxel Dörfler 			// Actual address
15201f9c8c45SAxel Dörfler 			buffer.Push(address->local, length = address->local->sa_len);
152161729d93SAxel Dörfler 		} else {
1522715fed44SAxel Dörfler 			// Empty address
15231f9c8c45SAxel Dörfler 			sockaddr empty;
15241f9c8c45SAxel Dörfler 			empty.sa_len = 2;
15251f9c8c45SAxel Dörfler 			empty.sa_family = AF_UNSPEC;
15261f9c8c45SAxel Dörfler 			buffer.Push(&empty, length = empty.sa_len);
1527715fed44SAxel Dörfler 		}
1528715fed44SAxel Dörfler 
152961729d93SAxel Dörfler 		if (address != NULL)
153061729d93SAxel Dörfler 			address->ReleaseReference();
153161729d93SAxel Dörfler 
15321f9c8c45SAxel Dörfler 		if (IF_NAMESIZE + length < sizeof(ifreq)) {
15331f9c8c45SAxel Dörfler 			// Make sure at least sizeof(ifreq) bytes are written for each
15341f9c8c45SAxel Dörfler 			// interface for compatibility with other platforms
15351f9c8c45SAxel Dörfler 			buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length);
15361f9c8c45SAxel Dörfler 		}
15371f9c8c45SAxel Dörfler 
15381f9c8c45SAxel Dörfler 		if (buffer.Status() != B_OK)
1539409b1fc0SHugo Santos 			return buffer.Status();
1540c22d69bfSAxel Dörfler 	}
1541c22d69bfSAxel Dörfler 
1542715fed44SAxel Dörfler 	*bufferSize = buffer.BytesConsumed();
1543c22d69bfSAxel Dörfler 	return B_OK;
1544c22d69bfSAxel Dörfler }
1545c22d69bfSAxel Dörfler 
1546c22d69bfSAxel Dörfler 
1547c22d69bfSAxel Dörfler //	#pragma mark -
1548c22d69bfSAxel Dörfler 
1549c22d69bfSAxel Dörfler 
1550c22d69bfSAxel Dörfler status_t
1551c22d69bfSAxel Dörfler init_interfaces()
1552c22d69bfSAxel Dörfler {
155361729d93SAxel Dörfler 	mutex_init(&sLock, "net interfaces");
155461729d93SAxel Dörfler 	mutex_init(&sHashLock, "net local addresses");
1555c22d69bfSAxel Dörfler 
155661729d93SAxel Dörfler 	new (&sInterfaces) InterfaceList;
155761729d93SAxel Dörfler 	new (&sAddressTable) AddressTable;
15589206bb37SAxel Dörfler 		// static C++ objects are not initialized in the module startup
1559a3ec278aSAxel Dörfler 
1560a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1561a3ec278aSAxel Dörfler 	add_debugger_command("net_interface", &dump_interface,
1562a3ec278aSAxel Dörfler 		"Dump the given network interface");
156361729d93SAxel Dörfler 	add_debugger_command("net_interfaces", &dump_interfaces,
156461729d93SAxel Dörfler 		"Dump all network interfaces");
156561729d93SAxel Dörfler 	add_debugger_command("net_local", &dump_local,
156661729d93SAxel Dörfler 		"Dump all local interface addresses");
156761729d93SAxel Dörfler 	add_debugger_command("net_route", &dump_route,
156861729d93SAxel Dörfler 		"Dump the given network route");
1569a3ec278aSAxel Dörfler #endif
1570c22d69bfSAxel Dörfler 	return B_OK;
1571c22d69bfSAxel Dörfler }
1572c22d69bfSAxel Dörfler 
1573c22d69bfSAxel Dörfler 
1574c22d69bfSAxel Dörfler status_t
1575c22d69bfSAxel Dörfler uninit_interfaces()
1576c22d69bfSAxel Dörfler {
1577a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1578a3ec278aSAxel Dörfler 	remove_debugger_command("net_interface", &dump_interface);
1579a3ec278aSAxel Dörfler #endif
1580a3ec278aSAxel Dörfler 
158161729d93SAxel Dörfler 	mutex_destroy(&sLock);
158261729d93SAxel Dörfler 	mutex_destroy(&sHashLock);
1583c22d69bfSAxel Dörfler 	return B_OK;
1584c22d69bfSAxel Dörfler }
1585c22d69bfSAxel Dörfler 
1586