xref: /haiku/src/add-ons/kernel/network/stack/interfaces.cpp (revision 7ed2a4437610d5a342d3d2a9950311cbc5e89a9e)
1c22d69bfSAxel Dörfler /*
24ae58630SAxel Dörfler  * Copyright 2006-2011, 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 	{
574ae58630SAxel Dörfler 		return address->domain->address_module->hash_address(address->local,
584ae58630SAxel Dörfler 			false);
5961729d93SAxel Dörfler 	}
6061729d93SAxel Dörfler 
6161729d93SAxel Dörfler 	bool Compare(const KeyType& key, InterfaceAddress* address) const
6261729d93SAxel Dörfler 	{
6361729d93SAxel Dörfler 		if (address->local == NULL)
6461729d93SAxel Dörfler 			return key->sa_family == AF_UNSPEC;
6561729d93SAxel Dörfler 
6661729d93SAxel Dörfler 		if (address->local->sa_family != key->sa_family)
6761729d93SAxel Dörfler 			return false;
6861729d93SAxel Dörfler 
6961729d93SAxel Dörfler 		return address->domain->address_module->equal_addresses(key,
7061729d93SAxel Dörfler 			address->local);
7161729d93SAxel Dörfler 	}
7261729d93SAxel Dörfler 
7361729d93SAxel Dörfler 	InterfaceAddress*& GetLink(InterfaceAddress* address) const
7461729d93SAxel Dörfler 	{
7561729d93SAxel Dörfler 		return address->HashTableLink();
7661729d93SAxel Dörfler 	}
7761729d93SAxel Dörfler };
7861729d93SAxel Dörfler 
794ae58630SAxel Dörfler typedef BOpenHashTable<AddressHashDefinition, true, false> AddressTable;
80a3ec278aSAxel Dörfler 
81c22d69bfSAxel Dörfler 
828a6337d0SStefano Ceccherini static recursive_lock sLock;
8361729d93SAxel Dörfler static InterfaceList sInterfaces;
8461729d93SAxel Dörfler static mutex sHashLock;
8561729d93SAxel Dörfler static AddressTable sAddressTable;
86c22d69bfSAxel Dörfler static uint32 sInterfaceIndex;
879261b129SHugo Santos 
889261b129SHugo Santos 
89ec4fb0f4SAxel Dörfler #if 0
90ec4fb0f4SAxel Dörfler //! For debugging purposes only
91ec4fb0f4SAxel Dörfler void
92ec4fb0f4SAxel Dörfler dump_interface_refs(void)
93ec4fb0f4SAxel Dörfler {
948a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
95ec4fb0f4SAxel Dörfler 
96ec4fb0f4SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
97ec4fb0f4SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
98ec4fb0f4SAxel Dörfler 		dprintf("%p: %s, %ld\n", interface, interface->name,
99ec4fb0f4SAxel Dörfler 			interface->CountReferences());
100ec4fb0f4SAxel Dörfler 	}
101ec4fb0f4SAxel Dörfler }
102ec4fb0f4SAxel Dörfler #endif
103ec4fb0f4SAxel Dörfler 
104ec4fb0f4SAxel Dörfler 
105a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
106a3ec278aSAxel Dörfler 
107a3ec278aSAxel Dörfler 
108a3ec278aSAxel Dörfler static int
109a3ec278aSAxel Dörfler dump_interface(int argc, char** argv)
110a3ec278aSAxel Dörfler {
111a3ec278aSAxel Dörfler 	if (argc != 2) {
11211eccb54SAxel Dörfler 		kprintf("usage: %s [name|address]\n", argv[0]);
113a3ec278aSAxel Dörfler 		return 0;
114a3ec278aSAxel Dörfler 	}
115a3ec278aSAxel Dörfler 
11611eccb54SAxel Dörfler 	Interface* interface = NULL;
11711eccb54SAxel Dörfler 
11811eccb54SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
11911eccb54SAxel Dörfler 	while ((interface = iterator.Next()) != NULL) {
12011eccb54SAxel Dörfler 		if (!strcmp(argv[1], interface->name))
12111eccb54SAxel Dörfler 			break;
12211eccb54SAxel Dörfler 	}
12311eccb54SAxel Dörfler 
12411eccb54SAxel Dörfler 	if (interface == NULL)
12511eccb54SAxel Dörfler 		interface = (Interface*)parse_expression(argv[1]);
12611eccb54SAxel Dörfler 
12761729d93SAxel Dörfler 	interface->Dump();
128a3ec278aSAxel Dörfler 
129a3ec278aSAxel Dörfler 	return 0;
130a3ec278aSAxel Dörfler }
131a3ec278aSAxel Dörfler 
132a3ec278aSAxel Dörfler 
133a3ec278aSAxel Dörfler static int
13461729d93SAxel Dörfler dump_interfaces(int argc, char** argv)
13561729d93SAxel Dörfler {
13661729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
13761729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
13861729d93SAxel Dörfler 		kprintf("%p  %s\n", interface, interface->name);
13961729d93SAxel Dörfler 	}
14061729d93SAxel Dörfler 	return 0;
14161729d93SAxel Dörfler }
14261729d93SAxel Dörfler 
14361729d93SAxel Dörfler 
14461729d93SAxel Dörfler static int
14561729d93SAxel Dörfler dump_local(int argc, char** argv)
14661729d93SAxel Dörfler {
14761729d93SAxel Dörfler 	AddressTable::Iterator iterator = sAddressTable.GetIterator();
14861729d93SAxel Dörfler 	size_t i = 0;
14961729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
15061729d93SAxel Dörfler 		address->Dump(++i);
1516d796a84SAlex Smith 		dprintf("    hash:          %" B_PRIu32 "\n",
15261729d93SAxel Dörfler 			address->domain->address_module->hash_address(address->local,
15361729d93SAxel Dörfler 				false));
15461729d93SAxel Dörfler 	}
15561729d93SAxel Dörfler 	return 0;
15661729d93SAxel Dörfler }
15761729d93SAxel Dörfler 
15861729d93SAxel Dörfler 
15961729d93SAxel Dörfler static int
16061729d93SAxel Dörfler dump_route(int argc, char** argv)
161a3ec278aSAxel Dörfler {
162a3ec278aSAxel Dörfler 	if (argc != 2) {
163a3ec278aSAxel Dörfler 		kprintf("usage: %s [address]\n", argv[0]);
164a3ec278aSAxel Dörfler 		return 0;
165a3ec278aSAxel Dörfler 	}
166a3ec278aSAxel Dörfler 
16761729d93SAxel Dörfler 	net_route* route = (net_route*)parse_expression(argv[1]);
16861729d93SAxel Dörfler 	kprintf("destination:       %p\n", route->destination);
16961729d93SAxel Dörfler 	kprintf("mask:              %p\n", route->mask);
17061729d93SAxel Dörfler 	kprintf("gateway:           %p\n", route->gateway);
17161729d93SAxel Dörfler 	kprintf("flags:             %" B_PRIx32 "\n", route->flags);
17261729d93SAxel Dörfler 	kprintf("mtu:               %" B_PRIu32 "\n", route->mtu);
17361729d93SAxel Dörfler 	kprintf("interface address: %p\n", route->interface_address);
174a3ec278aSAxel Dörfler 
17561729d93SAxel Dörfler 	if (route->interface_address != NULL) {
17661729d93SAxel Dörfler 		((InterfaceAddress*)route->interface_address)->Dump();
177a3ec278aSAxel Dörfler 	}
178a3ec278aSAxel Dörfler 
179a3ec278aSAxel Dörfler 	return 0;
180a3ec278aSAxel Dörfler }
181a3ec278aSAxel Dörfler 
182a3ec278aSAxel Dörfler 
183a3ec278aSAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
184a3ec278aSAxel Dörfler 
185a3ec278aSAxel Dörfler 
18661729d93SAxel Dörfler InterfaceAddress::InterfaceAddress()
187c22d69bfSAxel Dörfler {
18861729d93SAxel Dörfler 	_Init(NULL, NULL);
18961729d93SAxel Dörfler }
190c22d69bfSAxel Dörfler 
19161729d93SAxel Dörfler 
19261729d93SAxel Dörfler InterfaceAddress::InterfaceAddress(net_interface* netInterface,
19361729d93SAxel Dörfler 	net_domain* netDomain)
19461729d93SAxel Dörfler {
19561729d93SAxel Dörfler 	_Init(netInterface, netDomain);
19661729d93SAxel Dörfler }
19761729d93SAxel Dörfler 
19861729d93SAxel Dörfler 
19961729d93SAxel Dörfler InterfaceAddress::~InterfaceAddress()
20061729d93SAxel Dörfler {
2012b1c0755SAxel Dörfler 	TRACE("InterfaceAddress %p: destructor\n", this);
2022b1c0755SAxel Dörfler 
2032b1c0755SAxel Dörfler 	if (interface != NULL && (flags & IFAF_DIRECT_ADDRESS) == 0)
2042b1c0755SAxel Dörfler 		((Interface*)interface)->ReleaseReference();
20561729d93SAxel Dörfler }
20661729d93SAxel Dörfler 
20761729d93SAxel Dörfler 
20861729d93SAxel Dörfler status_t
20961729d93SAxel Dörfler InterfaceAddress::SetTo(const ifaliasreq& request)
21061729d93SAxel Dörfler {
21161729d93SAxel Dörfler 	status_t status = SetLocal((const sockaddr*)&request.ifra_addr);
21261729d93SAxel Dörfler 	if (status == B_OK)
21361729d93SAxel Dörfler 		status = SetDestination((const sockaddr*)&request.ifra_broadaddr);
21461729d93SAxel Dörfler 	if (status == B_OK)
21561729d93SAxel Dörfler 		status = SetMask((const sockaddr*)&request.ifra_mask);
21661729d93SAxel Dörfler 
21761729d93SAxel Dörfler 	return status;
21861729d93SAxel Dörfler }
21961729d93SAxel Dörfler 
22061729d93SAxel Dörfler 
22161729d93SAxel Dörfler status_t
22261729d93SAxel Dörfler InterfaceAddress::SetLocal(const sockaddr* to)
22361729d93SAxel Dörfler {
22461729d93SAxel Dörfler 	return Set(&local, to);
22561729d93SAxel Dörfler }
22661729d93SAxel Dörfler 
22761729d93SAxel Dörfler 
22861729d93SAxel Dörfler status_t
22961729d93SAxel Dörfler InterfaceAddress::SetDestination(const sockaddr* to)
23061729d93SAxel Dörfler {
23161729d93SAxel Dörfler 	return Set(&destination, to);
23261729d93SAxel Dörfler }
23361729d93SAxel Dörfler 
23461729d93SAxel Dörfler 
23561729d93SAxel Dörfler status_t
23661729d93SAxel Dörfler InterfaceAddress::SetMask(const sockaddr* to)
23761729d93SAxel Dörfler {
23861729d93SAxel Dörfler 	return Set(&mask, to);
23961729d93SAxel Dörfler }
24061729d93SAxel Dörfler 
24161729d93SAxel Dörfler 
24261729d93SAxel Dörfler sockaddr**
24361729d93SAxel Dörfler InterfaceAddress::AddressFor(int32 option)
24461729d93SAxel Dörfler {
24561729d93SAxel Dörfler 	switch (option) {
24661729d93SAxel Dörfler 		case SIOCSIFADDR:
24761729d93SAxel Dörfler 		case SIOCGIFADDR:
2482b1c0755SAxel Dörfler 		case SIOCDIFADDR:
24961729d93SAxel Dörfler 			return &local;
25061729d93SAxel Dörfler 
25161729d93SAxel Dörfler 		case SIOCSIFNETMASK:
25261729d93SAxel Dörfler 		case SIOCGIFNETMASK:
25361729d93SAxel Dörfler 			return &mask;
25461729d93SAxel Dörfler 
25561729d93SAxel Dörfler 		case SIOCSIFBRDADDR:
25661729d93SAxel Dörfler 		case SIOCSIFDSTADDR:
25761729d93SAxel Dörfler 		case SIOCGIFBRDADDR:
25861729d93SAxel Dörfler 		case SIOCGIFDSTADDR:
25961729d93SAxel Dörfler 			return &destination;
26061729d93SAxel Dörfler 
26161729d93SAxel Dörfler 		default:
26261729d93SAxel Dörfler 			return NULL;
26361729d93SAxel Dörfler 	}
26461729d93SAxel Dörfler }
26561729d93SAxel Dörfler 
26661729d93SAxel Dörfler 
2672b1c0755SAxel Dörfler /*!	Adds the default routes that every interface address needs, ie. the local
2682b1c0755SAxel Dörfler 	host route, and one for the subnet (if set).
2692b1c0755SAxel Dörfler */
2702b1c0755SAxel Dörfler void
2712b1c0755SAxel Dörfler InterfaceAddress::AddDefaultRoutes(int32 option)
2722b1c0755SAxel Dörfler {
2732b1c0755SAxel Dörfler 	net_route route;
2742b1c0755SAxel Dörfler 	route.destination = local;
2752b1c0755SAxel Dörfler 	route.gateway = NULL;
2762b1c0755SAxel Dörfler 	route.interface_address = this;
2772b1c0755SAxel Dörfler 
2782b1c0755SAxel Dörfler 	if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
2792b1c0755SAxel Dörfler 		route.mask = mask;
2802b1c0755SAxel Dörfler 		route.flags = 0;
2812b1c0755SAxel Dörfler 		add_route(domain, &route);
2822b1c0755SAxel Dörfler 	}
2832b1c0755SAxel Dörfler 
2842b1c0755SAxel Dörfler 	if (option == SIOCSIFADDR) {
2852b1c0755SAxel Dörfler 		route.mask = NULL;
2862b1c0755SAxel Dörfler 		route.flags = RTF_LOCAL | RTF_HOST;
2872b1c0755SAxel Dörfler 		add_route(domain, &route);
2882b1c0755SAxel Dörfler 	}
2892b1c0755SAxel Dörfler }
2902b1c0755SAxel Dörfler 
2912b1c0755SAxel Dörfler 
2922b1c0755SAxel Dörfler /*!	Removes the default routes as set by AddDefaultRoutes() again. */
2932b1c0755SAxel Dörfler void
2942b1c0755SAxel Dörfler InterfaceAddress::RemoveDefaultRoutes(int32 option)
2952b1c0755SAxel Dörfler {
2962b1c0755SAxel Dörfler 	net_route route;
2972b1c0755SAxel Dörfler 	route.destination = local;
2982b1c0755SAxel Dörfler 	route.gateway = NULL;
2992b1c0755SAxel Dörfler 	route.interface_address = this;
3002b1c0755SAxel Dörfler 
3012b1c0755SAxel Dörfler 	if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
3022b1c0755SAxel Dörfler 		route.mask = mask;
3032b1c0755SAxel Dörfler 		route.flags = 0;
3042b1c0755SAxel Dörfler 		remove_route(domain, &route);
3052b1c0755SAxel Dörfler 	}
3062b1c0755SAxel Dörfler 
3072b1c0755SAxel Dörfler 	if (option == SIOCSIFADDR) {
3082b1c0755SAxel Dörfler 		route.mask = NULL;
3092b1c0755SAxel Dörfler 		route.flags = RTF_LOCAL | RTF_HOST;
3102b1c0755SAxel Dörfler 		remove_route(domain, &route);
3112b1c0755SAxel Dörfler 	}
3122b1c0755SAxel Dörfler }
3132b1c0755SAxel Dörfler 
3142b1c0755SAxel Dörfler 
3154ae58630SAxel Dörfler bool
3164ae58630SAxel Dörfler InterfaceAddress::LocalIsDefined() const
3174ae58630SAxel Dörfler {
3184ae58630SAxel Dörfler 	return local != NULL && local->sa_family != AF_UNSPEC;
3194ae58630SAxel Dörfler }
3204ae58630SAxel Dörfler 
3214ae58630SAxel Dörfler 
32261729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
32361729d93SAxel Dörfler 
32461729d93SAxel Dörfler 
32561729d93SAxel Dörfler void
32661729d93SAxel Dörfler InterfaceAddress::Dump(size_t index, bool hideInterface)
32761729d93SAxel Dörfler {
32861729d93SAxel Dörfler 	if (index)
32961729d93SAxel Dörfler 		kprintf("%2zu. ", index);
33061729d93SAxel Dörfler 	else
33161729d93SAxel Dörfler 		kprintf("    ");
33261729d93SAxel Dörfler 
33361729d93SAxel Dörfler 	if (!hideInterface) {
33461729d93SAxel Dörfler 		kprintf("interface:   %p (%s)\n    ", interface,
33561729d93SAxel Dörfler 			interface != NULL ? interface->name : "-");
33661729d93SAxel Dörfler 	}
33761729d93SAxel Dörfler 
33861729d93SAxel Dörfler 	kprintf("domain:      %p (family %u)\n", domain,
33961729d93SAxel Dörfler 		domain != NULL ? domain->family : AF_UNSPEC);
34061729d93SAxel Dörfler 
34161729d93SAxel Dörfler 	char buffer[64];
34261729d93SAxel Dörfler 	if (local != NULL && domain != NULL) {
34361729d93SAxel Dörfler 		domain->address_module->print_address_buffer(local, buffer,
34461729d93SAxel Dörfler 			sizeof(buffer), false);
34561729d93SAxel Dörfler 	} else
34661729d93SAxel Dörfler 		strcpy(buffer, "-");
34761729d93SAxel Dörfler 	kprintf("    local:       %s\n", buffer);
34861729d93SAxel Dörfler 
34961729d93SAxel Dörfler 	if (mask != NULL && domain != NULL) {
35061729d93SAxel Dörfler 		domain->address_module->print_address_buffer(mask, buffer,
35161729d93SAxel Dörfler 			sizeof(buffer), false);
35261729d93SAxel Dörfler 	} else
35361729d93SAxel Dörfler 		strcpy(buffer, "-");
35461729d93SAxel Dörfler 	kprintf("    mask:        %s\n", buffer);
35561729d93SAxel Dörfler 
35661729d93SAxel Dörfler 	if (destination != NULL && domain != NULL) {
35761729d93SAxel Dörfler 		domain->address_module->print_address_buffer(destination, buffer,
35861729d93SAxel Dörfler 			sizeof(buffer), false);
35961729d93SAxel Dörfler 	} else
36061729d93SAxel Dörfler 		strcpy(buffer, "-");
36161729d93SAxel Dörfler 	kprintf("    destination: %s\n", buffer);
3624af124a1SAxel Dörfler 
3634af124a1SAxel Dörfler 	kprintf("    ref count:   %" B_PRId32 "\n", CountReferences());
36461729d93SAxel Dörfler }
36561729d93SAxel Dörfler 
36661729d93SAxel Dörfler 
36761729d93SAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
36861729d93SAxel Dörfler 
36961729d93SAxel Dörfler 
37061729d93SAxel Dörfler /*static*/ status_t
37161729d93SAxel Dörfler InterfaceAddress::Set(sockaddr** _address, const sockaddr* to)
37261729d93SAxel Dörfler {
37361729d93SAxel Dörfler 	sockaddr* address = *_address;
37461729d93SAxel Dörfler 
37561729d93SAxel Dörfler 	if (to == NULL || to->sa_family == AF_UNSPEC) {
37661729d93SAxel Dörfler 		// Clear address
37761729d93SAxel Dörfler 		free(address);
37861729d93SAxel Dörfler 		*_address = NULL;
37961729d93SAxel Dörfler 		return B_OK;
38061729d93SAxel Dörfler 	}
38161729d93SAxel Dörfler 
38261729d93SAxel Dörfler 	// Set address
38361729d93SAxel Dörfler 
38461729d93SAxel Dörfler 	size_t size = max_c(to->sa_len, sizeof(sockaddr));
38561729d93SAxel Dörfler 	if (size > sizeof(sockaddr_storage))
38661729d93SAxel Dörfler 		size = sizeof(sockaddr_storage);
38761729d93SAxel Dörfler 
38861729d93SAxel Dörfler 	address = Prepare(_address, size);
38961729d93SAxel Dörfler 	if (address == NULL)
39061729d93SAxel Dörfler 		return B_NO_MEMORY;
39161729d93SAxel Dörfler 
39261729d93SAxel Dörfler 	memcpy(address, to, size);
39361729d93SAxel Dörfler 	address->sa_len = size;
39461729d93SAxel Dörfler 
39561729d93SAxel Dörfler 	return B_OK;
39661729d93SAxel Dörfler }
39761729d93SAxel Dörfler 
39861729d93SAxel Dörfler 
3995ebd9548SAxel Dörfler /*!	Makes sure that the sockaddr object pointed to by \a _address is large
4005ebd9548SAxel Dörfler 	enough to hold \a size bytes.
4015ebd9548SAxel Dörfler 	\a _address may point to NULL when calling this method.
4025ebd9548SAxel Dörfler */
40361729d93SAxel Dörfler /*static*/ sockaddr*
40461729d93SAxel Dörfler InterfaceAddress::Prepare(sockaddr** _address, size_t size)
40561729d93SAxel Dörfler {
40661729d93SAxel Dörfler 	size = max_c(size, sizeof(sockaddr));
40761729d93SAxel Dörfler 	if (size > sizeof(sockaddr_storage))
40861729d93SAxel Dörfler 		size = sizeof(sockaddr_storage);
40961729d93SAxel Dörfler 
41061729d93SAxel Dörfler 	sockaddr* address = *_address;
41161729d93SAxel Dörfler 
41261729d93SAxel Dörfler 	if (address == NULL || size > address->sa_len) {
41361729d93SAxel Dörfler 		address = (sockaddr*)realloc(address, size);
41461729d93SAxel Dörfler 		if (address == NULL)
41561729d93SAxel Dörfler 			return NULL;
41661729d93SAxel Dörfler 	}
41761729d93SAxel Dörfler 
41861729d93SAxel Dörfler 	address->sa_len = size;
41961729d93SAxel Dörfler 
42061729d93SAxel Dörfler 	*_address = address;
42161729d93SAxel Dörfler 	return address;
42261729d93SAxel Dörfler }
42361729d93SAxel Dörfler 
42461729d93SAxel Dörfler 
42561729d93SAxel Dörfler void
42661729d93SAxel Dörfler InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain)
42761729d93SAxel Dörfler {
4282b1c0755SAxel Dörfler 	TRACE("InterfaceAddress %p: init interface %p, domain %p\n", this,
4292b1c0755SAxel Dörfler 		netInterface, netDomain);
4302b1c0755SAxel Dörfler 
43161729d93SAxel Dörfler 	interface = netInterface;
43261729d93SAxel Dörfler 	domain = netDomain;
43361729d93SAxel Dörfler 	local = NULL;
43461729d93SAxel Dörfler 	destination = NULL;
43561729d93SAxel Dörfler 	mask = NULL;
4362b1c0755SAxel Dörfler 	flags = 0;
4372b1c0755SAxel Dörfler 
4382b1c0755SAxel Dörfler 	if (interface != NULL)
4392b1c0755SAxel Dörfler 		((Interface*)interface)->AcquireReference();
44061729d93SAxel Dörfler }
44161729d93SAxel Dörfler 
44261729d93SAxel Dörfler 
44361729d93SAxel Dörfler // #pragma mark -
44461729d93SAxel Dörfler 
44561729d93SAxel Dörfler 
44661729d93SAxel Dörfler Interface::Interface(const char* interfaceName,
44761729d93SAxel Dörfler 	net_device_interface* deviceInterface)
448ff8c8dfcSStefano Ceccherini 	:
449ff8c8dfcSStefano Ceccherini 	fBusy(false)
45061729d93SAxel Dörfler {
45161729d93SAxel Dörfler 	TRACE("Interface %p: new \"%s\", device interface %p\n", this,
45261729d93SAxel Dörfler 		interfaceName, deviceInterface);
45361729d93SAxel Dörfler 
454b0cf274aSAxel Dörfler 	int written = strlcpy(name, interfaceName, IF_NAMESIZE);
455b0cf274aSAxel Dörfler 	memset(name + written, 0, IF_NAMESIZE - written);
456b0cf274aSAxel Dörfler 		// Clear remaining space
457b0cf274aSAxel Dörfler 
45861729d93SAxel Dörfler 	device = deviceInterface->device;
45961729d93SAxel Dörfler 
46061729d93SAxel Dörfler 	index = ++sInterfaceIndex;
46161729d93SAxel Dörfler 	flags = 0;
46261729d93SAxel Dörfler 	type = 0;
46361729d93SAxel Dörfler 	mtu = deviceInterface->device->mtu;
46461729d93SAxel Dörfler 	metric = 0;
46561729d93SAxel Dörfler 
46661729d93SAxel Dörfler 	fDeviceInterface = acquire_device_interface(deviceInterface);
46761729d93SAxel Dörfler 
46861729d93SAxel Dörfler 	recursive_lock_init(&fLock, name);
46961729d93SAxel Dörfler 
47061729d93SAxel Dörfler 	// Grab a reference to the networking stack, to make sure it won't be
47161729d93SAxel Dörfler 	// unloaded as long as an interface exists
47261729d93SAxel Dörfler 	module_info* module;
47361729d93SAxel Dörfler 	get_module(gNetStackInterfaceModule.info.name, &module);
47461729d93SAxel Dörfler }
47561729d93SAxel Dörfler 
47661729d93SAxel Dörfler 
47761729d93SAxel Dörfler Interface::~Interface()
47861729d93SAxel Dörfler {
4792b1c0755SAxel Dörfler 	TRACE("Interface %p: destructor\n", this);
4802b1c0755SAxel Dörfler 
4812b1c0755SAxel Dörfler 	put_device_interface(fDeviceInterface);
4822b1c0755SAxel Dörfler 
4832b1c0755SAxel Dörfler 	// Uninitialize the domain datalink protocols
4842b1c0755SAxel Dörfler 
4852b1c0755SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
4862b1c0755SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
4872b1c0755SAxel Dörfler 		put_domain_datalink_protocols(this, datalink->domain);
4882b1c0755SAxel Dörfler 	}
4892b1c0755SAxel Dörfler 
4902b1c0755SAxel Dörfler 	// Free domain datalink objects
4912b1c0755SAxel Dörfler 
4922b1c0755SAxel Dörfler 	domain_datalink* next = fDatalinkTable.Clear(true);
4932b1c0755SAxel Dörfler 	while (next != NULL) {
4942b1c0755SAxel Dörfler 		domain_datalink* datalink = next;
4952b1c0755SAxel Dörfler 		next = next->hash_link;
4962b1c0755SAxel Dörfler 
4972b1c0755SAxel Dörfler 		delete datalink;
4982b1c0755SAxel Dörfler 	}
4992b1c0755SAxel Dörfler 
50061729d93SAxel Dörfler 	recursive_lock_destroy(&fLock);
50161729d93SAxel Dörfler 
50261729d93SAxel Dörfler 	// Release reference of the stack - at this point, our stack may be unloaded
50361729d93SAxel Dörfler 	// if no other interfaces or sockets are left
50461729d93SAxel Dörfler 	put_module(gNetStackInterfaceModule.info.name);
50561729d93SAxel Dörfler }
50661729d93SAxel Dörfler 
50761729d93SAxel Dörfler 
50861729d93SAxel Dörfler /*!	Returns a reference to the first InterfaceAddress that is from the same
50961729d93SAxel Dörfler 	as the specified \a family.
51061729d93SAxel Dörfler */
51161729d93SAxel Dörfler InterfaceAddress*
51261729d93SAxel Dörfler Interface::FirstForFamily(int family)
51361729d93SAxel Dörfler {
51461729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
51561729d93SAxel Dörfler 
51661729d93SAxel Dörfler 	InterfaceAddress* address = _FirstForFamily(family);
51761729d93SAxel Dörfler 	if (address != NULL) {
51861729d93SAxel Dörfler 		address->AcquireReference();
51961729d93SAxel Dörfler 		return address;
52061729d93SAxel Dörfler 	}
52161729d93SAxel Dörfler 
52261729d93SAxel Dörfler 	return NULL;
52361729d93SAxel Dörfler }
52461729d93SAxel Dörfler 
52561729d93SAxel Dörfler 
52661729d93SAxel Dörfler /*!	Returns a reference to the first unconfigured address of this interface
52761729d93SAxel Dörfler 	for the specified \a family.
52861729d93SAxel Dörfler */
52961729d93SAxel Dörfler InterfaceAddress*
53061729d93SAxel Dörfler Interface::FirstUnconfiguredForFamily(int family)
53161729d93SAxel Dörfler {
53261729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
53361729d93SAxel Dörfler 
53461729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
53561729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
53661729d93SAxel Dörfler 		if (address->domain->family == family
53761729d93SAxel Dörfler 			&& (address->local == NULL
53861729d93SAxel Dörfler 				// TODO: this has to be solved differently!!
53961729d93SAxel Dörfler 				|| (flags & IFF_CONFIGURING) != 0)) {
54061729d93SAxel Dörfler 			address->AcquireReference();
54161729d93SAxel Dörfler 			return address;
54261729d93SAxel Dörfler 		}
54361729d93SAxel Dörfler 	}
54461729d93SAxel Dörfler 
54561729d93SAxel Dörfler 	return NULL;
54661729d93SAxel Dörfler }
54761729d93SAxel Dörfler 
54861729d93SAxel Dörfler 
54961729d93SAxel Dörfler /*!	Returns a reference to the InterfaceAddress that has the specified
55061729d93SAxel Dörfler 	\a destination address.
55161729d93SAxel Dörfler */
55261729d93SAxel Dörfler InterfaceAddress*
55361729d93SAxel Dörfler Interface::AddressForDestination(net_domain* domain,
55461729d93SAxel Dörfler 	const sockaddr* destination)
55561729d93SAxel Dörfler {
55661729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
55761729d93SAxel Dörfler 
55861729d93SAxel Dörfler 	if ((device->flags & IFF_BROADCAST) == 0) {
55961729d93SAxel Dörfler 		// The device does not support broadcasting
56061729d93SAxel Dörfler 		return NULL;
56161729d93SAxel Dörfler 	}
56261729d93SAxel Dörfler 
56361729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
56461729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
56561729d93SAxel Dörfler 		if (address->domain == domain
56661729d93SAxel Dörfler 			&& address->destination != NULL
56761729d93SAxel Dörfler 			&& domain->address_module->equal_addresses(address->destination,
56861729d93SAxel Dörfler 					destination)) {
56961729d93SAxel Dörfler 			address->AcquireReference();
57061729d93SAxel Dörfler 			return address;
57161729d93SAxel Dörfler 		}
57261729d93SAxel Dörfler 	}
57361729d93SAxel Dörfler 
57461729d93SAxel Dörfler 	return NULL;
57561729d93SAxel Dörfler }
57661729d93SAxel Dörfler 
57761729d93SAxel Dörfler 
578910ffb32SAxel Dörfler /*!	Returns a reference to the InterfaceAddress that has the specified
579910ffb32SAxel Dörfler 	\a local address.
580910ffb32SAxel Dörfler */
581910ffb32SAxel Dörfler InterfaceAddress*
582910ffb32SAxel Dörfler Interface::AddressForLocal(net_domain* domain, const sockaddr* local)
583910ffb32SAxel Dörfler {
584910ffb32SAxel Dörfler 	RecursiveLocker locker(fLock);
585910ffb32SAxel Dörfler 
586910ffb32SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
587910ffb32SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
588910ffb32SAxel Dörfler 		if (address->domain == domain
589910ffb32SAxel Dörfler 			&& address->local != NULL
590910ffb32SAxel Dörfler 			&& domain->address_module->equal_addresses(address->local, local)) {
591910ffb32SAxel Dörfler 			address->AcquireReference();
592910ffb32SAxel Dörfler 			return address;
593910ffb32SAxel Dörfler 		}
594910ffb32SAxel Dörfler 	}
595910ffb32SAxel Dörfler 
596910ffb32SAxel Dörfler 	return NULL;
597910ffb32SAxel Dörfler }
598910ffb32SAxel Dörfler 
599910ffb32SAxel Dörfler 
60061729d93SAxel Dörfler status_t
60161729d93SAxel Dörfler Interface::AddAddress(InterfaceAddress* address)
60261729d93SAxel Dörfler {
60361729d93SAxel Dörfler 	net_domain* domain = address->domain;
60461729d93SAxel Dörfler 	if (domain == NULL)
60561729d93SAxel Dörfler 		return B_BAD_VALUE;
60661729d93SAxel Dörfler 
60761729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
60861729d93SAxel Dörfler 	fAddresses.Add(address);
60961729d93SAxel Dörfler 	locker.Unlock();
61061729d93SAxel Dörfler 
6114ae58630SAxel Dörfler 	if (address->LocalIsDefined()) {
61261729d93SAxel Dörfler 		MutexLocker hashLocker(sHashLock);
61361729d93SAxel Dörfler 		sAddressTable.Insert(address);
6144ae58630SAxel Dörfler 	}
61561729d93SAxel Dörfler 	return B_OK;
61661729d93SAxel Dörfler }
61761729d93SAxel Dörfler 
61861729d93SAxel Dörfler 
61961729d93SAxel Dörfler void
62061729d93SAxel Dörfler Interface::RemoveAddress(InterfaceAddress* address)
62161729d93SAxel Dörfler {
62261729d93SAxel Dörfler 	net_domain* domain = address->domain;
62361729d93SAxel Dörfler 	if (domain == NULL)
62461729d93SAxel Dörfler 		return;
62561729d93SAxel Dörfler 
62661729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
62761729d93SAxel Dörfler 
62861729d93SAxel Dörfler 	fAddresses.Remove(address);
62961729d93SAxel Dörfler 	address->GetDoublyLinkedListLink()->next = NULL;
63061729d93SAxel Dörfler 
63161729d93SAxel Dörfler 	locker.Unlock();
63261729d93SAxel Dörfler 
6334ae58630SAxel Dörfler 	if (address->LocalIsDefined()) {
63461729d93SAxel Dörfler 		MutexLocker hashLocker(sHashLock);
63561729d93SAxel Dörfler 		sAddressTable.Remove(address);
63661729d93SAxel Dörfler 	}
6374ae58630SAxel Dörfler }
63861729d93SAxel Dörfler 
63961729d93SAxel Dörfler 
64061729d93SAxel Dörfler bool
64161729d93SAxel Dörfler Interface::GetNextAddress(InterfaceAddress** _address)
64261729d93SAxel Dörfler {
64361729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
64461729d93SAxel Dörfler 
64561729d93SAxel Dörfler 	InterfaceAddress* address = *_address;
64661729d93SAxel Dörfler 	if (address == NULL) {
64761729d93SAxel Dörfler 		// get first address
64861729d93SAxel Dörfler 		address = fAddresses.First();
64961729d93SAxel Dörfler 	} else {
65061729d93SAxel Dörfler 		// get next, if possible
65161729d93SAxel Dörfler 		InterfaceAddress* next = fAddresses.GetNext(address);
65261729d93SAxel Dörfler 		address->ReleaseReference();
65361729d93SAxel Dörfler 		address = next;
65461729d93SAxel Dörfler 	}
65561729d93SAxel Dörfler 
65661729d93SAxel Dörfler 	*_address = address;
65761729d93SAxel Dörfler 
65861729d93SAxel Dörfler 	if (address == NULL)
65961729d93SAxel Dörfler 		return false;
66061729d93SAxel Dörfler 
66161729d93SAxel Dörfler 	address->AcquireReference();
66261729d93SAxel Dörfler 	return true;
66361729d93SAxel Dörfler }
66461729d93SAxel Dörfler 
66561729d93SAxel Dörfler 
6669d771afbSAxel Dörfler InterfaceAddress*
6679d771afbSAxel Dörfler Interface::AddressAt(size_t index)
6689d771afbSAxel Dörfler {
6699d771afbSAxel Dörfler 	RecursiveLocker locker(fLock);
6709d771afbSAxel Dörfler 
6719d771afbSAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
6729d771afbSAxel Dörfler 	size_t i = 0;
6739d771afbSAxel Dörfler 
6749d771afbSAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
6759d771afbSAxel Dörfler 		if (i++ == index) {
6769d771afbSAxel Dörfler 			address->AcquireReference();
6779d771afbSAxel Dörfler 			return address;
6789d771afbSAxel Dörfler 		}
6799d771afbSAxel Dörfler 	}
6809d771afbSAxel Dörfler 
6819d771afbSAxel Dörfler 	return NULL;
6829d771afbSAxel Dörfler }
6839d771afbSAxel Dörfler 
6849d771afbSAxel Dörfler 
6852c12b8a3SAxel Dörfler int32
6862c12b8a3SAxel Dörfler Interface::IndexOfAddress(InterfaceAddress* address)
6872c12b8a3SAxel Dörfler {
688b0766602SAxel Dörfler 	if (address == NULL)
689b0766602SAxel Dörfler 		return -1;
690b0766602SAxel Dörfler 
6912c12b8a3SAxel Dörfler 	RecursiveLocker locker(fLock);
6922c12b8a3SAxel Dörfler 
6932c12b8a3SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
6942c12b8a3SAxel Dörfler 	int32 index = 0;
6952c12b8a3SAxel Dörfler 
6962c12b8a3SAxel Dörfler 	while (iterator.HasNext()) {
6972c12b8a3SAxel Dörfler 		if (address == iterator.Next())
6982c12b8a3SAxel Dörfler 			return index;
6992c12b8a3SAxel Dörfler 
7002c12b8a3SAxel Dörfler 		index++;
7012c12b8a3SAxel Dörfler 	}
7022c12b8a3SAxel Dörfler 
7032c12b8a3SAxel Dörfler 	return -1;
7042c12b8a3SAxel Dörfler }
7052c12b8a3SAxel Dörfler 
7062c12b8a3SAxel Dörfler 
7079d771afbSAxel Dörfler size_t
7089d771afbSAxel Dörfler Interface::CountAddresses()
7099d771afbSAxel Dörfler {
7109d771afbSAxel Dörfler 	RecursiveLocker locker(fLock);
7119d771afbSAxel Dörfler 	return fAddresses.Count();
7129d771afbSAxel Dörfler }
7139d771afbSAxel Dörfler 
7149d771afbSAxel Dörfler 
7152b1c0755SAxel Dörfler void
7162b1c0755SAxel Dörfler Interface::RemoveAddresses()
7172b1c0755SAxel Dörfler {
7182b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
7192b1c0755SAxel Dörfler 
7202b1c0755SAxel Dörfler 	while (InterfaceAddress* address = fAddresses.RemoveHead()) {
721b0766602SAxel Dörfler 		locker.Unlock();
722b0766602SAxel Dörfler 
723b0766602SAxel Dörfler 		if (address->LocalIsDefined()) {
724b0766602SAxel Dörfler 			MutexLocker hashLocker(sHashLock);
725b0766602SAxel Dörfler 			sAddressTable.Remove(address);
726b0766602SAxel Dörfler 		}
7275ebd9548SAxel Dörfler 		address->ReleaseReference();
728b0766602SAxel Dörfler 
729b0766602SAxel Dörfler 		locker.Lock();
7302b1c0755SAxel Dörfler 	}
7312b1c0755SAxel Dörfler }
7322b1c0755SAxel Dörfler 
7332b1c0755SAxel Dörfler 
7349d771afbSAxel Dörfler /*!	This is called in order to call the correct methods of the datalink
7359d771afbSAxel Dörfler 	protocols, ie. it will translate address changes to
7369d771afbSAxel Dörfler 	net_datalink_protocol::change_address(), and IFF_UP changes to
7379d771afbSAxel Dörfler 	net_datalink_protocol::interface_up(), and interface_down().
7389d771afbSAxel Dörfler 
7399d771afbSAxel Dörfler 	Everything else is passed unchanged to net_datalink_protocol::control().
7409d771afbSAxel Dörfler */
74161729d93SAxel Dörfler status_t
74261729d93SAxel Dörfler Interface::Control(net_domain* domain, int32 option, ifreq& request,
74361729d93SAxel Dörfler 	ifreq* userRequest, size_t length)
74461729d93SAxel Dörfler {
74561729d93SAxel Dörfler 	switch (option) {
74661729d93SAxel Dörfler 		case SIOCSIFFLAGS:
74761729d93SAxel Dörfler 		{
748e8802e49SAxel Dörfler 			if (length != sizeof(ifreq))
749e8802e49SAxel Dörfler 				return B_BAD_VALUE;
750e8802e49SAxel Dörfler 
75161729d93SAxel Dörfler 			uint32 requestFlags = request.ifr_flags;
75261729d93SAxel Dörfler 			uint32 oldFlags = flags;
75361729d93SAxel Dörfler 			status_t status = B_OK;
75461729d93SAxel Dörfler 
75561729d93SAxel Dörfler 			request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST);
75661729d93SAxel Dörfler 
75761729d93SAxel Dörfler 			if ((requestFlags & IFF_UP) != (flags & IFF_UP)) {
75861729d93SAxel Dörfler 				if ((requestFlags & IFF_UP) != 0)
75961729d93SAxel Dörfler 					status = _SetUp();
76061729d93SAxel Dörfler 				else
7612b1c0755SAxel Dörfler 					SetDown();
76261729d93SAxel Dörfler 			}
76361729d93SAxel Dörfler 
76461729d93SAxel Dörfler 			if (status == B_OK) {
76561729d93SAxel Dörfler 				// TODO: maybe allow deleting IFF_BROADCAST on the interface
76661729d93SAxel Dörfler 				// level?
76761729d93SAxel Dörfler 				flags &= IFF_UP | IFF_LINK | IFF_BROADCAST;
76861729d93SAxel Dörfler 				flags |= request.ifr_flags;
76961729d93SAxel Dörfler 			}
77061729d93SAxel Dörfler 
771e78fea43SAxel Dörfler 			if (oldFlags != flags) {
772e78fea43SAxel Dörfler 				TRACE("Interface %p: flags changed from %" B_PRIx32 " to %"
773e78fea43SAxel Dörfler 					B_PRIx32 "\n", this, oldFlags, flags);
77461729d93SAxel Dörfler 				notify_interface_changed(this, oldFlags, flags);
775e78fea43SAxel Dörfler 			}
77661729d93SAxel Dörfler 
77761729d93SAxel Dörfler 			return status;
77861729d93SAxel Dörfler 		}
77961729d93SAxel Dörfler 
7802b1c0755SAxel Dörfler 		case B_SOCKET_SET_ALIAS:
7819d771afbSAxel Dörfler 		{
782e8802e49SAxel Dörfler 			if (length != sizeof(ifaliasreq))
783e8802e49SAxel Dörfler 				return B_BAD_VALUE;
784e8802e49SAxel Dörfler 
7859d771afbSAxel Dörfler 			RecursiveLocker locker(fLock);
7869d771afbSAxel Dörfler 
7879d771afbSAxel Dörfler 			ifaliasreq aliasRequest;
7889d771afbSAxel Dörfler 			if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq))
7899d771afbSAxel Dörfler 					!= B_OK)
7909d771afbSAxel Dörfler 				return B_BAD_ADDRESS;
7919d771afbSAxel Dörfler 
792910ffb32SAxel Dörfler 			InterfaceAddress* address = NULL;
793910ffb32SAxel Dörfler 			if (aliasRequest.ifra_index < 0) {
794910ffb32SAxel Dörfler 				if (!domain->address_module->is_empty_address(
795910ffb32SAxel Dörfler 						(const sockaddr*)&aliasRequest.ifra_addr, false)) {
796910ffb32SAxel Dörfler 					// Find first address that matches the local address
797910ffb32SAxel Dörfler 					address = AddressForLocal(domain,
798910ffb32SAxel Dörfler 						(const sockaddr*)&aliasRequest.ifra_addr);
799910ffb32SAxel Dörfler 				}
800910ffb32SAxel Dörfler 				if (address == NULL) {
801910ffb32SAxel Dörfler 					// Find first address for family
802910ffb32SAxel Dörfler 					address = FirstForFamily(domain->family);
803910ffb32SAxel Dörfler 				}
804a271028eSAxel Dörfler 				if (address == NULL) {
805a271028eSAxel Dörfler 					// Create new on the fly
806a271028eSAxel Dörfler 					address = new(std::nothrow) InterfaceAddress(this, domain);
807a271028eSAxel Dörfler 					if (address == NULL)
808a271028eSAxel Dörfler 						return B_NO_MEMORY;
809a271028eSAxel Dörfler 
810a271028eSAxel Dörfler 					status_t status = AddAddress(address);
811095f97a6SAxel Dörfler 					if (status != B_OK) {
812095f97a6SAxel Dörfler 						delete address;
813a271028eSAxel Dörfler 						return status;
814095f97a6SAxel Dörfler 					}
815a271028eSAxel Dörfler 
816a271028eSAxel Dörfler 					// Note, even if setting the address failed, the empty
817a271028eSAxel Dörfler 					// address added here will still be added to the interface.
8188dcde8b1SAxel Dörfler 					address->AcquireReference();
819a271028eSAxel Dörfler 				}
820910ffb32SAxel Dörfler 			} else
821910ffb32SAxel Dörfler 				address = AddressAt(aliasRequest.ifra_index);
822910ffb32SAxel Dörfler 
8239d771afbSAxel Dörfler 			if (address == NULL)
8249d771afbSAxel Dörfler 				return B_BAD_VALUE;
8259d771afbSAxel Dörfler 
8269d771afbSAxel Dörfler 			status_t status = B_OK;
8279d771afbSAxel Dörfler 
8289d771afbSAxel Dörfler 			if (!domain->address_module->equal_addresses(
8299d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_addr, address->local)) {
8309d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address, SIOCSIFADDR,
8319d771afbSAxel Dörfler 					address->local, (sockaddr*)&aliasRequest.ifra_addr);
8329d771afbSAxel Dörfler 			}
8339d771afbSAxel Dörfler 
8349d771afbSAxel Dörfler 			if (status == B_OK && !domain->address_module->equal_addresses(
835910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_mask, address->mask)
836910ffb32SAxel Dörfler 				&& !domain->address_module->is_empty_address(
837910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_mask, false)) {
8389d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address, SIOCSIFNETMASK,
8399d771afbSAxel Dörfler 					address->mask, (sockaddr*)&aliasRequest.ifra_mask);
8409d771afbSAxel Dörfler 			}
8419d771afbSAxel Dörfler 
8429d771afbSAxel Dörfler 			if (status == B_OK && !domain->address_module->equal_addresses(
8439d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination,
844910ffb32SAxel Dörfler 					address->destination)
845910ffb32SAxel Dörfler 				&& !domain->address_module->is_empty_address(
846910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination, false)) {
8479d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address,
8489d771afbSAxel Dörfler 					(domain->address_module->flags
8499d771afbSAxel Dörfler 						& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0
8509d771afbSAxel Dörfler 							? SIOCSIFBRDADDR : SIOCSIFDSTADDR,
8519d771afbSAxel Dörfler 					address->destination,
8529d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination);
8539d771afbSAxel Dörfler 			}
8549d771afbSAxel Dörfler 
8559d771afbSAxel Dörfler 			address->ReleaseReference();
8569d771afbSAxel Dörfler 			return status;
8579d771afbSAxel Dörfler 		}
8589d771afbSAxel Dörfler 
85961729d93SAxel Dörfler 		case SIOCSIFADDR:
86061729d93SAxel Dörfler 		case SIOCSIFNETMASK:
86161729d93SAxel Dörfler 		case SIOCSIFBRDADDR:
86261729d93SAxel Dörfler 		case SIOCSIFDSTADDR:
86361729d93SAxel Dörfler 		case SIOCDIFADDR:
86461729d93SAxel Dörfler 		{
865e8802e49SAxel Dörfler 			if (length != sizeof(ifreq))
866e8802e49SAxel Dörfler 				return B_BAD_VALUE;
867e8802e49SAxel Dörfler 
86861729d93SAxel Dörfler 			RecursiveLocker locker(fLock);
86961729d93SAxel Dörfler 
87061729d93SAxel Dörfler 			InterfaceAddress* address = NULL;
87161729d93SAxel Dörfler 			sockaddr_storage newAddress;
87261729d93SAxel Dörfler 
87361729d93SAxel Dörfler 			size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr));
87461729d93SAxel Dörfler 			if (size > sizeof(sockaddr_storage))
87561729d93SAxel Dörfler 				size = sizeof(sockaddr_storage);
87661729d93SAxel Dörfler 
87761729d93SAxel Dörfler 			if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK)
87861729d93SAxel Dörfler 				return B_BAD_ADDRESS;
87961729d93SAxel Dörfler 
88061729d93SAxel Dörfler 			if (option == SIOCDIFADDR) {
88161729d93SAxel Dörfler 				// Find referring address - we can't use the hash, as another
88261729d93SAxel Dörfler 				// interface might use the same address.
88361729d93SAxel Dörfler 				AddressList::Iterator iterator = fAddresses.GetIterator();
88461729d93SAxel Dörfler 				while ((address = iterator.Next()) != NULL) {
88561729d93SAxel Dörfler 					if (address->domain == domain
88661729d93SAxel Dörfler 						&& domain->address_module->equal_addresses(
88761729d93SAxel Dörfler 							address->local, (sockaddr*)&newAddress))
88861729d93SAxel Dörfler 						break;
88961729d93SAxel Dörfler 				}
89061729d93SAxel Dörfler 
89161729d93SAxel Dörfler 				if (address == NULL)
89261729d93SAxel Dörfler 					return B_BAD_VALUE;
89378abd727SAxel Dörfler 			} else {
89478abd727SAxel Dörfler 				// Just use the first address for this family
89578abd727SAxel Dörfler 				address = _FirstForFamily(domain->family);
89678abd727SAxel Dörfler 				if (address == NULL) {
89778abd727SAxel Dörfler 					// Create new on the fly
89878abd727SAxel Dörfler 					address = new(std::nothrow) InterfaceAddress(this, domain);
89978abd727SAxel Dörfler 					if (address == NULL)
90078abd727SAxel Dörfler 						return B_NO_MEMORY;
90178abd727SAxel Dörfler 
90278abd727SAxel Dörfler 					status_t status = AddAddress(address);
903095f97a6SAxel Dörfler 					if (status != B_OK) {
904095f97a6SAxel Dörfler 						delete address;
90578abd727SAxel Dörfler 						return status;
906095f97a6SAxel Dörfler 					}
90778abd727SAxel Dörfler 
90878abd727SAxel Dörfler 					// Note, even if setting the address failed, the empty
90978abd727SAxel Dörfler 					// address added here will still be added to the interface.
91078abd727SAxel Dörfler 				}
91178abd727SAxel Dörfler 			}
91261729d93SAxel Dörfler 
9139d771afbSAxel Dörfler 			return _ChangeAddress(locker, address, option,
9149d771afbSAxel Dörfler 				*address->AddressFor(option),
91561729d93SAxel Dörfler 				option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL);
91661729d93SAxel Dörfler 		}
91761729d93SAxel Dörfler 
91861729d93SAxel Dörfler 		default:
91961729d93SAxel Dörfler 			// pass the request into the datalink protocol stack
92061729d93SAxel Dörfler 			domain_datalink* datalink = DomainDatalink(domain->family);
92161729d93SAxel Dörfler 			if (datalink->first_info != NULL) {
92261729d93SAxel Dörfler 				return datalink->first_info->control(
92361729d93SAxel Dörfler 					datalink->first_protocol, option, userRequest, length);
92461729d93SAxel Dörfler 			}
92561729d93SAxel Dörfler 			break;
92661729d93SAxel Dörfler 	}
92761729d93SAxel Dörfler 
92861729d93SAxel Dörfler 	return B_BAD_VALUE;
92961729d93SAxel Dörfler }
93061729d93SAxel Dörfler 
93161729d93SAxel Dörfler 
9322b1c0755SAxel Dörfler void
9332b1c0755SAxel Dörfler Interface::SetDown()
9342b1c0755SAxel Dörfler {
9352b1c0755SAxel Dörfler 	if ((flags & IFF_UP) == 0)
9362b1c0755SAxel Dörfler 		return;
9372b1c0755SAxel Dörfler 
938*7ed2a443SStefano Ceccherini 	RecursiveLocker interfacesLocker(sLock);
939ff8c8dfcSStefano Ceccherini 
940ff8c8dfcSStefano Ceccherini 	if (IsBusy())
941ff8c8dfcSStefano Ceccherini 		return;
942ff8c8dfcSStefano Ceccherini 
943ff8c8dfcSStefano Ceccherini 	SetBusy(true);
944*7ed2a443SStefano Ceccherini 	interfacesLocker.Unlock();
9452b1c0755SAxel Dörfler 
9462b1c0755SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
9472b1c0755SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
9482b1c0755SAxel Dörfler 		datalink->first_info->interface_down(datalink->first_protocol);
9492b1c0755SAxel Dörfler 	}
9502b1c0755SAxel Dörfler 
9512b1c0755SAxel Dörfler 	flags &= ~IFF_UP;
952ff8c8dfcSStefano Ceccherini 
953ff8c8dfcSStefano Ceccherini 	SetBusy(false);
9542b1c0755SAxel Dörfler }
9552b1c0755SAxel Dörfler 
9562b1c0755SAxel Dörfler 
9572b1c0755SAxel Dörfler /*!	Called when a device lost its IFF_UP status. We will invalidate all
9582b1c0755SAxel Dörfler 	interface routes here.
9592b1c0755SAxel Dörfler */
9602b1c0755SAxel Dörfler void
9612b1c0755SAxel Dörfler Interface::WentDown()
9622b1c0755SAxel Dörfler {
963ed18d7cfSAxel Dörfler 	TRACE("Interface %p: went down\n", this);
964ed18d7cfSAxel Dörfler 
9652b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
9662b1c0755SAxel Dörfler 
9672b1c0755SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
9682b1c0755SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
9692b1c0755SAxel Dörfler 		if (address->domain != NULL)
9702b1c0755SAxel Dörfler 			invalidate_routes(address->domain, this);
9712b1c0755SAxel Dörfler 	}
9722b1c0755SAxel Dörfler }
9732b1c0755SAxel Dörfler 
9742b1c0755SAxel Dörfler 
97561729d93SAxel Dörfler status_t
97661729d93SAxel Dörfler Interface::CreateDomainDatalinkIfNeeded(net_domain* domain)
97761729d93SAxel Dörfler {
97861729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
97961729d93SAxel Dörfler 
98061729d93SAxel Dörfler 	if (fDatalinkTable.Lookup(domain->family) != NULL)
98161729d93SAxel Dörfler 		return B_OK;
98261729d93SAxel Dörfler 
98361729d93SAxel Dörfler 	TRACE("Interface %p: create domain datalink for domain %p\n", this, domain);
98461729d93SAxel Dörfler 
98561729d93SAxel Dörfler 	domain_datalink* datalink = new(std::nothrow) domain_datalink;
98661729d93SAxel Dörfler 	if (datalink == NULL)
98761729d93SAxel Dörfler 		return B_NO_MEMORY;
98861729d93SAxel Dörfler 
989ed18d7cfSAxel Dörfler 	datalink->first_protocol = NULL;
990ed18d7cfSAxel Dörfler 	datalink->first_info = NULL;
99161729d93SAxel Dörfler 	datalink->domain = domain;
99261729d93SAxel Dörfler 
99361729d93SAxel Dörfler 	// setup direct route for bound devices
99461729d93SAxel Dörfler 	datalink->direct_route.destination = NULL;
99561729d93SAxel Dörfler 	datalink->direct_route.mask = NULL;
99661729d93SAxel Dörfler 	datalink->direct_route.gateway = NULL;
99761729d93SAxel Dörfler 	datalink->direct_route.flags = 0;
99861729d93SAxel Dörfler 	datalink->direct_route.mtu = 0;
99961729d93SAxel Dörfler 	datalink->direct_route.interface_address = &datalink->direct_address;
100061729d93SAxel Dörfler 	datalink->direct_route.ref_count = 1;
100161729d93SAxel Dörfler 		// make sure this doesn't get deleted accidently
100261729d93SAxel Dörfler 
100361729d93SAxel Dörfler 	// provide its link back to the interface
100461729d93SAxel Dörfler 	datalink->direct_address.local = NULL;
100561729d93SAxel Dörfler 	datalink->direct_address.destination = NULL;
100661729d93SAxel Dörfler 	datalink->direct_address.mask = NULL;
100761729d93SAxel Dörfler 	datalink->direct_address.domain = domain;
100861729d93SAxel Dörfler 	datalink->direct_address.interface = this;
10092b1c0755SAxel Dörfler 	datalink->direct_address.flags = IFAF_DIRECT_ADDRESS;
101061729d93SAxel Dörfler 
101161729d93SAxel Dörfler 	fDatalinkTable.Insert(datalink);
101261729d93SAxel Dörfler 
101361729d93SAxel Dörfler 	status_t status = get_domain_datalink_protocols(this, domain);
101461729d93SAxel Dörfler 	if (status == B_OK)
101561729d93SAxel Dörfler 		return B_OK;
101661729d93SAxel Dörfler 
101761729d93SAxel Dörfler 	fDatalinkTable.Remove(datalink);
101861729d93SAxel Dörfler 	delete datalink;
101961729d93SAxel Dörfler 
102061729d93SAxel Dörfler 	return status;
102161729d93SAxel Dörfler }
102261729d93SAxel Dörfler 
102361729d93SAxel Dörfler 
102461729d93SAxel Dörfler domain_datalink*
102561729d93SAxel Dörfler Interface::DomainDatalink(uint8 family)
102661729d93SAxel Dörfler {
102761729d93SAxel Dörfler 	// Note: domain datalinks cannot be removed while the interface is alive,
102861729d93SAxel Dörfler 	// since this would require us either to hold the lock while calling this
102961729d93SAxel Dörfler 	// function, or introduce reference counting for the domain_datalink
103061729d93SAxel Dörfler 	// structure.
103161729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
103261729d93SAxel Dörfler 	return fDatalinkTable.Lookup(family);
103361729d93SAxel Dörfler }
103461729d93SAxel Dörfler 
103561729d93SAxel Dörfler 
103661729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
103761729d93SAxel Dörfler 
103861729d93SAxel Dörfler 
103961729d93SAxel Dörfler void
104061729d93SAxel Dörfler Interface::Dump() const
104161729d93SAxel Dörfler {
104261729d93SAxel Dörfler 	kprintf("name:                %s\n", name);
104361729d93SAxel Dörfler 	kprintf("device:              %p\n", device);
104461729d93SAxel Dörfler 	kprintf("device_interface:    %p\n", fDeviceInterface);
104561729d93SAxel Dörfler 	kprintf("index:               %" B_PRIu32 "\n", index);
104661729d93SAxel Dörfler 	kprintf("flags:               %#" B_PRIx32 "\n", flags);
104761729d93SAxel Dörfler 	kprintf("type:                %u\n", type);
104861729d93SAxel Dörfler 	kprintf("mtu:                 %" B_PRIu32 "\n", mtu);
104961729d93SAxel Dörfler 	kprintf("metric:              %" B_PRIu32 "\n", metric);
1050ed18d7cfSAxel Dörfler 	kprintf("ref count:           %" B_PRId32 "\n", CountReferences());
105161729d93SAxel Dörfler 
105261729d93SAxel Dörfler 	kprintf("datalink protocols:\n");
105361729d93SAxel Dörfler 
105461729d93SAxel Dörfler 	DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator();
105561729d93SAxel Dörfler 	size_t i = 0;
105661729d93SAxel Dörfler 	while (domain_datalink* datalink = datalinkIterator.Next()) {
105761729d93SAxel Dörfler 		kprintf("%2zu. domain:          %p\n", ++i, datalink->domain);
105861729d93SAxel Dörfler 		kprintf("    first_protocol:  %p\n", datalink->first_protocol);
105961729d93SAxel Dörfler 		kprintf("    first_info:      %p\n", datalink->first_info);
106061729d93SAxel Dörfler 		kprintf("    direct_route:    %p\n", &datalink->direct_route);
106161729d93SAxel Dörfler 	}
106261729d93SAxel Dörfler 
106361729d93SAxel Dörfler 	kprintf("addresses:\n");
106461729d93SAxel Dörfler 
106561729d93SAxel Dörfler 	AddressList::ConstIterator iterator = fAddresses.GetIterator();
106661729d93SAxel Dörfler 	i = 0;
106761729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
106861729d93SAxel Dörfler 		address->Dump(++i, true);
106961729d93SAxel Dörfler 	}
107061729d93SAxel Dörfler }
107161729d93SAxel Dörfler 
107261729d93SAxel Dörfler 
107361729d93SAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
107461729d93SAxel Dörfler 
107561729d93SAxel Dörfler 
107661729d93SAxel Dörfler status_t
107761729d93SAxel Dörfler Interface::_SetUp()
107861729d93SAxel Dörfler {
107961729d93SAxel Dörfler 	status_t status = up_device_interface(fDeviceInterface);
108061729d93SAxel Dörfler 	if (status != B_OK)
108161729d93SAxel Dörfler 		return status;
108261729d93SAxel Dörfler 
1083ff8c8dfcSStefano Ceccherini 	RecursiveLocker interfacesLocker(sLock);
1084ff8c8dfcSStefano Ceccherini 	SetBusy(true);
1085ff8c8dfcSStefano Ceccherini 	interfacesLocker.Unlock();
1086ff8c8dfcSStefano Ceccherini 
10872b1c0755SAxel Dörfler 	// Propagate flag to all datalink protocols
108861729d93SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
108961729d93SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
109061729d93SAxel Dörfler 		status = datalink->first_info->interface_up(datalink->first_protocol);
109161729d93SAxel Dörfler 		if (status != B_OK) {
109261729d93SAxel Dörfler 			// Revert "up" status
109361729d93SAxel Dörfler 			DatalinkTable::Iterator secondIterator
109461729d93SAxel Dörfler 				= fDatalinkTable.GetIterator();
109561729d93SAxel Dörfler 			while (secondIterator.HasNext()) {
109661729d93SAxel Dörfler 				domain_datalink* secondDatalink = secondIterator.Next();
109761729d93SAxel Dörfler 				if (secondDatalink == NULL || secondDatalink == datalink)
1098c22d69bfSAxel Dörfler 					break;
1099c22d69bfSAxel Dörfler 
110061729d93SAxel Dörfler 				secondDatalink->first_info->interface_down(
110161729d93SAxel Dörfler 					secondDatalink->first_protocol);
110261729d93SAxel Dörfler 			}
110361729d93SAxel Dörfler 
110461729d93SAxel Dörfler 			down_device_interface(fDeviceInterface);
1105ff8c8dfcSStefano Ceccherini 			SetBusy(false);
110661729d93SAxel Dörfler 			return status;
110761729d93SAxel Dörfler 		}
110861729d93SAxel Dörfler 	}
110961729d93SAxel Dörfler 
11102b1c0755SAxel Dörfler 	// Add default routes for the existing addresses
11112b1c0755SAxel Dörfler 
11122b1c0755SAxel Dörfler 	AddressList::Iterator addressIterator = fAddresses.GetIterator();
11132b1c0755SAxel Dörfler 	while (InterfaceAddress* address = addressIterator.Next()) {
11142b1c0755SAxel Dörfler 		address->AddDefaultRoutes(SIOCSIFADDR);
11152b1c0755SAxel Dörfler 	}
11162b1c0755SAxel Dörfler 
111761729d93SAxel Dörfler 	flags |= IFF_UP;
1118ff8c8dfcSStefano Ceccherini 	SetBusy(false);
1119ff8c8dfcSStefano Ceccherini 
112061729d93SAxel Dörfler 	return B_OK;
112161729d93SAxel Dörfler }
112261729d93SAxel Dörfler 
112361729d93SAxel Dörfler 
112461729d93SAxel Dörfler InterfaceAddress*
112561729d93SAxel Dörfler Interface::_FirstForFamily(int family)
112661729d93SAxel Dörfler {
112761729d93SAxel Dörfler 	ASSERT_LOCKED_RECURSIVE(&fLock);
112861729d93SAxel Dörfler 
112961729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
113061729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
113161729d93SAxel Dörfler 		if (address->domain != NULL && address->domain->family == family)
113261729d93SAxel Dörfler 			return address;
113361729d93SAxel Dörfler 	}
113461729d93SAxel Dörfler 
113561729d93SAxel Dörfler 	return NULL;
113661729d93SAxel Dörfler }
113761729d93SAxel Dörfler 
113861729d93SAxel Dörfler 
11399d771afbSAxel Dörfler status_t
11409d771afbSAxel Dörfler Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address,
1141b0cf274aSAxel Dörfler 	int32 option, const sockaddr* originalAddress,
1142b0cf274aSAxel Dörfler 	const sockaddr* requestedAddress)
11439d771afbSAxel Dörfler {
1144b0cf274aSAxel Dörfler 	// Copy old address
11459d771afbSAxel Dörfler 	sockaddr_storage oldAddress;
11469d771afbSAxel Dörfler 	if (address->domain->address_module->set_to((sockaddr*)&oldAddress,
11479d771afbSAxel Dörfler 			originalAddress) != B_OK)
11489d771afbSAxel Dörfler 		oldAddress.ss_family = AF_UNSPEC;
11499d771afbSAxel Dörfler 
1150b0cf274aSAxel Dörfler 	// Copy new address (this also makes sure that sockaddr::sa_len is set
1151b0cf274aSAxel Dörfler 	// correctly)
1152b0cf274aSAxel Dörfler 	sockaddr_storage newAddress;
1153b0cf274aSAxel Dörfler 	if (address->domain->address_module->set_to((sockaddr*)&newAddress,
1154b0cf274aSAxel Dörfler 			requestedAddress) != B_OK)
1155b0cf274aSAxel Dörfler 		newAddress.ss_family = AF_UNSPEC;
1156b0cf274aSAxel Dörfler 
11576b1e1488SAxel Dörfler 	// Test if anything changed for real
1158b0cf274aSAxel Dörfler 	if (address->domain->address_module->equal_addresses(
1159b0cf274aSAxel Dörfler 			(sockaddr*)&oldAddress, (sockaddr*)&newAddress)) {
11606b1e1488SAxel Dörfler 		// Nothing to do
1161b0cf274aSAxel Dörfler 		TRACE("  option %" B_PRId32 " addresses are equal!\n", option);
11626b1e1488SAxel Dörfler 		return B_OK;
11636b1e1488SAxel Dörfler 	}
11646b1e1488SAxel Dörfler 
11659d771afbSAxel Dörfler 	// TODO: mark this address busy or call while holding the lock!
11669d771afbSAxel Dörfler 	address->AcquireReference();
11679d771afbSAxel Dörfler 	locker.Unlock();
11689d771afbSAxel Dörfler 
11699d771afbSAxel Dörfler 	domain_datalink* datalink = DomainDatalink(address->domain);
11709d771afbSAxel Dörfler 	status_t status = datalink->first_protocol->module->change_address(
11719d771afbSAxel Dörfler 		datalink->first_protocol, address, option,
11729d771afbSAxel Dörfler 		oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL,
1173b0cf274aSAxel Dörfler 		newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL);
11749d771afbSAxel Dörfler 
11759d771afbSAxel Dörfler 	locker.Lock();
11769d771afbSAxel Dörfler 	address->ReleaseReference();
11779d771afbSAxel Dörfler 	return status;
11789d771afbSAxel Dörfler }
11799d771afbSAxel Dörfler 
11809d771afbSAxel Dörfler 
118161729d93SAxel Dörfler // #pragma mark -
118261729d93SAxel Dörfler 
118361729d93SAxel Dörfler 
118461729d93SAxel Dörfler /*!	Searches for a specific interface by name.
118561729d93SAxel Dörfler 	You need to have the interface list's lock hold when calling this function.
118661729d93SAxel Dörfler */
118761729d93SAxel Dörfler static struct Interface*
118861729d93SAxel Dörfler find_interface(const char* name)
118961729d93SAxel Dörfler {
11908a6337d0SStefano Ceccherini 	ASSERT_LOCKED_RECURSIVE(&sLock);
119161729d93SAxel Dörfler 
119261729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
119361729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1194c22d69bfSAxel Dörfler 		if (!strcmp(interface->name, name))
1195c22d69bfSAxel Dörfler 			return interface;
1196c22d69bfSAxel Dörfler 	}
1197c22d69bfSAxel Dörfler 
1198c22d69bfSAxel Dörfler 	return NULL;
1199c22d69bfSAxel Dörfler }
1200c22d69bfSAxel Dörfler 
1201c22d69bfSAxel Dörfler 
120261729d93SAxel Dörfler /*!	Searches for a specific interface by index.
120361729d93SAxel Dörfler 	You need to have the interface list's lock hold when calling this function.
1204c22d69bfSAxel Dörfler */
120561729d93SAxel Dörfler static struct Interface*
120661729d93SAxel Dörfler find_interface(uint32 index)
1207c22d69bfSAxel Dörfler {
120861729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
120961729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1210c22d69bfSAxel Dörfler 		if (interface->index == index)
1211c22d69bfSAxel Dörfler 			return interface;
1212c22d69bfSAxel Dörfler 	}
1213c22d69bfSAxel Dörfler 
1214c22d69bfSAxel Dörfler 	return NULL;
1215c22d69bfSAxel Dörfler }
1216c22d69bfSAxel Dörfler 
1217c22d69bfSAxel Dörfler 
121861729d93SAxel Dörfler // #pragma mark -
121961729d93SAxel Dörfler 
122061729d93SAxel Dörfler 
122161729d93SAxel Dörfler status_t
122261729d93SAxel Dörfler add_interface(const char* name, net_domain_private* domain,
122361729d93SAxel Dörfler 	const ifaliasreq& request, net_device_interface* deviceInterface)
122461729d93SAxel Dörfler {
12258a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
122661729d93SAxel Dörfler 
122761729d93SAxel Dörfler 	if (find_interface(name) != NULL)
122861729d93SAxel Dörfler 		return B_NAME_IN_USE;
122961729d93SAxel Dörfler 
123061729d93SAxel Dörfler 	Interface* interface
123161729d93SAxel Dörfler 		= new(std::nothrow) Interface(name, deviceInterface);
1232c22d69bfSAxel Dörfler 	if (interface == NULL)
1233c22d69bfSAxel Dörfler 		return B_NO_MEMORY;
1234c22d69bfSAxel Dörfler 
123561729d93SAxel Dörfler 	sInterfaces.Add(interface);
123661729d93SAxel Dörfler 	interface->AcquireReference();
123761729d93SAxel Dörfler 		// We need another reference to be able to use the interface without
123861729d93SAxel Dörfler 		// holding sLock.
1239c22d69bfSAxel Dörfler 
124061729d93SAxel Dörfler 	locker.Unlock();
1241c22d69bfSAxel Dörfler 
12424ae58630SAxel Dörfler 	status_t status = add_interface_address(interface, domain, request);
12434ae58630SAxel Dörfler 	if (status == B_OK)
124461729d93SAxel Dörfler 		notify_interface_added(interface);
12454ae58630SAxel Dörfler 	else {
12464ae58630SAxel Dörfler 		locker.Lock();
12474ae58630SAxel Dörfler 		sInterfaces.Remove(interface);
12484ae58630SAxel Dörfler 		locker.Unlock();
12494ae58630SAxel Dörfler 		interface->ReleaseReference();
12504ae58630SAxel Dörfler 	}
1251c22d69bfSAxel Dörfler 
125261729d93SAxel Dörfler 	interface->ReleaseReference();
125327e0dea9SAxel Dörfler 
12544ae58630SAxel Dörfler 	return status;
1255c22d69bfSAxel Dörfler }
1256c22d69bfSAxel Dörfler 
1257c22d69bfSAxel Dörfler 
125861729d93SAxel Dörfler /*!	Removes the interface from the list, and puts the stack's reference to it.
125961729d93SAxel Dörfler */
12607aa2819cSAxel Dörfler void
126161729d93SAxel Dörfler remove_interface(Interface* interface)
1262c64feccaSHugo Santos {
12632b1c0755SAxel Dörfler 	interface->SetDown();
12642b1c0755SAxel Dörfler 	interface->RemoveAddresses();
1265c64feccaSHugo Santos 
12668a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
12672b1c0755SAxel Dörfler 	sInterfaces.Remove(interface);
12682b1c0755SAxel Dörfler 	locker.Unlock();
1269f6d219a1SAxel Dörfler 
127061729d93SAxel Dörfler 	notify_interface_removed(interface);
1271c22d69bfSAxel Dörfler 
12722b1c0755SAxel Dörfler 	interface->ReleaseReference();
12737aa2819cSAxel Dörfler }
12747aa2819cSAxel Dörfler 
12757aa2819cSAxel Dörfler 
12767aa2819cSAxel Dörfler /*!	This is called whenever a device interface is being removed. We will get
12777aa2819cSAxel Dörfler 	the corresponding Interface, and remove it.
12787aa2819cSAxel Dörfler */
12797aa2819cSAxel Dörfler void
12807aa2819cSAxel Dörfler interface_removed_device_interface(net_device_interface* deviceInterface)
12817aa2819cSAxel Dörfler {
12828a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
12837aa2819cSAxel Dörfler 
12847aa2819cSAxel Dörfler 	Interface* interface = find_interface(deviceInterface->device->name);
12857aa2819cSAxel Dörfler 	if (interface != NULL)
12867aa2819cSAxel Dörfler 		remove_interface(interface);
1287c22d69bfSAxel Dörfler }
1288c22d69bfSAxel Dörfler 
1289c22d69bfSAxel Dörfler 
129061729d93SAxel Dörfler status_t
129161729d93SAxel Dörfler add_interface_address(Interface* interface, net_domain_private* domain,
129261729d93SAxel Dörfler 	const ifaliasreq& request)
1293c22d69bfSAxel Dörfler {
129461729d93SAxel Dörfler 	// Make sure the family of the provided addresses is valid
129561729d93SAxel Dörfler 	if ((request.ifra_addr.ss_family != domain->family
129661729d93SAxel Dörfler 			&& request.ifra_addr.ss_family != AF_UNSPEC)
129761729d93SAxel Dörfler 		|| (request.ifra_mask.ss_family != domain->family
129861729d93SAxel Dörfler 			&& request.ifra_mask.ss_family != AF_UNSPEC)
129961729d93SAxel Dörfler 		|| (request.ifra_broadaddr.ss_family != domain->family
130061729d93SAxel Dörfler 			&& request.ifra_broadaddr.ss_family != AF_UNSPEC))
130161729d93SAxel Dörfler 		return B_BAD_VALUE;
1302c22d69bfSAxel Dörfler 
130361729d93SAxel Dörfler 	RecursiveLocker locker(interface->Lock());
130461729d93SAxel Dörfler 
130561729d93SAxel Dörfler 	InterfaceAddress* address
130661729d93SAxel Dörfler 		= new(std::nothrow) InterfaceAddress(interface, domain);
130761729d93SAxel Dörfler 	if (address == NULL)
130861729d93SAxel Dörfler 		return B_NO_MEMORY;
130961729d93SAxel Dörfler 
131061729d93SAxel Dörfler 	status_t status = address->SetTo(request);
131161729d93SAxel Dörfler 	if (status == B_OK)
131261729d93SAxel Dörfler 		status = interface->CreateDomainDatalinkIfNeeded(domain);
131361729d93SAxel Dörfler 	if (status == B_OK)
131461729d93SAxel Dörfler 		status = interface->AddAddress(address);
131561729d93SAxel Dörfler 
131661729d93SAxel Dörfler 	if (status == B_OK && address->local != NULL) {
131761729d93SAxel Dörfler 		// update the datalink protocols
131861729d93SAxel Dörfler 		domain_datalink* datalink = interface->DomainDatalink(domain->family);
131961729d93SAxel Dörfler 
132061729d93SAxel Dörfler 		status = datalink->first_protocol->module->change_address(
132161729d93SAxel Dörfler 			datalink->first_protocol, address, SIOCAIFADDR, NULL,
132261729d93SAxel Dörfler 			address->local);
132361729d93SAxel Dörfler 		if (status != B_OK)
132461729d93SAxel Dörfler 			interface->RemoveAddress(address);
132561729d93SAxel Dörfler 	}
132661729d93SAxel Dörfler 	if (status == B_OK)
132761729d93SAxel Dörfler 		notify_interface_changed(interface);
132861729d93SAxel Dörfler 	else
132961729d93SAxel Dörfler 		delete address;
133061729d93SAxel Dörfler 
133161729d93SAxel Dörfler 	return status;
133261729d93SAxel Dörfler }
133361729d93SAxel Dörfler 
133461729d93SAxel Dörfler 
133561729d93SAxel Dörfler status_t
133661729d93SAxel Dörfler update_interface_address(InterfaceAddress* interfaceAddress, int32 option,
133761729d93SAxel Dörfler 	const sockaddr* oldAddress, const sockaddr* newAddress)
133861729d93SAxel Dörfler {
1339b0cf274aSAxel Dörfler 	TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress "
1340b0cf274aSAxel Dörfler 		"%s)\n", __FUNCTION__, interfaceAddress, option,
1341b0cf274aSAxel Dörfler 		AddressString(interfaceAddress->domain, oldAddress).Data(),
1342b0cf274aSAxel Dörfler 		AddressString(interfaceAddress->domain, newAddress).Data());
1343b0cf274aSAxel Dörfler 
134461729d93SAxel Dörfler 	MutexLocker locker(sHashLock);
134561729d93SAxel Dörfler 
134661729d93SAxel Dörfler 	// set logical interface address
134761729d93SAxel Dörfler 	sockaddr** _address = interfaceAddress->AddressFor(option);
134861729d93SAxel Dörfler 	if (_address == NULL)
134961729d93SAxel Dörfler 		return B_BAD_VALUE;
135061729d93SAxel Dörfler 
13512b1c0755SAxel Dörfler 	Interface* interface = (Interface*)interfaceAddress->interface;
13522b1c0755SAxel Dörfler 
13532b1c0755SAxel Dörfler 	interfaceAddress->RemoveDefaultRoutes(option);
13542b1c0755SAxel Dörfler 
13552b1c0755SAxel Dörfler 	if (option == SIOCDIFADDR) {
13562b1c0755SAxel Dörfler 		// Remove address, and release its reference (causing our caller to
13572b1c0755SAxel Dörfler 		// delete it)
13582b1c0755SAxel Dörfler 		locker.Unlock();
13592b1c0755SAxel Dörfler 
13602b1c0755SAxel Dörfler 		invalidate_routes(interfaceAddress);
13612b1c0755SAxel Dörfler 
13622b1c0755SAxel Dörfler 		interface->RemoveAddress(interfaceAddress);
13632b1c0755SAxel Dörfler 		interfaceAddress->ReleaseReference();
13642b1c0755SAxel Dörfler 		return B_OK;
13652b1c0755SAxel Dörfler 	}
13662b1c0755SAxel Dörfler 
13674ae58630SAxel Dörfler 	if (interfaceAddress->LocalIsDefined())
136861729d93SAxel Dörfler 		sAddressTable.Remove(interfaceAddress);
136961729d93SAxel Dörfler 
137061729d93SAxel Dörfler 	// Copy new address over
137161729d93SAxel Dörfler 	status_t status = InterfaceAddress::Set(_address, newAddress);
137261729d93SAxel Dörfler 	if (status == B_OK) {
137361729d93SAxel Dörfler 		sockaddr* address = *_address;
137461729d93SAxel Dörfler 
13755ebd9548SAxel Dörfler 		if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) {
137661729d93SAxel Dörfler 			// Reset netmask and broadcast addresses to defaults
137761729d93SAxel Dörfler 			net_domain* domain = interfaceAddress->domain;
13785ebd9548SAxel Dörfler 			sockaddr* defaultNetmask = NULL;
13795ebd9548SAxel Dörfler 			const sockaddr* netmask = NULL;
138061729d93SAxel Dörfler 			if (option == SIOCSIFADDR) {
13815ebd9548SAxel Dörfler 				defaultNetmask = InterfaceAddress::Prepare(
138261729d93SAxel Dörfler 					&interfaceAddress->mask, address->sa_len);
13835ebd9548SAxel Dörfler 			} else
13845ebd9548SAxel Dörfler 				netmask = newAddress;
138561729d93SAxel Dörfler 
138661729d93SAxel Dörfler 			// Reset the broadcast address if the address family has
138761729d93SAxel Dörfler 			// such
13885ebd9548SAxel Dörfler 			sockaddr* defaultBroadcast = NULL;
138961729d93SAxel Dörfler 			if ((domain->address_module->flags
139061729d93SAxel Dörfler 					& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) {
13915ebd9548SAxel Dörfler 				defaultBroadcast = InterfaceAddress::Prepare(
139261729d93SAxel Dörfler 					&interfaceAddress->destination, address->sa_len);
139361729d93SAxel Dörfler 			} else
139461729d93SAxel Dörfler 				InterfaceAddress::Set(&interfaceAddress->destination, NULL);
139561729d93SAxel Dörfler 
13965ebd9548SAxel Dörfler 			domain->address_module->set_to_defaults(defaultNetmask,
13975ebd9548SAxel Dörfler 				defaultBroadcast, interfaceAddress->local, netmask);
139861729d93SAxel Dörfler 		}
139961729d93SAxel Dörfler 
14002b1c0755SAxel Dörfler 		interfaceAddress->AddDefaultRoutes(option);
14012b1c0755SAxel Dörfler 		notify_interface_changed(interface);
140261729d93SAxel Dörfler 	}
140361729d93SAxel Dörfler 
14044ae58630SAxel Dörfler 	if (interfaceAddress->LocalIsDefined())
140561729d93SAxel Dörfler 		sAddressTable.Insert(interfaceAddress);
140661729d93SAxel Dörfler 	return status;
140761729d93SAxel Dörfler }
140861729d93SAxel Dörfler 
140961729d93SAxel Dörfler 
141061729d93SAxel Dörfler Interface*
141161729d93SAxel Dörfler get_interface(net_domain* domain, uint32 index)
141261729d93SAxel Dörfler {
14138a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
141461729d93SAxel Dörfler 
1415ec4fb0f4SAxel Dörfler 	Interface* interface;
141661729d93SAxel Dörfler 	if (index == 0)
1417ec4fb0f4SAxel Dörfler 		interface = sInterfaces.First();
1418ec4fb0f4SAxel Dörfler 	else
1419ec4fb0f4SAxel Dörfler 		interface = find_interface(index);
1420ff8c8dfcSStefano Ceccherini 	if (interface == NULL || interface->IsBusy())
142161729d93SAxel Dörfler 		return NULL;
1422c22d69bfSAxel Dörfler 
142361729d93SAxel Dörfler 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
142461729d93SAxel Dörfler 		return NULL;
142561729d93SAxel Dörfler 
142661729d93SAxel Dörfler 	interface->AcquireReference();
1427c22d69bfSAxel Dörfler 	return interface;
1428c22d69bfSAxel Dörfler }
1429c22d69bfSAxel Dörfler 
143061729d93SAxel Dörfler 
143161729d93SAxel Dörfler Interface*
143261729d93SAxel Dörfler get_interface(net_domain* domain, const char* name)
143361729d93SAxel Dörfler {
14348a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
143561729d93SAxel Dörfler 
143661729d93SAxel Dörfler 	Interface* interface = find_interface(name);
1437ff8c8dfcSStefano Ceccherini 	if (interface == NULL || interface->IsBusy())
143861729d93SAxel Dörfler 		return NULL;
143961729d93SAxel Dörfler 
144061729d93SAxel Dörfler 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
144161729d93SAxel Dörfler 		return NULL;
144261729d93SAxel Dörfler 
144361729d93SAxel Dörfler 	interface->AcquireReference();
144461729d93SAxel Dörfler 	return interface;
144561729d93SAxel Dörfler }
144661729d93SAxel Dörfler 
144761729d93SAxel Dörfler 
144861729d93SAxel Dörfler Interface*
144961729d93SAxel Dörfler get_interface_for_device(net_domain* domain, uint32 index)
145061729d93SAxel Dörfler {
14518a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
145261729d93SAxel Dörfler 
145361729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
145461729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
145561729d93SAxel Dörfler 		if (interface->device->index == index) {
1456ff8c8dfcSStefano Ceccherini 			if (interface->IsBusy())
1457ff8c8dfcSStefano Ceccherini 				return NULL;
145861729d93SAxel Dörfler 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
145961729d93SAxel Dörfler 				return NULL;
146061729d93SAxel Dörfler 
146161729d93SAxel Dörfler 			interface->AcquireReference();
146261729d93SAxel Dörfler 			return interface;
146361729d93SAxel Dörfler 		}
146461729d93SAxel Dörfler 	}
146561729d93SAxel Dörfler 
1466c22d69bfSAxel Dörfler 	return NULL;
1467c22d69bfSAxel Dörfler }
1468c22d69bfSAxel Dörfler 
1469c22d69bfSAxel Dörfler 
1470cd08b9f7SAxel Dörfler /*!	Returns a reference to an Interface that matches the given \a linkAddress.
1471cd08b9f7SAxel Dörfler 	The link address is checked against its hardware address, or its interface
1472cd08b9f7SAxel Dörfler 	name, or finally the interface index.
1473cd08b9f7SAxel Dörfler */
1474cd08b9f7SAxel Dörfler Interface*
1475cd08b9f7SAxel Dörfler get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress)
1476cd08b9f7SAxel Dörfler {
1477cd08b9f7SAxel Dörfler 	sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress;
1478cd08b9f7SAxel Dörfler 
14798a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
1480cd08b9f7SAxel Dörfler 
1481cd08b9f7SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1482cd08b9f7SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1483ff8c8dfcSStefano Ceccherini 		if (interface->IsBusy())
1484ff8c8dfcSStefano Ceccherini 			continue;
1485cd08b9f7SAxel Dörfler 		// Test if the hardware address matches, or if the given interface
1486cd08b9f7SAxel Dörfler 		// matches, or if at least the index matches.
1487cd08b9f7SAxel Dörfler 		if ((linkAddress.sdl_alen == interface->device->address.length
1488cd08b9f7SAxel Dörfler 				&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
1489cd08b9f7SAxel Dörfler 					linkAddress.sdl_alen) == 0)
1490cd08b9f7SAxel Dörfler 			|| (linkAddress.sdl_nlen > 0
1491cd08b9f7SAxel Dörfler 				&& !strcmp(interface->name, (const char*)linkAddress.sdl_data))
1492cd08b9f7SAxel Dörfler 			|| (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0
1493cd08b9f7SAxel Dörfler 				&& linkAddress.sdl_index == interface->index)) {
1494ff8c8dfcSStefano Ceccherini 			if (interface->IsBusy())
1495ff8c8dfcSStefano Ceccherini 				return NULL;
1496cd08b9f7SAxel Dörfler 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
1497cd08b9f7SAxel Dörfler 				return NULL;
1498cd08b9f7SAxel Dörfler 
1499cd08b9f7SAxel Dörfler 			interface->AcquireReference();
1500cd08b9f7SAxel Dörfler 			return interface;
1501cd08b9f7SAxel Dörfler 		}
1502cd08b9f7SAxel Dörfler 	}
1503cd08b9f7SAxel Dörfler 
1504cd08b9f7SAxel Dörfler 	return NULL;
1505cd08b9f7SAxel Dörfler }
1506cd08b9f7SAxel Dörfler 
1507cd08b9f7SAxel Dörfler 
150861729d93SAxel Dörfler InterfaceAddress*
150961729d93SAxel Dörfler get_interface_address(const sockaddr* local)
1510c22d69bfSAxel Dörfler {
151161729d93SAxel Dörfler 	if (local->sa_family == AF_UNSPEC)
151261729d93SAxel Dörfler 		return NULL;
1513c22d69bfSAxel Dörfler 
151461729d93SAxel Dörfler 	MutexLocker locker(sHashLock);
1515c22d69bfSAxel Dörfler 
151661729d93SAxel Dörfler 	InterfaceAddress* address = sAddressTable.Lookup(local);
151761729d93SAxel Dörfler 	if (address == NULL)
151861729d93SAxel Dörfler 		return NULL;
1519c22d69bfSAxel Dörfler 
152061729d93SAxel Dörfler 	address->AcquireReference();
152161729d93SAxel Dörfler 	return address;
152261729d93SAxel Dörfler }
152361729d93SAxel Dörfler 
152461729d93SAxel Dörfler 
152561729d93SAxel Dörfler InterfaceAddress*
152661729d93SAxel Dörfler get_interface_address_for_destination(net_domain* domain,
1527cd08b9f7SAxel Dörfler 	const sockaddr* destination)
152861729d93SAxel Dörfler {
15298a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
153061729d93SAxel Dörfler 
153161729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
153261729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1533ff8c8dfcSStefano Ceccherini 		if (interface->IsBusy())
1534ff8c8dfcSStefano Ceccherini 			continue;
1535ff8c8dfcSStefano Ceccherini 
153661729d93SAxel Dörfler 		InterfaceAddress* address
153761729d93SAxel Dörfler 			= interface->AddressForDestination(domain, destination);
153861729d93SAxel Dörfler 		if (address != NULL)
153961729d93SAxel Dörfler 			return address;
154061729d93SAxel Dörfler 	}
154161729d93SAxel Dörfler 
154261729d93SAxel Dörfler 	return NULL;
154361729d93SAxel Dörfler }
154461729d93SAxel Dörfler 
154561729d93SAxel Dörfler 
1546cd08b9f7SAxel Dörfler /*!	Returns a reference to an InterfaceAddress of the specified \a domain that
1547cd08b9f7SAxel Dörfler 	belongs to the interface identified via \a linkAddress. Only the hardware
1548cd08b9f7SAxel Dörfler 	address is matched.
1549cd08b9f7SAxel Dörfler 
1550cd08b9f7SAxel Dörfler 	If \a unconfiguredOnly is set, the interface address must not yet be
1551cd08b9f7SAxel Dörfler 	configured, or must currently be in the process of being configured.
1552cd08b9f7SAxel Dörfler */
155361729d93SAxel Dörfler InterfaceAddress*
1554cd08b9f7SAxel Dörfler get_interface_address_for_link(net_domain* domain, const sockaddr* address,
1555cd08b9f7SAxel Dörfler 	bool unconfiguredOnly)
155661729d93SAxel Dörfler {
1557cd08b9f7SAxel Dörfler 	sockaddr_dl& linkAddress = *(sockaddr_dl*)address;
155861729d93SAxel Dörfler 
15598a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
156061729d93SAxel Dörfler 
156161729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
156261729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1563ff8c8dfcSStefano Ceccherini 		if (interface->IsBusy())
1564ff8c8dfcSStefano Ceccherini 			continue;
1565cd08b9f7SAxel Dörfler 		// Test if the hardware address matches, or if the given interface
1566cd08b9f7SAxel Dörfler 		// matches, or if at least the index matches.
156761729d93SAxel Dörfler 		if (linkAddress.sdl_alen == interface->device->address.length
156861729d93SAxel Dörfler 			&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
156961729d93SAxel Dörfler 				linkAddress.sdl_alen) == 0) {
1570b0cf274aSAxel Dörfler 			TRACE("  %s matches\n", interface->name);
157161729d93SAxel Dörfler 			// link address matches
157261729d93SAxel Dörfler 			if (unconfiguredOnly)
157361729d93SAxel Dörfler 				return interface->FirstUnconfiguredForFamily(domain->family);
157461729d93SAxel Dörfler 
157561729d93SAxel Dörfler 			return interface->FirstForFamily(domain->family);
157661729d93SAxel Dörfler 		}
157761729d93SAxel Dörfler 	}
157861729d93SAxel Dörfler 
157961729d93SAxel Dörfler 	return NULL;
1580c22d69bfSAxel Dörfler }
1581c22d69bfSAxel Dörfler 
1582c22d69bfSAxel Dörfler 
1583c22d69bfSAxel Dörfler uint32
158461729d93SAxel Dörfler count_interfaces()
1585c22d69bfSAxel Dörfler {
15868a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
1587c22d69bfSAxel Dörfler 
158861729d93SAxel Dörfler 	return sInterfaces.Count();
1589c22d69bfSAxel Dörfler }
1590c22d69bfSAxel Dörfler 
1591c22d69bfSAxel Dörfler 
15923c13a5f5SAxel Dörfler /*!	Dumps a list of all interfaces into the supplied userland buffer.
1593c22d69bfSAxel Dörfler 	If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
1594c22d69bfSAxel Dörfler 	returned.
1595c22d69bfSAxel Dörfler */
1596c22d69bfSAxel Dörfler status_t
159761729d93SAxel Dörfler list_interfaces(int family, void* _buffer, size_t* bufferSize)
1598c22d69bfSAxel Dörfler {
15998a6337d0SStefano Ceccherini 	RecursiveLocker locker(sLock);
1600c22d69bfSAxel Dörfler 
1601409b1fc0SHugo Santos 	UserBuffer buffer(_buffer, *bufferSize);
1602c22d69bfSAxel Dörfler 
160361729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
160461729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1605715fed44SAxel Dörfler 		// Copy name
1606715fed44SAxel Dörfler 		buffer.Push(interface->name, IF_NAMESIZE);
1607c22d69bfSAxel Dörfler 
1608715fed44SAxel Dörfler 		// Copy address
160961729d93SAxel Dörfler 		InterfaceAddress* address = interface->FirstForFamily(family);
16101f9c8c45SAxel Dörfler 		size_t length = 0;
1611715fed44SAxel Dörfler 
161261729d93SAxel Dörfler 		if (address != NULL && address->local != NULL) {
1613715fed44SAxel Dörfler 			// Actual address
16141f9c8c45SAxel Dörfler 			buffer.Push(address->local, length = address->local->sa_len);
161561729d93SAxel Dörfler 		} else {
1616715fed44SAxel Dörfler 			// Empty address
16171f9c8c45SAxel Dörfler 			sockaddr empty;
16181f9c8c45SAxel Dörfler 			empty.sa_len = 2;
16191f9c8c45SAxel Dörfler 			empty.sa_family = AF_UNSPEC;
16201f9c8c45SAxel Dörfler 			buffer.Push(&empty, length = empty.sa_len);
1621715fed44SAxel Dörfler 		}
1622715fed44SAxel Dörfler 
162361729d93SAxel Dörfler 		if (address != NULL)
162461729d93SAxel Dörfler 			address->ReleaseReference();
162561729d93SAxel Dörfler 
16261f9c8c45SAxel Dörfler 		if (IF_NAMESIZE + length < sizeof(ifreq)) {
16271f9c8c45SAxel Dörfler 			// Make sure at least sizeof(ifreq) bytes are written for each
16281f9c8c45SAxel Dörfler 			// interface for compatibility with other platforms
16291f9c8c45SAxel Dörfler 			buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length);
16301f9c8c45SAxel Dörfler 		}
16311f9c8c45SAxel Dörfler 
16321f9c8c45SAxel Dörfler 		if (buffer.Status() != B_OK)
1633409b1fc0SHugo Santos 			return buffer.Status();
1634c22d69bfSAxel Dörfler 	}
1635c22d69bfSAxel Dörfler 
1636715fed44SAxel Dörfler 	*bufferSize = buffer.BytesConsumed();
1637c22d69bfSAxel Dörfler 	return B_OK;
1638c22d69bfSAxel Dörfler }
1639c22d69bfSAxel Dörfler 
1640c22d69bfSAxel Dörfler 
1641c22d69bfSAxel Dörfler //	#pragma mark -
1642c22d69bfSAxel Dörfler 
1643c22d69bfSAxel Dörfler 
1644c22d69bfSAxel Dörfler status_t
1645c22d69bfSAxel Dörfler init_interfaces()
1646c22d69bfSAxel Dörfler {
16478a6337d0SStefano Ceccherini 	recursive_lock_init(&sLock, "net interfaces");
164861729d93SAxel Dörfler 	mutex_init(&sHashLock, "net local addresses");
1649c22d69bfSAxel Dörfler 
165061729d93SAxel Dörfler 	new (&sInterfaces) InterfaceList;
165161729d93SAxel Dörfler 	new (&sAddressTable) AddressTable;
16529206bb37SAxel Dörfler 		// static C++ objects are not initialized in the module startup
1653a3ec278aSAxel Dörfler 
1654a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1655a3ec278aSAxel Dörfler 	add_debugger_command("net_interface", &dump_interface,
1656a3ec278aSAxel Dörfler 		"Dump the given network interface");
165761729d93SAxel Dörfler 	add_debugger_command("net_interfaces", &dump_interfaces,
165861729d93SAxel Dörfler 		"Dump all network interfaces");
165961729d93SAxel Dörfler 	add_debugger_command("net_local", &dump_local,
166061729d93SAxel Dörfler 		"Dump all local interface addresses");
166161729d93SAxel Dörfler 	add_debugger_command("net_route", &dump_route,
166261729d93SAxel Dörfler 		"Dump the given network route");
1663a3ec278aSAxel Dörfler #endif
1664c22d69bfSAxel Dörfler 	return B_OK;
1665c22d69bfSAxel Dörfler }
1666c22d69bfSAxel Dörfler 
1667c22d69bfSAxel Dörfler 
1668c22d69bfSAxel Dörfler status_t
1669c22d69bfSAxel Dörfler uninit_interfaces()
1670c22d69bfSAxel Dörfler {
1671a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1672a3ec278aSAxel Dörfler 	remove_debugger_command("net_interface", &dump_interface);
16733f2a0963SPhilippe Houdoin 	remove_debugger_command("net_interfaces", &dump_interfaces);
16743f2a0963SPhilippe Houdoin 	remove_debugger_command("net_local", &dump_local);
16753f2a0963SPhilippe Houdoin 	remove_debugger_command("net_route", &dump_route);
1676a3ec278aSAxel Dörfler #endif
1677a3ec278aSAxel Dörfler 
16788a6337d0SStefano Ceccherini 	recursive_lock_destroy(&sLock);
167961729d93SAxel Dörfler 	mutex_destroy(&sHashLock);
1680c22d69bfSAxel Dörfler 	return B_OK;
1681c22d69bfSAxel Dörfler }
1682c22d69bfSAxel Dörfler 
1683