xref: /haiku/src/add-ons/kernel/network/stack/interfaces.cpp (revision e78fea43f50d8a07bbce1d406401c9a66e69afc2)
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 
88ec4fb0f4SAxel Dörfler #if 0
89ec4fb0f4SAxel Dörfler //! For debugging purposes only
90ec4fb0f4SAxel Dörfler void
91ec4fb0f4SAxel Dörfler dump_interface_refs(void)
92ec4fb0f4SAxel Dörfler {
93ec4fb0f4SAxel Dörfler 	MutexLocker locker(sLock);
94ec4fb0f4SAxel Dörfler 
95ec4fb0f4SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
96ec4fb0f4SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
97ec4fb0f4SAxel Dörfler 		dprintf("%p: %s, %ld\n", interface, interface->name,
98ec4fb0f4SAxel Dörfler 			interface->CountReferences());
99ec4fb0f4SAxel Dörfler 	}
100ec4fb0f4SAxel Dörfler }
101ec4fb0f4SAxel Dörfler #endif
102ec4fb0f4SAxel Dörfler 
103ec4fb0f4SAxel Dörfler 
104a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
105a3ec278aSAxel Dörfler 
106a3ec278aSAxel Dörfler 
107a3ec278aSAxel Dörfler static int
108a3ec278aSAxel Dörfler dump_interface(int argc, char** argv)
109a3ec278aSAxel Dörfler {
110a3ec278aSAxel Dörfler 	if (argc != 2) {
11111eccb54SAxel Dörfler 		kprintf("usage: %s [name|address]\n", argv[0]);
112a3ec278aSAxel Dörfler 		return 0;
113a3ec278aSAxel Dörfler 	}
114a3ec278aSAxel Dörfler 
11511eccb54SAxel Dörfler 	Interface* interface = NULL;
11611eccb54SAxel Dörfler 
11711eccb54SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
11811eccb54SAxel Dörfler 	while ((interface = iterator.Next()) != NULL) {
11911eccb54SAxel Dörfler 		if (!strcmp(argv[1], interface->name))
12011eccb54SAxel Dörfler 			break;
12111eccb54SAxel Dörfler 	}
12211eccb54SAxel Dörfler 
12311eccb54SAxel Dörfler 	if (interface == NULL)
12411eccb54SAxel Dörfler 		interface = (Interface*)parse_expression(argv[1]);
12511eccb54SAxel Dörfler 
12661729d93SAxel Dörfler 	interface->Dump();
127a3ec278aSAxel Dörfler 
128a3ec278aSAxel Dörfler 	return 0;
129a3ec278aSAxel Dörfler }
130a3ec278aSAxel Dörfler 
131a3ec278aSAxel Dörfler 
132a3ec278aSAxel Dörfler static int
13361729d93SAxel Dörfler dump_interfaces(int argc, char** argv)
13461729d93SAxel Dörfler {
13561729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
13661729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
13761729d93SAxel Dörfler 		kprintf("%p  %s\n", interface, interface->name);
13861729d93SAxel Dörfler 	}
13961729d93SAxel Dörfler 	return 0;
14061729d93SAxel Dörfler }
14161729d93SAxel Dörfler 
14261729d93SAxel Dörfler 
14361729d93SAxel Dörfler static int
14461729d93SAxel Dörfler dump_local(int argc, char** argv)
14561729d93SAxel Dörfler {
14661729d93SAxel Dörfler 	AddressTable::Iterator iterator = sAddressTable.GetIterator();
14761729d93SAxel Dörfler 	size_t i = 0;
14861729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
14961729d93SAxel Dörfler 		address->Dump(++i);
15061729d93SAxel Dörfler 		dprintf("    hash:          %lu\n",
15161729d93SAxel Dörfler 			address->domain->address_module->hash_address(address->local,
15261729d93SAxel Dörfler 				false));
15361729d93SAxel Dörfler 	}
15461729d93SAxel Dörfler 	return 0;
15561729d93SAxel Dörfler }
15661729d93SAxel Dörfler 
15761729d93SAxel Dörfler 
15861729d93SAxel Dörfler static int
15961729d93SAxel Dörfler dump_route(int argc, char** argv)
160a3ec278aSAxel Dörfler {
161a3ec278aSAxel Dörfler 	if (argc != 2) {
162a3ec278aSAxel Dörfler 		kprintf("usage: %s [address]\n", argv[0]);
163a3ec278aSAxel Dörfler 		return 0;
164a3ec278aSAxel Dörfler 	}
165a3ec278aSAxel Dörfler 
16661729d93SAxel Dörfler 	net_route* route = (net_route*)parse_expression(argv[1]);
16761729d93SAxel Dörfler 	kprintf("destination:       %p\n", route->destination);
16861729d93SAxel Dörfler 	kprintf("mask:              %p\n", route->mask);
16961729d93SAxel Dörfler 	kprintf("gateway:           %p\n", route->gateway);
17061729d93SAxel Dörfler 	kprintf("flags:             %" B_PRIx32 "\n", route->flags);
17161729d93SAxel Dörfler 	kprintf("mtu:               %" B_PRIu32 "\n", route->mtu);
17261729d93SAxel Dörfler 	kprintf("interface address: %p\n", route->interface_address);
173a3ec278aSAxel Dörfler 
17461729d93SAxel Dörfler 	if (route->interface_address != NULL) {
17561729d93SAxel Dörfler 		((InterfaceAddress*)route->interface_address)->Dump();
176a3ec278aSAxel Dörfler 	}
177a3ec278aSAxel Dörfler 
178a3ec278aSAxel Dörfler 	return 0;
179a3ec278aSAxel Dörfler }
180a3ec278aSAxel Dörfler 
181a3ec278aSAxel Dörfler 
182a3ec278aSAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
183a3ec278aSAxel Dörfler 
184a3ec278aSAxel Dörfler 
18561729d93SAxel Dörfler InterfaceAddress::InterfaceAddress()
186c22d69bfSAxel Dörfler {
18761729d93SAxel Dörfler 	_Init(NULL, NULL);
18861729d93SAxel Dörfler }
189c22d69bfSAxel Dörfler 
19061729d93SAxel Dörfler 
19161729d93SAxel Dörfler InterfaceAddress::InterfaceAddress(net_interface* netInterface,
19261729d93SAxel Dörfler 	net_domain* netDomain)
19361729d93SAxel Dörfler {
19461729d93SAxel Dörfler 	_Init(netInterface, netDomain);
19561729d93SAxel Dörfler }
19661729d93SAxel Dörfler 
19761729d93SAxel Dörfler 
19861729d93SAxel Dörfler InterfaceAddress::~InterfaceAddress()
19961729d93SAxel Dörfler {
2002b1c0755SAxel Dörfler 	TRACE("InterfaceAddress %p: destructor\n", this);
2012b1c0755SAxel Dörfler 
2022b1c0755SAxel Dörfler 	if (interface != NULL && (flags & IFAF_DIRECT_ADDRESS) == 0)
2032b1c0755SAxel Dörfler 		((Interface*)interface)->ReleaseReference();
20461729d93SAxel Dörfler }
20561729d93SAxel Dörfler 
20661729d93SAxel Dörfler 
20761729d93SAxel Dörfler status_t
20861729d93SAxel Dörfler InterfaceAddress::SetTo(const ifaliasreq& request)
20961729d93SAxel Dörfler {
21061729d93SAxel Dörfler 	status_t status = SetLocal((const sockaddr*)&request.ifra_addr);
21161729d93SAxel Dörfler 	if (status == B_OK)
21261729d93SAxel Dörfler 		status = SetDestination((const sockaddr*)&request.ifra_broadaddr);
21361729d93SAxel Dörfler 	if (status == B_OK)
21461729d93SAxel Dörfler 		status = SetMask((const sockaddr*)&request.ifra_mask);
21561729d93SAxel Dörfler 
21661729d93SAxel Dörfler 	return status;
21761729d93SAxel Dörfler }
21861729d93SAxel Dörfler 
21961729d93SAxel Dörfler 
22061729d93SAxel Dörfler status_t
22161729d93SAxel Dörfler InterfaceAddress::SetLocal(const sockaddr* to)
22261729d93SAxel Dörfler {
22361729d93SAxel Dörfler 	return Set(&local, to);
22461729d93SAxel Dörfler }
22561729d93SAxel Dörfler 
22661729d93SAxel Dörfler 
22761729d93SAxel Dörfler status_t
22861729d93SAxel Dörfler InterfaceAddress::SetDestination(const sockaddr* to)
22961729d93SAxel Dörfler {
23061729d93SAxel Dörfler 	return Set(&destination, to);
23161729d93SAxel Dörfler }
23261729d93SAxel Dörfler 
23361729d93SAxel Dörfler 
23461729d93SAxel Dörfler status_t
23561729d93SAxel Dörfler InterfaceAddress::SetMask(const sockaddr* to)
23661729d93SAxel Dörfler {
23761729d93SAxel Dörfler 	return Set(&mask, to);
23861729d93SAxel Dörfler }
23961729d93SAxel Dörfler 
24061729d93SAxel Dörfler 
24161729d93SAxel Dörfler sockaddr**
24261729d93SAxel Dörfler InterfaceAddress::AddressFor(int32 option)
24361729d93SAxel Dörfler {
24461729d93SAxel Dörfler 	switch (option) {
24561729d93SAxel Dörfler 		case SIOCSIFADDR:
24661729d93SAxel Dörfler 		case SIOCGIFADDR:
2472b1c0755SAxel Dörfler 		case SIOCDIFADDR:
24861729d93SAxel Dörfler 			return &local;
24961729d93SAxel Dörfler 
25061729d93SAxel Dörfler 		case SIOCSIFNETMASK:
25161729d93SAxel Dörfler 		case SIOCGIFNETMASK:
25261729d93SAxel Dörfler 			return &mask;
25361729d93SAxel Dörfler 
25461729d93SAxel Dörfler 		case SIOCSIFBRDADDR:
25561729d93SAxel Dörfler 		case SIOCSIFDSTADDR:
25661729d93SAxel Dörfler 		case SIOCGIFBRDADDR:
25761729d93SAxel Dörfler 		case SIOCGIFDSTADDR:
25861729d93SAxel Dörfler 			return &destination;
25961729d93SAxel Dörfler 
26061729d93SAxel Dörfler 		default:
26161729d93SAxel Dörfler 			return NULL;
26261729d93SAxel Dörfler 	}
26361729d93SAxel Dörfler }
26461729d93SAxel Dörfler 
26561729d93SAxel Dörfler 
2662b1c0755SAxel Dörfler /*!	Adds the default routes that every interface address needs, ie. the local
2672b1c0755SAxel Dörfler 	host route, and one for the subnet (if set).
2682b1c0755SAxel Dörfler */
2692b1c0755SAxel Dörfler void
2702b1c0755SAxel Dörfler InterfaceAddress::AddDefaultRoutes(int32 option)
2712b1c0755SAxel Dörfler {
2722b1c0755SAxel Dörfler 	net_route route;
2732b1c0755SAxel Dörfler 	route.destination = local;
2742b1c0755SAxel Dörfler 	route.gateway = NULL;
2752b1c0755SAxel Dörfler 	route.interface_address = this;
2762b1c0755SAxel Dörfler 
2772b1c0755SAxel Dörfler 	if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
2782b1c0755SAxel Dörfler 		route.mask = mask;
2792b1c0755SAxel Dörfler 		route.flags = 0;
2802b1c0755SAxel Dörfler 		add_route(domain, &route);
2812b1c0755SAxel Dörfler 	}
2822b1c0755SAxel Dörfler 
2832b1c0755SAxel Dörfler 	if (option == SIOCSIFADDR) {
2842b1c0755SAxel Dörfler 		route.mask = NULL;
2852b1c0755SAxel Dörfler 		route.flags = RTF_LOCAL | RTF_HOST;
2862b1c0755SAxel Dörfler 		add_route(domain, &route);
2872b1c0755SAxel Dörfler 	}
2882b1c0755SAxel Dörfler }
2892b1c0755SAxel Dörfler 
2902b1c0755SAxel Dörfler 
2912b1c0755SAxel Dörfler /*!	Removes the default routes as set by AddDefaultRoutes() again. */
2922b1c0755SAxel Dörfler void
2932b1c0755SAxel Dörfler InterfaceAddress::RemoveDefaultRoutes(int32 option)
2942b1c0755SAxel Dörfler {
2952b1c0755SAxel Dörfler 	net_route route;
2962b1c0755SAxel Dörfler 	route.destination = local;
2972b1c0755SAxel Dörfler 	route.gateway = NULL;
2982b1c0755SAxel Dörfler 	route.interface_address = this;
2992b1c0755SAxel Dörfler 
3002b1c0755SAxel Dörfler 	if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
3012b1c0755SAxel Dörfler 		route.mask = mask;
3022b1c0755SAxel Dörfler 		route.flags = 0;
3032b1c0755SAxel Dörfler 		remove_route(domain, &route);
3042b1c0755SAxel Dörfler 	}
3052b1c0755SAxel Dörfler 
3062b1c0755SAxel Dörfler 	if (option == SIOCSIFADDR) {
3072b1c0755SAxel Dörfler 		route.mask = NULL;
3082b1c0755SAxel Dörfler 		route.flags = RTF_LOCAL | RTF_HOST;
3092b1c0755SAxel Dörfler 		remove_route(domain, &route);
3102b1c0755SAxel Dörfler 	}
3112b1c0755SAxel Dörfler }
3122b1c0755SAxel Dörfler 
3132b1c0755SAxel Dörfler 
31461729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
31561729d93SAxel Dörfler 
31661729d93SAxel Dörfler 
31761729d93SAxel Dörfler void
31861729d93SAxel Dörfler InterfaceAddress::Dump(size_t index, bool hideInterface)
31961729d93SAxel Dörfler {
32061729d93SAxel Dörfler 	if (index)
32161729d93SAxel Dörfler 		kprintf("%2zu. ", index);
32261729d93SAxel Dörfler 	else
32361729d93SAxel Dörfler 		kprintf("    ");
32461729d93SAxel Dörfler 
32561729d93SAxel Dörfler 	if (!hideInterface) {
32661729d93SAxel Dörfler 		kprintf("interface:   %p (%s)\n    ", interface,
32761729d93SAxel Dörfler 			interface != NULL ? interface->name : "-");
32861729d93SAxel Dörfler 	}
32961729d93SAxel Dörfler 
33061729d93SAxel Dörfler 	kprintf("domain:      %p (family %u)\n", domain,
33161729d93SAxel Dörfler 		domain != NULL ? domain->family : AF_UNSPEC);
33261729d93SAxel Dörfler 
33361729d93SAxel Dörfler 	char buffer[64];
33461729d93SAxel Dörfler 	if (local != NULL && domain != NULL) {
33561729d93SAxel Dörfler 		domain->address_module->print_address_buffer(local, buffer,
33661729d93SAxel Dörfler 			sizeof(buffer), false);
33761729d93SAxel Dörfler 	} else
33861729d93SAxel Dörfler 		strcpy(buffer, "-");
33961729d93SAxel Dörfler 	kprintf("    local:       %s\n", buffer);
34061729d93SAxel Dörfler 
34161729d93SAxel Dörfler 	if (mask != NULL && domain != NULL) {
34261729d93SAxel Dörfler 		domain->address_module->print_address_buffer(mask, buffer,
34361729d93SAxel Dörfler 			sizeof(buffer), false);
34461729d93SAxel Dörfler 	} else
34561729d93SAxel Dörfler 		strcpy(buffer, "-");
34661729d93SAxel Dörfler 	kprintf("    mask:        %s\n", buffer);
34761729d93SAxel Dörfler 
34861729d93SAxel Dörfler 	if (destination != NULL && domain != NULL) {
34961729d93SAxel Dörfler 		domain->address_module->print_address_buffer(destination, buffer,
35061729d93SAxel Dörfler 			sizeof(buffer), false);
35161729d93SAxel Dörfler 	} else
35261729d93SAxel Dörfler 		strcpy(buffer, "-");
35361729d93SAxel Dörfler 	kprintf("    destination: %s\n", buffer);
3544af124a1SAxel Dörfler 
3554af124a1SAxel Dörfler 	kprintf("    ref count:   %" B_PRId32 "\n", CountReferences());
35661729d93SAxel Dörfler }
35761729d93SAxel Dörfler 
35861729d93SAxel Dörfler 
35961729d93SAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
36061729d93SAxel Dörfler 
36161729d93SAxel Dörfler 
36261729d93SAxel Dörfler /*static*/ status_t
36361729d93SAxel Dörfler InterfaceAddress::Set(sockaddr** _address, const sockaddr* to)
36461729d93SAxel Dörfler {
36561729d93SAxel Dörfler 	sockaddr* address = *_address;
36661729d93SAxel Dörfler 
36761729d93SAxel Dörfler 	if (to == NULL || to->sa_family == AF_UNSPEC) {
36861729d93SAxel Dörfler 		// Clear address
36961729d93SAxel Dörfler 		free(address);
37061729d93SAxel Dörfler 		*_address = NULL;
37161729d93SAxel Dörfler 		return B_OK;
37261729d93SAxel Dörfler 	}
37361729d93SAxel Dörfler 
37461729d93SAxel Dörfler 	// Set address
37561729d93SAxel Dörfler 
37661729d93SAxel Dörfler 	size_t size = max_c(to->sa_len, sizeof(sockaddr));
37761729d93SAxel Dörfler 	if (size > sizeof(sockaddr_storage))
37861729d93SAxel Dörfler 		size = sizeof(sockaddr_storage);
37961729d93SAxel Dörfler 
38061729d93SAxel Dörfler 	address = Prepare(_address, size);
38161729d93SAxel Dörfler 	if (address == NULL)
38261729d93SAxel Dörfler 		return B_NO_MEMORY;
38361729d93SAxel Dörfler 
38461729d93SAxel Dörfler 	memcpy(address, to, size);
38561729d93SAxel Dörfler 	address->sa_len = size;
38661729d93SAxel Dörfler 
38761729d93SAxel Dörfler 	return B_OK;
38861729d93SAxel Dörfler }
38961729d93SAxel Dörfler 
39061729d93SAxel Dörfler 
39161729d93SAxel Dörfler /*static*/ sockaddr*
39261729d93SAxel Dörfler InterfaceAddress::Prepare(sockaddr** _address, size_t size)
39361729d93SAxel Dörfler {
39461729d93SAxel Dörfler 	size = max_c(size, sizeof(sockaddr));
39561729d93SAxel Dörfler 	if (size > sizeof(sockaddr_storage))
39661729d93SAxel Dörfler 		size = sizeof(sockaddr_storage);
39761729d93SAxel Dörfler 
39861729d93SAxel Dörfler 	sockaddr* address = *_address;
39961729d93SAxel Dörfler 
40061729d93SAxel Dörfler 	if (address == NULL || size > address->sa_len) {
40161729d93SAxel Dörfler 		address = (sockaddr*)realloc(address, size);
40261729d93SAxel Dörfler 		if (address == NULL)
40361729d93SAxel Dörfler 			return NULL;
40461729d93SAxel Dörfler 	}
40561729d93SAxel Dörfler 
40661729d93SAxel Dörfler 	address->sa_len = size;
40761729d93SAxel Dörfler 
40861729d93SAxel Dörfler 	*_address = address;
40961729d93SAxel Dörfler 	return address;
41061729d93SAxel Dörfler }
41161729d93SAxel Dörfler 
41261729d93SAxel Dörfler 
41361729d93SAxel Dörfler void
41461729d93SAxel Dörfler InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain)
41561729d93SAxel Dörfler {
4162b1c0755SAxel Dörfler 	TRACE("InterfaceAddress %p: init interface %p, domain %p\n", this,
4172b1c0755SAxel Dörfler 		netInterface, netDomain);
4182b1c0755SAxel Dörfler 
41961729d93SAxel Dörfler 	interface = netInterface;
42061729d93SAxel Dörfler 	domain = netDomain;
42161729d93SAxel Dörfler 	local = NULL;
42261729d93SAxel Dörfler 	destination = NULL;
42361729d93SAxel Dörfler 	mask = NULL;
4242b1c0755SAxel Dörfler 	flags = 0;
4252b1c0755SAxel Dörfler 
4262b1c0755SAxel Dörfler 	if (interface != NULL)
4272b1c0755SAxel Dörfler 		((Interface*)interface)->AcquireReference();
42861729d93SAxel Dörfler }
42961729d93SAxel Dörfler 
43061729d93SAxel Dörfler 
43161729d93SAxel Dörfler // #pragma mark -
43261729d93SAxel Dörfler 
43361729d93SAxel Dörfler 
43461729d93SAxel Dörfler Interface::Interface(const char* interfaceName,
43561729d93SAxel Dörfler 	net_device_interface* deviceInterface)
43661729d93SAxel Dörfler {
43761729d93SAxel Dörfler 	TRACE("Interface %p: new \"%s\", device interface %p\n", this,
43861729d93SAxel Dörfler 		interfaceName, deviceInterface);
43961729d93SAxel Dörfler 
440b0cf274aSAxel Dörfler 	int written = strlcpy(name, interfaceName, IF_NAMESIZE);
441b0cf274aSAxel Dörfler 	memset(name + written, 0, IF_NAMESIZE - written);
442b0cf274aSAxel Dörfler 		// Clear remaining space
443b0cf274aSAxel Dörfler 
44461729d93SAxel Dörfler 	device = deviceInterface->device;
44561729d93SAxel Dörfler 
44661729d93SAxel Dörfler 	index = ++sInterfaceIndex;
44761729d93SAxel Dörfler 	flags = 0;
44861729d93SAxel Dörfler 	type = 0;
44961729d93SAxel Dörfler 	mtu = deviceInterface->device->mtu;
45061729d93SAxel Dörfler 	metric = 0;
45161729d93SAxel Dörfler 
45261729d93SAxel Dörfler 	fDeviceInterface = acquire_device_interface(deviceInterface);
45361729d93SAxel Dörfler 
45461729d93SAxel Dörfler 	recursive_lock_init(&fLock, name);
45561729d93SAxel Dörfler 
45661729d93SAxel Dörfler 	// Grab a reference to the networking stack, to make sure it won't be
45761729d93SAxel Dörfler 	// unloaded as long as an interface exists
45861729d93SAxel Dörfler 	module_info* module;
45961729d93SAxel Dörfler 	get_module(gNetStackInterfaceModule.info.name, &module);
46061729d93SAxel Dörfler }
46161729d93SAxel Dörfler 
46261729d93SAxel Dörfler 
46361729d93SAxel Dörfler Interface::~Interface()
46461729d93SAxel Dörfler {
4652b1c0755SAxel Dörfler 	TRACE("Interface %p: destructor\n", this);
4662b1c0755SAxel Dörfler 
4672b1c0755SAxel Dörfler 	put_device_interface(fDeviceInterface);
4682b1c0755SAxel Dörfler 
4692b1c0755SAxel Dörfler 	// Uninitialize the domain datalink protocols
4702b1c0755SAxel Dörfler 
4712b1c0755SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
4722b1c0755SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
4732b1c0755SAxel Dörfler 		put_domain_datalink_protocols(this, datalink->domain);
4742b1c0755SAxel Dörfler 	}
4752b1c0755SAxel Dörfler 
4762b1c0755SAxel Dörfler 	// Free domain datalink objects
4772b1c0755SAxel Dörfler 
4782b1c0755SAxel Dörfler 	domain_datalink* next = fDatalinkTable.Clear(true);
4792b1c0755SAxel Dörfler 	while (next != NULL) {
4802b1c0755SAxel Dörfler 		domain_datalink* datalink = next;
4812b1c0755SAxel Dörfler 		next = next->hash_link;
4822b1c0755SAxel Dörfler 
4832b1c0755SAxel Dörfler 		delete datalink;
4842b1c0755SAxel Dörfler 	}
4852b1c0755SAxel Dörfler 
48661729d93SAxel Dörfler 	recursive_lock_destroy(&fLock);
48761729d93SAxel Dörfler 
48861729d93SAxel Dörfler 	// Release reference of the stack - at this point, our stack may be unloaded
48961729d93SAxel Dörfler 	// if no other interfaces or sockets are left
49061729d93SAxel Dörfler 	put_module(gNetStackInterfaceModule.info.name);
49161729d93SAxel Dörfler }
49261729d93SAxel Dörfler 
49361729d93SAxel Dörfler 
49461729d93SAxel Dörfler /*!	Returns a reference to the first InterfaceAddress that is from the same
49561729d93SAxel Dörfler 	as the specified \a family.
49661729d93SAxel Dörfler */
49761729d93SAxel Dörfler InterfaceAddress*
49861729d93SAxel Dörfler Interface::FirstForFamily(int family)
49961729d93SAxel Dörfler {
50061729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
50161729d93SAxel Dörfler 
50261729d93SAxel Dörfler 	InterfaceAddress* address = _FirstForFamily(family);
50361729d93SAxel Dörfler 	if (address != NULL) {
50461729d93SAxel Dörfler 		address->AcquireReference();
50561729d93SAxel Dörfler 		return address;
50661729d93SAxel Dörfler 	}
50761729d93SAxel Dörfler 
50861729d93SAxel Dörfler 	return NULL;
50961729d93SAxel Dörfler }
51061729d93SAxel Dörfler 
51161729d93SAxel Dörfler 
51261729d93SAxel Dörfler /*!	Returns a reference to the first unconfigured address of this interface
51361729d93SAxel Dörfler 	for the specified \a family.
51461729d93SAxel Dörfler */
51561729d93SAxel Dörfler InterfaceAddress*
51661729d93SAxel Dörfler Interface::FirstUnconfiguredForFamily(int family)
51761729d93SAxel Dörfler {
51861729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
51961729d93SAxel Dörfler 
52061729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
52161729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
52261729d93SAxel Dörfler 		if (address->domain->family == family
52361729d93SAxel Dörfler 			&& (address->local == NULL
52461729d93SAxel Dörfler 				// TODO: this has to be solved differently!!
52561729d93SAxel Dörfler 				|| (flags & IFF_CONFIGURING) != 0)) {
52661729d93SAxel Dörfler 			address->AcquireReference();
52761729d93SAxel Dörfler 			return address;
52861729d93SAxel Dörfler 		}
52961729d93SAxel Dörfler 	}
53061729d93SAxel Dörfler 
53161729d93SAxel Dörfler 	return NULL;
53261729d93SAxel Dörfler }
53361729d93SAxel Dörfler 
53461729d93SAxel Dörfler 
53561729d93SAxel Dörfler /*!	Returns a reference to the InterfaceAddress that has the specified
53661729d93SAxel Dörfler 	\a destination address.
53761729d93SAxel Dörfler */
53861729d93SAxel Dörfler InterfaceAddress*
53961729d93SAxel Dörfler Interface::AddressForDestination(net_domain* domain,
54061729d93SAxel Dörfler 	const sockaddr* destination)
54161729d93SAxel Dörfler {
54261729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
54361729d93SAxel Dörfler 
54461729d93SAxel Dörfler 	if ((device->flags & IFF_BROADCAST) == 0) {
54561729d93SAxel Dörfler 		// The device does not support broadcasting
54661729d93SAxel Dörfler 		return NULL;
54761729d93SAxel Dörfler 	}
54861729d93SAxel Dörfler 
54961729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
55061729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
55161729d93SAxel Dörfler 		if (address->domain == domain
55261729d93SAxel Dörfler 			&& address->destination != NULL
55361729d93SAxel Dörfler 			&& domain->address_module->equal_addresses(address->destination,
55461729d93SAxel Dörfler 					destination)) {
55561729d93SAxel Dörfler 			address->AcquireReference();
55661729d93SAxel Dörfler 			return address;
55761729d93SAxel Dörfler 		}
55861729d93SAxel Dörfler 	}
55961729d93SAxel Dörfler 
56061729d93SAxel Dörfler 	return NULL;
56161729d93SAxel Dörfler }
56261729d93SAxel Dörfler 
56361729d93SAxel Dörfler 
564910ffb32SAxel Dörfler /*!	Returns a reference to the InterfaceAddress that has the specified
565910ffb32SAxel Dörfler 	\a local address.
566910ffb32SAxel Dörfler */
567910ffb32SAxel Dörfler InterfaceAddress*
568910ffb32SAxel Dörfler Interface::AddressForLocal(net_domain* domain, const sockaddr* local)
569910ffb32SAxel Dörfler {
570910ffb32SAxel Dörfler 	RecursiveLocker locker(fLock);
571910ffb32SAxel Dörfler 
572910ffb32SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
573910ffb32SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
574910ffb32SAxel Dörfler 		if (address->domain == domain
575910ffb32SAxel Dörfler 			&& address->local != NULL
576910ffb32SAxel Dörfler 			&& domain->address_module->equal_addresses(address->local, local)) {
577910ffb32SAxel Dörfler 			address->AcquireReference();
578910ffb32SAxel Dörfler 			return address;
579910ffb32SAxel Dörfler 		}
580910ffb32SAxel Dörfler 	}
581910ffb32SAxel Dörfler 
582910ffb32SAxel Dörfler 	return NULL;
583910ffb32SAxel Dörfler }
584910ffb32SAxel Dörfler 
585910ffb32SAxel Dörfler 
58661729d93SAxel Dörfler status_t
58761729d93SAxel Dörfler Interface::AddAddress(InterfaceAddress* address)
58861729d93SAxel Dörfler {
58961729d93SAxel Dörfler 	net_domain* domain = address->domain;
59061729d93SAxel Dörfler 	if (domain == NULL)
59161729d93SAxel Dörfler 		return B_BAD_VALUE;
59261729d93SAxel Dörfler 
59361729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
59461729d93SAxel Dörfler 	fAddresses.Add(address);
59561729d93SAxel Dörfler 	locker.Unlock();
59661729d93SAxel Dörfler 
59761729d93SAxel Dörfler 	MutexLocker hashLocker(sHashLock);
59861729d93SAxel Dörfler 	sAddressTable.Insert(address);
59961729d93SAxel Dörfler 	return B_OK;
60061729d93SAxel Dörfler }
60161729d93SAxel Dörfler 
60261729d93SAxel Dörfler 
60361729d93SAxel Dörfler void
60461729d93SAxel Dörfler Interface::RemoveAddress(InterfaceAddress* address)
60561729d93SAxel Dörfler {
60661729d93SAxel Dörfler 	net_domain* domain = address->domain;
60761729d93SAxel Dörfler 	if (domain == NULL)
60861729d93SAxel Dörfler 		return;
60961729d93SAxel Dörfler 
61061729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
61161729d93SAxel Dörfler 
61261729d93SAxel Dörfler 	fAddresses.Remove(address);
61361729d93SAxel Dörfler 	address->GetDoublyLinkedListLink()->next = NULL;
61461729d93SAxel Dörfler 
61561729d93SAxel Dörfler 	locker.Unlock();
61661729d93SAxel Dörfler 
61761729d93SAxel Dörfler 	MutexLocker hashLocker(sHashLock);
61861729d93SAxel Dörfler 	sAddressTable.Remove(address);
61961729d93SAxel Dörfler }
62061729d93SAxel Dörfler 
62161729d93SAxel Dörfler 
62261729d93SAxel Dörfler bool
62361729d93SAxel Dörfler Interface::GetNextAddress(InterfaceAddress** _address)
62461729d93SAxel Dörfler {
62561729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
62661729d93SAxel Dörfler 
62761729d93SAxel Dörfler 	InterfaceAddress* address = *_address;
62861729d93SAxel Dörfler 	if (address == NULL) {
62961729d93SAxel Dörfler 		// get first address
63061729d93SAxel Dörfler 		address = fAddresses.First();
63161729d93SAxel Dörfler 	} else {
63261729d93SAxel Dörfler 		// get next, if possible
63361729d93SAxel Dörfler 		InterfaceAddress* next = fAddresses.GetNext(address);
63461729d93SAxel Dörfler 		address->ReleaseReference();
63561729d93SAxel Dörfler 		address = next;
63661729d93SAxel Dörfler 	}
63761729d93SAxel Dörfler 
63861729d93SAxel Dörfler 	*_address = address;
63961729d93SAxel Dörfler 
64061729d93SAxel Dörfler 	if (address == NULL)
64161729d93SAxel Dörfler 		return false;
64261729d93SAxel Dörfler 
64361729d93SAxel Dörfler 	address->AcquireReference();
64461729d93SAxel Dörfler 	return true;
64561729d93SAxel Dörfler }
64661729d93SAxel Dörfler 
64761729d93SAxel Dörfler 
6489d771afbSAxel Dörfler InterfaceAddress*
6499d771afbSAxel Dörfler Interface::AddressAt(size_t index)
6509d771afbSAxel Dörfler {
6519d771afbSAxel Dörfler 	RecursiveLocker locker(fLock);
6529d771afbSAxel Dörfler 
6539d771afbSAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
6549d771afbSAxel Dörfler 	size_t i = 0;
6559d771afbSAxel Dörfler 
6569d771afbSAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
6579d771afbSAxel Dörfler 		if (i++ == index) {
6589d771afbSAxel Dörfler 			address->AcquireReference();
6599d771afbSAxel Dörfler 			return address;
6609d771afbSAxel Dörfler 		}
6619d771afbSAxel Dörfler 	}
6629d771afbSAxel Dörfler 
6639d771afbSAxel Dörfler 	return NULL;
6649d771afbSAxel Dörfler }
6659d771afbSAxel Dörfler 
6669d771afbSAxel Dörfler 
6672c12b8a3SAxel Dörfler int32
6682c12b8a3SAxel Dörfler Interface::IndexOfAddress(InterfaceAddress* address)
6692c12b8a3SAxel Dörfler {
6702c12b8a3SAxel Dörfler 	RecursiveLocker locker(fLock);
6712c12b8a3SAxel Dörfler 
6722c12b8a3SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
6732c12b8a3SAxel Dörfler 	int32 index = 0;
6742c12b8a3SAxel Dörfler 
6752c12b8a3SAxel Dörfler 	while (iterator.HasNext()) {
6762c12b8a3SAxel Dörfler 		if (address == iterator.Next())
6772c12b8a3SAxel Dörfler 			return index;
6782c12b8a3SAxel Dörfler 
6792c12b8a3SAxel Dörfler 		index++;
6802c12b8a3SAxel Dörfler 	}
6812c12b8a3SAxel Dörfler 
6822c12b8a3SAxel Dörfler 	return -1;
6832c12b8a3SAxel Dörfler }
6842c12b8a3SAxel Dörfler 
6852c12b8a3SAxel Dörfler 
6869d771afbSAxel Dörfler size_t
6879d771afbSAxel Dörfler Interface::CountAddresses()
6889d771afbSAxel Dörfler {
6899d771afbSAxel Dörfler 	RecursiveLocker locker(fLock);
6909d771afbSAxel Dörfler 	return fAddresses.Count();
6919d771afbSAxel Dörfler }
6929d771afbSAxel Dörfler 
6939d771afbSAxel Dörfler 
6942b1c0755SAxel Dörfler void
6952b1c0755SAxel Dörfler Interface::RemoveAddresses()
6962b1c0755SAxel Dörfler {
6972b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
6982b1c0755SAxel Dörfler 
6992b1c0755SAxel Dörfler 	while (InterfaceAddress* address = fAddresses.RemoveHead()) {
7002b1c0755SAxel Dörfler 		address->ReleaseReference();
7012b1c0755SAxel Dörfler 	}
7022b1c0755SAxel Dörfler }
7032b1c0755SAxel Dörfler 
7042b1c0755SAxel Dörfler 
7059d771afbSAxel Dörfler /*!	This is called in order to call the correct methods of the datalink
7069d771afbSAxel Dörfler 	protocols, ie. it will translate address changes to
7079d771afbSAxel Dörfler 	net_datalink_protocol::change_address(), and IFF_UP changes to
7089d771afbSAxel Dörfler 	net_datalink_protocol::interface_up(), and interface_down().
7099d771afbSAxel Dörfler 
7109d771afbSAxel Dörfler 	Everything else is passed unchanged to net_datalink_protocol::control().
7119d771afbSAxel Dörfler */
71261729d93SAxel Dörfler status_t
71361729d93SAxel Dörfler Interface::Control(net_domain* domain, int32 option, ifreq& request,
71461729d93SAxel Dörfler 	ifreq* userRequest, size_t length)
71561729d93SAxel Dörfler {
71661729d93SAxel Dörfler 	switch (option) {
71761729d93SAxel Dörfler 		case SIOCSIFFLAGS:
71861729d93SAxel Dörfler 		{
719e8802e49SAxel Dörfler 			if (length != sizeof(ifreq))
720e8802e49SAxel Dörfler 				return B_BAD_VALUE;
721e8802e49SAxel Dörfler 
72261729d93SAxel Dörfler 			uint32 requestFlags = request.ifr_flags;
72361729d93SAxel Dörfler 			uint32 oldFlags = flags;
72461729d93SAxel Dörfler 			status_t status = B_OK;
72561729d93SAxel Dörfler 
72661729d93SAxel Dörfler 			request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST);
72761729d93SAxel Dörfler 
72861729d93SAxel Dörfler 			if ((requestFlags & IFF_UP) != (flags & IFF_UP)) {
72961729d93SAxel Dörfler 				if ((requestFlags & IFF_UP) != 0)
73061729d93SAxel Dörfler 					status = _SetUp();
73161729d93SAxel Dörfler 				else
7322b1c0755SAxel Dörfler 					SetDown();
73361729d93SAxel Dörfler 			}
73461729d93SAxel Dörfler 
73561729d93SAxel Dörfler 			if (status == B_OK) {
73661729d93SAxel Dörfler 				// TODO: maybe allow deleting IFF_BROADCAST on the interface
73761729d93SAxel Dörfler 				// level?
73861729d93SAxel Dörfler 				flags &= IFF_UP | IFF_LINK | IFF_BROADCAST;
73961729d93SAxel Dörfler 				flags |= request.ifr_flags;
74061729d93SAxel Dörfler 			}
74161729d93SAxel Dörfler 
742*e78fea43SAxel Dörfler 			if (oldFlags != flags) {
743*e78fea43SAxel Dörfler 				TRACE("Interface %p: flags changed from %" B_PRIx32 " to %"
744*e78fea43SAxel Dörfler 					B_PRIx32 "\n", this, oldFlags, flags);
74561729d93SAxel Dörfler 				notify_interface_changed(this, oldFlags, flags);
746*e78fea43SAxel Dörfler 			}
74761729d93SAxel Dörfler 
74861729d93SAxel Dörfler 			return status;
74961729d93SAxel Dörfler 		}
75061729d93SAxel Dörfler 
7512b1c0755SAxel Dörfler 		case B_SOCKET_SET_ALIAS:
7529d771afbSAxel Dörfler 		{
753e8802e49SAxel Dörfler 			if (length != sizeof(ifaliasreq))
754e8802e49SAxel Dörfler 				return B_BAD_VALUE;
755e8802e49SAxel Dörfler 
7569d771afbSAxel Dörfler 			RecursiveLocker locker(fLock);
7579d771afbSAxel Dörfler 
7589d771afbSAxel Dörfler 			ifaliasreq aliasRequest;
7599d771afbSAxel Dörfler 			if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq))
7609d771afbSAxel Dörfler 					!= B_OK)
7619d771afbSAxel Dörfler 				return B_BAD_ADDRESS;
7629d771afbSAxel Dörfler 
763910ffb32SAxel Dörfler 			InterfaceAddress* address = NULL;
764910ffb32SAxel Dörfler 			if (aliasRequest.ifra_index < 0) {
765910ffb32SAxel Dörfler 				if (!domain->address_module->is_empty_address(
766910ffb32SAxel Dörfler 						(const sockaddr*)&aliasRequest.ifra_addr, false)) {
767910ffb32SAxel Dörfler 					// Find first address that matches the local address
768910ffb32SAxel Dörfler 					address = AddressForLocal(domain,
769910ffb32SAxel Dörfler 						(const sockaddr*)&aliasRequest.ifra_addr);
770910ffb32SAxel Dörfler 				}
771910ffb32SAxel Dörfler 				if (address == NULL) {
772910ffb32SAxel Dörfler 					// Find first address for family
773910ffb32SAxel Dörfler 					address = FirstForFamily(domain->family);
774910ffb32SAxel Dörfler 				}
775a271028eSAxel Dörfler 				if (address == NULL) {
776a271028eSAxel Dörfler 					// Create new on the fly
777a271028eSAxel Dörfler 					address = new(std::nothrow) InterfaceAddress(this, domain);
778a271028eSAxel Dörfler 					if (address == NULL)
779a271028eSAxel Dörfler 						return B_NO_MEMORY;
780a271028eSAxel Dörfler 
781a271028eSAxel Dörfler 					status_t status = AddAddress(address);
782095f97a6SAxel Dörfler 					if (status != B_OK) {
783095f97a6SAxel Dörfler 						delete address;
784a271028eSAxel Dörfler 						return status;
785095f97a6SAxel Dörfler 					}
786a271028eSAxel Dörfler 
787a271028eSAxel Dörfler 					// Note, even if setting the address failed, the empty
788a271028eSAxel Dörfler 					// address added here will still be added to the interface.
7898dcde8b1SAxel Dörfler 					address->AcquireReference();
790a271028eSAxel Dörfler 				}
791910ffb32SAxel Dörfler 			} else
792910ffb32SAxel Dörfler 				address = AddressAt(aliasRequest.ifra_index);
793910ffb32SAxel Dörfler 
7949d771afbSAxel Dörfler 			if (address == NULL)
7959d771afbSAxel Dörfler 				return B_BAD_VALUE;
7969d771afbSAxel Dörfler 
7979d771afbSAxel Dörfler 			status_t status = B_OK;
7989d771afbSAxel Dörfler 
7999d771afbSAxel Dörfler 			if (!domain->address_module->equal_addresses(
8009d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_addr, address->local)) {
8019d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address, SIOCSIFADDR,
8029d771afbSAxel Dörfler 					address->local, (sockaddr*)&aliasRequest.ifra_addr);
8039d771afbSAxel Dörfler 			}
8049d771afbSAxel Dörfler 
8059d771afbSAxel Dörfler 			if (status == B_OK && !domain->address_module->equal_addresses(
806910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_mask, address->mask)
807910ffb32SAxel Dörfler 				&& !domain->address_module->is_empty_address(
808910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_mask, false)) {
8099d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address, SIOCSIFNETMASK,
8109d771afbSAxel Dörfler 					address->mask, (sockaddr*)&aliasRequest.ifra_mask);
8119d771afbSAxel Dörfler 			}
8129d771afbSAxel Dörfler 
8139d771afbSAxel Dörfler 			if (status == B_OK && !domain->address_module->equal_addresses(
8149d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination,
815910ffb32SAxel Dörfler 					address->destination)
816910ffb32SAxel Dörfler 				&& !domain->address_module->is_empty_address(
817910ffb32SAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination, false)) {
8189d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address,
8199d771afbSAxel Dörfler 					(domain->address_module->flags
8209d771afbSAxel Dörfler 						& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0
8219d771afbSAxel Dörfler 							? SIOCSIFBRDADDR : SIOCSIFDSTADDR,
8229d771afbSAxel Dörfler 					address->destination,
8239d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination);
8249d771afbSAxel Dörfler 			}
8259d771afbSAxel Dörfler 
8269d771afbSAxel Dörfler 			address->ReleaseReference();
8279d771afbSAxel Dörfler 			return status;
8289d771afbSAxel Dörfler 		}
8299d771afbSAxel Dörfler 
83061729d93SAxel Dörfler 		case SIOCSIFADDR:
83161729d93SAxel Dörfler 		case SIOCSIFNETMASK:
83261729d93SAxel Dörfler 		case SIOCSIFBRDADDR:
83361729d93SAxel Dörfler 		case SIOCSIFDSTADDR:
83461729d93SAxel Dörfler 		case SIOCDIFADDR:
83561729d93SAxel Dörfler 		{
836e8802e49SAxel Dörfler 			if (length != sizeof(ifreq))
837e8802e49SAxel Dörfler 				return B_BAD_VALUE;
838e8802e49SAxel Dörfler 
83961729d93SAxel Dörfler 			RecursiveLocker locker(fLock);
84061729d93SAxel Dörfler 
84161729d93SAxel Dörfler 			InterfaceAddress* address = NULL;
84261729d93SAxel Dörfler 			sockaddr_storage newAddress;
84361729d93SAxel Dörfler 
84461729d93SAxel Dörfler 			size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr));
84561729d93SAxel Dörfler 			if (size > sizeof(sockaddr_storage))
84661729d93SAxel Dörfler 				size = sizeof(sockaddr_storage);
84761729d93SAxel Dörfler 
84861729d93SAxel Dörfler 			if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK)
84961729d93SAxel Dörfler 				return B_BAD_ADDRESS;
85061729d93SAxel Dörfler 
85161729d93SAxel Dörfler 			if (option == SIOCDIFADDR) {
85261729d93SAxel Dörfler 				// Find referring address - we can't use the hash, as another
85361729d93SAxel Dörfler 				// interface might use the same address.
85461729d93SAxel Dörfler 				AddressList::Iterator iterator = fAddresses.GetIterator();
85561729d93SAxel Dörfler 				while ((address = iterator.Next()) != NULL) {
85661729d93SAxel Dörfler 					if (address->domain == domain
85761729d93SAxel Dörfler 						&& domain->address_module->equal_addresses(
85861729d93SAxel Dörfler 							address->local, (sockaddr*)&newAddress))
85961729d93SAxel Dörfler 						break;
86061729d93SAxel Dörfler 				}
86161729d93SAxel Dörfler 
86261729d93SAxel Dörfler 				if (address == NULL)
86361729d93SAxel Dörfler 					return B_BAD_VALUE;
86478abd727SAxel Dörfler 			} else {
86578abd727SAxel Dörfler 				// Just use the first address for this family
86678abd727SAxel Dörfler 				address = _FirstForFamily(domain->family);
86778abd727SAxel Dörfler 				if (address == NULL) {
86878abd727SAxel Dörfler 					// Create new on the fly
86978abd727SAxel Dörfler 					address = new(std::nothrow) InterfaceAddress(this, domain);
87078abd727SAxel Dörfler 					if (address == NULL)
87178abd727SAxel Dörfler 						return B_NO_MEMORY;
87278abd727SAxel Dörfler 
87378abd727SAxel Dörfler 					status_t status = AddAddress(address);
874095f97a6SAxel Dörfler 					if (status != B_OK) {
875095f97a6SAxel Dörfler 						delete address;
87678abd727SAxel Dörfler 						return status;
877095f97a6SAxel Dörfler 					}
87878abd727SAxel Dörfler 
87978abd727SAxel Dörfler 					// Note, even if setting the address failed, the empty
88078abd727SAxel Dörfler 					// address added here will still be added to the interface.
88178abd727SAxel Dörfler 				}
88278abd727SAxel Dörfler 			}
88361729d93SAxel Dörfler 
8849d771afbSAxel Dörfler 			return _ChangeAddress(locker, address, option,
8859d771afbSAxel Dörfler 				*address->AddressFor(option),
88661729d93SAxel Dörfler 				option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL);
88761729d93SAxel Dörfler 		}
88861729d93SAxel Dörfler 
88961729d93SAxel Dörfler 		default:
89061729d93SAxel Dörfler 			// pass the request into the datalink protocol stack
89161729d93SAxel Dörfler 			domain_datalink* datalink = DomainDatalink(domain->family);
89261729d93SAxel Dörfler 			if (datalink->first_info != NULL) {
89361729d93SAxel Dörfler 				return datalink->first_info->control(
89461729d93SAxel Dörfler 					datalink->first_protocol, option, userRequest, length);
89561729d93SAxel Dörfler 			}
89661729d93SAxel Dörfler 			break;
89761729d93SAxel Dörfler 	}
89861729d93SAxel Dörfler 
89961729d93SAxel Dörfler 	return B_BAD_VALUE;
90061729d93SAxel Dörfler }
90161729d93SAxel Dörfler 
90261729d93SAxel Dörfler 
9032b1c0755SAxel Dörfler void
9042b1c0755SAxel Dörfler Interface::SetDown()
9052b1c0755SAxel Dörfler {
9062b1c0755SAxel Dörfler 	if ((flags & IFF_UP) == 0)
9072b1c0755SAxel Dörfler 		return;
9082b1c0755SAxel Dörfler 
9092b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
9102b1c0755SAxel Dörfler 
9112b1c0755SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
9122b1c0755SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
9132b1c0755SAxel Dörfler 		datalink->first_info->interface_down(datalink->first_protocol);
9142b1c0755SAxel Dörfler 	}
9152b1c0755SAxel Dörfler 
9162b1c0755SAxel Dörfler 	flags &= ~IFF_UP;
9172b1c0755SAxel Dörfler }
9182b1c0755SAxel Dörfler 
9192b1c0755SAxel Dörfler 
9202b1c0755SAxel Dörfler /*!	Called when a device lost its IFF_UP status. We will invalidate all
9212b1c0755SAxel Dörfler 	interface routes here.
9222b1c0755SAxel Dörfler */
9232b1c0755SAxel Dörfler void
9242b1c0755SAxel Dörfler Interface::WentDown()
9252b1c0755SAxel Dörfler {
926ed18d7cfSAxel Dörfler 	TRACE("Interface %p: went down\n", this);
927ed18d7cfSAxel Dörfler 
9282b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
9292b1c0755SAxel Dörfler 
9302b1c0755SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
9312b1c0755SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
9322b1c0755SAxel Dörfler 		if (address->domain != NULL)
9332b1c0755SAxel Dörfler 			invalidate_routes(address->domain, this);
9342b1c0755SAxel Dörfler 	}
9352b1c0755SAxel Dörfler }
9362b1c0755SAxel Dörfler 
9372b1c0755SAxel Dörfler 
93861729d93SAxel Dörfler status_t
93961729d93SAxel Dörfler Interface::CreateDomainDatalinkIfNeeded(net_domain* domain)
94061729d93SAxel Dörfler {
94161729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
94261729d93SAxel Dörfler 
94361729d93SAxel Dörfler 	if (fDatalinkTable.Lookup(domain->family) != NULL)
94461729d93SAxel Dörfler 		return B_OK;
94561729d93SAxel Dörfler 
94661729d93SAxel Dörfler 	TRACE("Interface %p: create domain datalink for domain %p\n", this, domain);
94761729d93SAxel Dörfler 
94861729d93SAxel Dörfler 	domain_datalink* datalink = new(std::nothrow) domain_datalink;
94961729d93SAxel Dörfler 	if (datalink == NULL)
95061729d93SAxel Dörfler 		return B_NO_MEMORY;
95161729d93SAxel Dörfler 
952ed18d7cfSAxel Dörfler 	datalink->first_protocol = NULL;
953ed18d7cfSAxel Dörfler 	datalink->first_info = NULL;
95461729d93SAxel Dörfler 	datalink->domain = domain;
95561729d93SAxel Dörfler 
95661729d93SAxel Dörfler 	// setup direct route for bound devices
95761729d93SAxel Dörfler 	datalink->direct_route.destination = NULL;
95861729d93SAxel Dörfler 	datalink->direct_route.mask = NULL;
95961729d93SAxel Dörfler 	datalink->direct_route.gateway = NULL;
96061729d93SAxel Dörfler 	datalink->direct_route.flags = 0;
96161729d93SAxel Dörfler 	datalink->direct_route.mtu = 0;
96261729d93SAxel Dörfler 	datalink->direct_route.interface_address = &datalink->direct_address;
96361729d93SAxel Dörfler 	datalink->direct_route.ref_count = 1;
96461729d93SAxel Dörfler 		// make sure this doesn't get deleted accidently
96561729d93SAxel Dörfler 
96661729d93SAxel Dörfler 	// provide its link back to the interface
96761729d93SAxel Dörfler 	datalink->direct_address.local = NULL;
96861729d93SAxel Dörfler 	datalink->direct_address.destination = NULL;
96961729d93SAxel Dörfler 	datalink->direct_address.mask = NULL;
97061729d93SAxel Dörfler 	datalink->direct_address.domain = domain;
97161729d93SAxel Dörfler 	datalink->direct_address.interface = this;
9722b1c0755SAxel Dörfler 	datalink->direct_address.flags = IFAF_DIRECT_ADDRESS;
97361729d93SAxel Dörfler 
97461729d93SAxel Dörfler 	fDatalinkTable.Insert(datalink);
97561729d93SAxel Dörfler 
97661729d93SAxel Dörfler 	status_t status = get_domain_datalink_protocols(this, domain);
97761729d93SAxel Dörfler 	if (status == B_OK)
97861729d93SAxel Dörfler 		return B_OK;
97961729d93SAxel Dörfler 
98061729d93SAxel Dörfler 	fDatalinkTable.Remove(datalink);
98161729d93SAxel Dörfler 	delete datalink;
98261729d93SAxel Dörfler 
98361729d93SAxel Dörfler 	return status;
98461729d93SAxel Dörfler }
98561729d93SAxel Dörfler 
98661729d93SAxel Dörfler 
98761729d93SAxel Dörfler domain_datalink*
98861729d93SAxel Dörfler Interface::DomainDatalink(uint8 family)
98961729d93SAxel Dörfler {
99061729d93SAxel Dörfler 	// Note: domain datalinks cannot be removed while the interface is alive,
99161729d93SAxel Dörfler 	// since this would require us either to hold the lock while calling this
99261729d93SAxel Dörfler 	// function, or introduce reference counting for the domain_datalink
99361729d93SAxel Dörfler 	// structure.
99461729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
99561729d93SAxel Dörfler 	return fDatalinkTable.Lookup(family);
99661729d93SAxel Dörfler }
99761729d93SAxel Dörfler 
99861729d93SAxel Dörfler 
99961729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
100061729d93SAxel Dörfler 
100161729d93SAxel Dörfler 
100261729d93SAxel Dörfler void
100361729d93SAxel Dörfler Interface::Dump() const
100461729d93SAxel Dörfler {
100561729d93SAxel Dörfler 	kprintf("name:                %s\n", name);
100661729d93SAxel Dörfler 	kprintf("device:              %p\n", device);
100761729d93SAxel Dörfler 	kprintf("device_interface:    %p\n", fDeviceInterface);
100861729d93SAxel Dörfler 	kprintf("index:               %" B_PRIu32 "\n", index);
100961729d93SAxel Dörfler 	kprintf("flags:               %#" B_PRIx32 "\n", flags);
101061729d93SAxel Dörfler 	kprintf("type:                %u\n", type);
101161729d93SAxel Dörfler 	kprintf("mtu:                 %" B_PRIu32 "\n", mtu);
101261729d93SAxel Dörfler 	kprintf("metric:              %" B_PRIu32 "\n", metric);
1013ed18d7cfSAxel Dörfler 	kprintf("ref count:           %" B_PRId32 "\n", CountReferences());
101461729d93SAxel Dörfler 
101561729d93SAxel Dörfler 	kprintf("datalink protocols:\n");
101661729d93SAxel Dörfler 
101761729d93SAxel Dörfler 	DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator();
101861729d93SAxel Dörfler 	size_t i = 0;
101961729d93SAxel Dörfler 	while (domain_datalink* datalink = datalinkIterator.Next()) {
102061729d93SAxel Dörfler 		kprintf("%2zu. domain:          %p\n", ++i, datalink->domain);
102161729d93SAxel Dörfler 		kprintf("    first_protocol:  %p\n", datalink->first_protocol);
102261729d93SAxel Dörfler 		kprintf("    first_info:      %p\n", datalink->first_info);
102361729d93SAxel Dörfler 		kprintf("    direct_route:    %p\n", &datalink->direct_route);
102461729d93SAxel Dörfler 	}
102561729d93SAxel Dörfler 
102661729d93SAxel Dörfler 	kprintf("addresses:\n");
102761729d93SAxel Dörfler 
102861729d93SAxel Dörfler 	AddressList::ConstIterator iterator = fAddresses.GetIterator();
102961729d93SAxel Dörfler 	i = 0;
103061729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
103161729d93SAxel Dörfler 		address->Dump(++i, true);
103261729d93SAxel Dörfler 	}
103361729d93SAxel Dörfler }
103461729d93SAxel Dörfler 
103561729d93SAxel Dörfler 
103661729d93SAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
103761729d93SAxel Dörfler 
103861729d93SAxel Dörfler 
103961729d93SAxel Dörfler status_t
104061729d93SAxel Dörfler Interface::_SetUp()
104161729d93SAxel Dörfler {
104261729d93SAxel Dörfler 	status_t status = up_device_interface(fDeviceInterface);
104361729d93SAxel Dörfler 	if (status != B_OK)
104461729d93SAxel Dörfler 		return status;
104561729d93SAxel Dörfler 
10462b1c0755SAxel Dörfler 	// Propagate flag to all datalink protocols
104761729d93SAxel Dörfler 
104861729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
104961729d93SAxel Dörfler 
105061729d93SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
105161729d93SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
105261729d93SAxel Dörfler 		status = datalink->first_info->interface_up(datalink->first_protocol);
105361729d93SAxel Dörfler 		if (status != B_OK) {
105461729d93SAxel Dörfler 			// Revert "up" status
105561729d93SAxel Dörfler 			DatalinkTable::Iterator secondIterator
105661729d93SAxel Dörfler 				= fDatalinkTable.GetIterator();
105761729d93SAxel Dörfler 			while (secondIterator.HasNext()) {
105861729d93SAxel Dörfler 				domain_datalink* secondDatalink = secondIterator.Next();
105961729d93SAxel Dörfler 				if (secondDatalink == NULL || secondDatalink == datalink)
1060c22d69bfSAxel Dörfler 					break;
1061c22d69bfSAxel Dörfler 
106261729d93SAxel Dörfler 				secondDatalink->first_info->interface_down(
106361729d93SAxel Dörfler 					secondDatalink->first_protocol);
106461729d93SAxel Dörfler 			}
106561729d93SAxel Dörfler 
106661729d93SAxel Dörfler 			down_device_interface(fDeviceInterface);
106761729d93SAxel Dörfler 			return status;
106861729d93SAxel Dörfler 		}
106961729d93SAxel Dörfler 	}
107061729d93SAxel Dörfler 
10712b1c0755SAxel Dörfler 	// Add default routes for the existing addresses
10722b1c0755SAxel Dörfler 
10732b1c0755SAxel Dörfler 	AddressList::Iterator addressIterator = fAddresses.GetIterator();
10742b1c0755SAxel Dörfler 	while (InterfaceAddress* address = addressIterator.Next()) {
10752b1c0755SAxel Dörfler 		address->AddDefaultRoutes(SIOCSIFADDR);
10762b1c0755SAxel Dörfler 	}
10772b1c0755SAxel Dörfler 
107861729d93SAxel Dörfler 	flags |= IFF_UP;
107961729d93SAxel Dörfler 	return B_OK;
108061729d93SAxel Dörfler }
108161729d93SAxel Dörfler 
108261729d93SAxel Dörfler 
108361729d93SAxel Dörfler InterfaceAddress*
108461729d93SAxel Dörfler Interface::_FirstForFamily(int family)
108561729d93SAxel Dörfler {
108661729d93SAxel Dörfler 	ASSERT_LOCKED_RECURSIVE(&fLock);
108761729d93SAxel Dörfler 
108861729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
108961729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
109061729d93SAxel Dörfler 		if (address->domain != NULL && address->domain->family == family)
109161729d93SAxel Dörfler 			return address;
109261729d93SAxel Dörfler 	}
109361729d93SAxel Dörfler 
109461729d93SAxel Dörfler 	return NULL;
109561729d93SAxel Dörfler }
109661729d93SAxel Dörfler 
109761729d93SAxel Dörfler 
10989d771afbSAxel Dörfler status_t
10999d771afbSAxel Dörfler Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address,
1100b0cf274aSAxel Dörfler 	int32 option, const sockaddr* originalAddress,
1101b0cf274aSAxel Dörfler 	const sockaddr* requestedAddress)
11029d771afbSAxel Dörfler {
1103b0cf274aSAxel Dörfler 	// Copy old address
11049d771afbSAxel Dörfler 	sockaddr_storage oldAddress;
11059d771afbSAxel Dörfler 	if (address->domain->address_module->set_to((sockaddr*)&oldAddress,
11069d771afbSAxel Dörfler 			originalAddress) != B_OK)
11079d771afbSAxel Dörfler 		oldAddress.ss_family = AF_UNSPEC;
11089d771afbSAxel Dörfler 
1109b0cf274aSAxel Dörfler 	// Copy new address (this also makes sure that sockaddr::sa_len is set
1110b0cf274aSAxel Dörfler 	// correctly)
1111b0cf274aSAxel Dörfler 	sockaddr_storage newAddress;
1112b0cf274aSAxel Dörfler 	if (address->domain->address_module->set_to((sockaddr*)&newAddress,
1113b0cf274aSAxel Dörfler 			requestedAddress) != B_OK)
1114b0cf274aSAxel Dörfler 		newAddress.ss_family = AF_UNSPEC;
1115b0cf274aSAxel Dörfler 
11166b1e1488SAxel Dörfler 	// Test if anything changed for real
1117b0cf274aSAxel Dörfler 	if (address->domain->address_module->equal_addresses(
1118b0cf274aSAxel Dörfler 			(sockaddr*)&oldAddress, (sockaddr*)&newAddress)) {
11196b1e1488SAxel Dörfler 		// Nothing to do
1120b0cf274aSAxel Dörfler 		TRACE("  option %" B_PRId32 " addresses are equal!\n", option);
11216b1e1488SAxel Dörfler 		return B_OK;
11226b1e1488SAxel Dörfler 	}
11236b1e1488SAxel Dörfler 
11249d771afbSAxel Dörfler 	// TODO: mark this address busy or call while holding the lock!
11259d771afbSAxel Dörfler 	address->AcquireReference();
11269d771afbSAxel Dörfler 	locker.Unlock();
11279d771afbSAxel Dörfler 
11289d771afbSAxel Dörfler 	domain_datalink* datalink = DomainDatalink(address->domain);
11299d771afbSAxel Dörfler 	status_t status = datalink->first_protocol->module->change_address(
11309d771afbSAxel Dörfler 		datalink->first_protocol, address, option,
11319d771afbSAxel Dörfler 		oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL,
1132b0cf274aSAxel Dörfler 		newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL);
11339d771afbSAxel Dörfler 
11349d771afbSAxel Dörfler 	locker.Lock();
11359d771afbSAxel Dörfler 	address->ReleaseReference();
11369d771afbSAxel Dörfler 	return status;
11379d771afbSAxel Dörfler }
11389d771afbSAxel Dörfler 
11399d771afbSAxel Dörfler 
114061729d93SAxel Dörfler // #pragma mark -
114161729d93SAxel Dörfler 
114261729d93SAxel Dörfler 
114361729d93SAxel Dörfler /*!	Searches for a specific interface by name.
114461729d93SAxel Dörfler 	You need to have the interface list's lock hold when calling this function.
114561729d93SAxel Dörfler */
114661729d93SAxel Dörfler static struct Interface*
114761729d93SAxel Dörfler find_interface(const char* name)
114861729d93SAxel Dörfler {
114961729d93SAxel Dörfler 	ASSERT_LOCKED_MUTEX(&sLock);
115061729d93SAxel Dörfler 
115161729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
115261729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1153c22d69bfSAxel Dörfler 		if (!strcmp(interface->name, name))
1154c22d69bfSAxel Dörfler 			return interface;
1155c22d69bfSAxel Dörfler 	}
1156c22d69bfSAxel Dörfler 
1157c22d69bfSAxel Dörfler 	return NULL;
1158c22d69bfSAxel Dörfler }
1159c22d69bfSAxel Dörfler 
1160c22d69bfSAxel Dörfler 
116161729d93SAxel Dörfler /*!	Searches for a specific interface by index.
116261729d93SAxel Dörfler 	You need to have the interface list's lock hold when calling this function.
1163c22d69bfSAxel Dörfler */
116461729d93SAxel Dörfler static struct Interface*
116561729d93SAxel Dörfler find_interface(uint32 index)
1166c22d69bfSAxel Dörfler {
116761729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
116861729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1169c22d69bfSAxel Dörfler 		if (interface->index == index)
1170c22d69bfSAxel Dörfler 			return interface;
1171c22d69bfSAxel Dörfler 	}
1172c22d69bfSAxel Dörfler 
1173c22d69bfSAxel Dörfler 	return NULL;
1174c22d69bfSAxel Dörfler }
1175c22d69bfSAxel Dörfler 
1176c22d69bfSAxel Dörfler 
117761729d93SAxel Dörfler // #pragma mark -
117861729d93SAxel Dörfler 
117961729d93SAxel Dörfler 
118061729d93SAxel Dörfler status_t
118161729d93SAxel Dörfler add_interface(const char* name, net_domain_private* domain,
118261729d93SAxel Dörfler 	const ifaliasreq& request, net_device_interface* deviceInterface)
118361729d93SAxel Dörfler {
118461729d93SAxel Dörfler 	MutexLocker locker(sLock);
118561729d93SAxel Dörfler 
118661729d93SAxel Dörfler 	if (find_interface(name) != NULL)
118761729d93SAxel Dörfler 		return B_NAME_IN_USE;
118861729d93SAxel Dörfler 
118961729d93SAxel Dörfler 	Interface* interface
119061729d93SAxel Dörfler 		= new(std::nothrow) Interface(name, deviceInterface);
1191c22d69bfSAxel Dörfler 	if (interface == NULL)
1192c22d69bfSAxel Dörfler 		return B_NO_MEMORY;
1193c22d69bfSAxel Dörfler 
119461729d93SAxel Dörfler 	sInterfaces.Add(interface);
119561729d93SAxel Dörfler 	interface->AcquireReference();
119661729d93SAxel Dörfler 		// We need another reference to be able to use the interface without
119761729d93SAxel Dörfler 		// holding sLock.
1198c22d69bfSAxel Dörfler 
119961729d93SAxel Dörfler 	locker.Unlock();
1200c22d69bfSAxel Dörfler 
120161729d93SAxel Dörfler 	notify_interface_added(interface);
120261729d93SAxel Dörfler 	add_interface_address(interface, domain, request);
1203c22d69bfSAxel Dörfler 
120461729d93SAxel Dörfler 	interface->ReleaseReference();
120527e0dea9SAxel Dörfler 
1206c22d69bfSAxel Dörfler 	return B_OK;
1207c22d69bfSAxel Dörfler }
1208c22d69bfSAxel Dörfler 
1209c22d69bfSAxel Dörfler 
121061729d93SAxel Dörfler /*!	Removes the interface from the list, and puts the stack's reference to it.
121161729d93SAxel Dörfler */
12127aa2819cSAxel Dörfler void
121361729d93SAxel Dörfler remove_interface(Interface* interface)
1214c64feccaSHugo Santos {
12152b1c0755SAxel Dörfler 	interface->SetDown();
12162b1c0755SAxel Dörfler 	interface->RemoveAddresses();
1217c64feccaSHugo Santos 
12182b1c0755SAxel Dörfler 	MutexLocker locker(sLock);
12192b1c0755SAxel Dörfler 	sInterfaces.Remove(interface);
12202b1c0755SAxel Dörfler 	locker.Unlock();
1221f6d219a1SAxel Dörfler 
122261729d93SAxel Dörfler 	notify_interface_removed(interface);
1223c22d69bfSAxel Dörfler 
12242b1c0755SAxel Dörfler 	interface->ReleaseReference();
12257aa2819cSAxel Dörfler }
12267aa2819cSAxel Dörfler 
12277aa2819cSAxel Dörfler 
12287aa2819cSAxel Dörfler /*!	This is called whenever a device interface is being removed. We will get
12297aa2819cSAxel Dörfler 	the corresponding Interface, and remove it.
12307aa2819cSAxel Dörfler */
12317aa2819cSAxel Dörfler void
12327aa2819cSAxel Dörfler interface_removed_device_interface(net_device_interface* deviceInterface)
12337aa2819cSAxel Dörfler {
12347aa2819cSAxel Dörfler 	MutexLocker locker(sLock);
12357aa2819cSAxel Dörfler 
12367aa2819cSAxel Dörfler 	Interface* interface = find_interface(deviceInterface->device->name);
12377aa2819cSAxel Dörfler 	if (interface != NULL)
12387aa2819cSAxel Dörfler 		remove_interface(interface);
1239c22d69bfSAxel Dörfler }
1240c22d69bfSAxel Dörfler 
1241c22d69bfSAxel Dörfler 
124261729d93SAxel Dörfler status_t
124361729d93SAxel Dörfler add_interface_address(Interface* interface, net_domain_private* domain,
124461729d93SAxel Dörfler 	const ifaliasreq& request)
1245c22d69bfSAxel Dörfler {
124661729d93SAxel Dörfler 	// Make sure the family of the provided addresses is valid
124761729d93SAxel Dörfler 	if ((request.ifra_addr.ss_family != domain->family
124861729d93SAxel Dörfler 			&& request.ifra_addr.ss_family != AF_UNSPEC)
124961729d93SAxel Dörfler 		|| (request.ifra_mask.ss_family != domain->family
125061729d93SAxel Dörfler 			&& request.ifra_mask.ss_family != AF_UNSPEC)
125161729d93SAxel Dörfler 		|| (request.ifra_broadaddr.ss_family != domain->family
125261729d93SAxel Dörfler 			&& request.ifra_broadaddr.ss_family != AF_UNSPEC))
125361729d93SAxel Dörfler 		return B_BAD_VALUE;
1254c22d69bfSAxel Dörfler 
125561729d93SAxel Dörfler 	RecursiveLocker locker(interface->Lock());
125661729d93SAxel Dörfler 
125761729d93SAxel Dörfler 	InterfaceAddress* address
125861729d93SAxel Dörfler 		= new(std::nothrow) InterfaceAddress(interface, domain);
125961729d93SAxel Dörfler 	if (address == NULL)
126061729d93SAxel Dörfler 		return B_NO_MEMORY;
126161729d93SAxel Dörfler 
126261729d93SAxel Dörfler 	status_t status = address->SetTo(request);
126361729d93SAxel Dörfler 	if (status == B_OK)
126461729d93SAxel Dörfler 		status = interface->CreateDomainDatalinkIfNeeded(domain);
126561729d93SAxel Dörfler 	if (status == B_OK)
126661729d93SAxel Dörfler 		status = interface->AddAddress(address);
126761729d93SAxel Dörfler 
126861729d93SAxel Dörfler 	if (status == B_OK && address->local != NULL) {
126961729d93SAxel Dörfler 		// update the datalink protocols
127061729d93SAxel Dörfler 		domain_datalink* datalink = interface->DomainDatalink(domain->family);
127161729d93SAxel Dörfler 
127261729d93SAxel Dörfler 		status = datalink->first_protocol->module->change_address(
127361729d93SAxel Dörfler 			datalink->first_protocol, address, SIOCAIFADDR, NULL,
127461729d93SAxel Dörfler 			address->local);
127561729d93SAxel Dörfler 		if (status != B_OK)
127661729d93SAxel Dörfler 			interface->RemoveAddress(address);
127761729d93SAxel Dörfler 	}
127861729d93SAxel Dörfler 	if (status == B_OK)
127961729d93SAxel Dörfler 		notify_interface_changed(interface);
128061729d93SAxel Dörfler 	else
128161729d93SAxel Dörfler 		delete address;
128261729d93SAxel Dörfler 
128361729d93SAxel Dörfler 	return status;
128461729d93SAxel Dörfler }
128561729d93SAxel Dörfler 
128661729d93SAxel Dörfler 
128761729d93SAxel Dörfler status_t
128861729d93SAxel Dörfler update_interface_address(InterfaceAddress* interfaceAddress, int32 option,
128961729d93SAxel Dörfler 	const sockaddr* oldAddress, const sockaddr* newAddress)
129061729d93SAxel Dörfler {
1291b0cf274aSAxel Dörfler 	TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress "
1292b0cf274aSAxel Dörfler 		"%s)\n", __FUNCTION__, interfaceAddress, option,
1293b0cf274aSAxel Dörfler 		AddressString(interfaceAddress->domain, oldAddress).Data(),
1294b0cf274aSAxel Dörfler 		AddressString(interfaceAddress->domain, newAddress).Data());
1295b0cf274aSAxel Dörfler 
129661729d93SAxel Dörfler 	MutexLocker locker(sHashLock);
129761729d93SAxel Dörfler 
129861729d93SAxel Dörfler 	// set logical interface address
129961729d93SAxel Dörfler 	sockaddr** _address = interfaceAddress->AddressFor(option);
130061729d93SAxel Dörfler 	if (_address == NULL)
130161729d93SAxel Dörfler 		return B_BAD_VALUE;
130261729d93SAxel Dörfler 
13032b1c0755SAxel Dörfler 	Interface* interface = (Interface*)interfaceAddress->interface;
13042b1c0755SAxel Dörfler 
13052b1c0755SAxel Dörfler 	interfaceAddress->RemoveDefaultRoutes(option);
13062b1c0755SAxel Dörfler 
13072b1c0755SAxel Dörfler 	if (option == SIOCDIFADDR) {
13082b1c0755SAxel Dörfler 		// Remove address, and release its reference (causing our caller to
13092b1c0755SAxel Dörfler 		// delete it)
13102b1c0755SAxel Dörfler 		locker.Unlock();
13112b1c0755SAxel Dörfler 
13122b1c0755SAxel Dörfler 		invalidate_routes(interfaceAddress);
13132b1c0755SAxel Dörfler 
13142b1c0755SAxel Dörfler 		interface->RemoveAddress(interfaceAddress);
13152b1c0755SAxel Dörfler 		interfaceAddress->ReleaseReference();
13162b1c0755SAxel Dörfler 		return B_OK;
13172b1c0755SAxel Dörfler 	}
13182b1c0755SAxel Dörfler 
131961729d93SAxel Dörfler 	sAddressTable.Remove(interfaceAddress);
132061729d93SAxel Dörfler 
132161729d93SAxel Dörfler 	// Copy new address over
132261729d93SAxel Dörfler 	status_t status = InterfaceAddress::Set(_address, newAddress);
132361729d93SAxel Dörfler 	if (status == B_OK) {
132461729d93SAxel Dörfler 		sockaddr* address = *_address;
132561729d93SAxel Dörfler 
13261ebd87f4SAxel Dörfler 		if (option == SIOCSIFADDR) {
132761729d93SAxel Dörfler 			// Reset netmask and broadcast addresses to defaults
132861729d93SAxel Dörfler 			net_domain* domain = interfaceAddress->domain;
132961729d93SAxel Dörfler 			sockaddr* netmask = NULL;
133061729d93SAxel Dörfler 			const sockaddr* oldNetmask = NULL;
133161729d93SAxel Dörfler 			if (option == SIOCSIFADDR) {
133261729d93SAxel Dörfler 				netmask = InterfaceAddress::Prepare(
133361729d93SAxel Dörfler 					&interfaceAddress->mask, address->sa_len);
133461729d93SAxel Dörfler 			} else {
133561729d93SAxel Dörfler 				oldNetmask = oldAddress;
133661729d93SAxel Dörfler 				netmask = interfaceAddress->mask;
133761729d93SAxel Dörfler 			}
133861729d93SAxel Dörfler 
133961729d93SAxel Dörfler 			// Reset the broadcast address if the address family has
134061729d93SAxel Dörfler 			// such
134161729d93SAxel Dörfler 			sockaddr* broadcast = NULL;
134261729d93SAxel Dörfler 			if ((domain->address_module->flags
134361729d93SAxel Dörfler 					& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) {
134461729d93SAxel Dörfler 				broadcast = InterfaceAddress::Prepare(
134561729d93SAxel Dörfler 					&interfaceAddress->destination, address->sa_len);
134661729d93SAxel Dörfler 			} else
134761729d93SAxel Dörfler 				InterfaceAddress::Set(&interfaceAddress->destination, NULL);
134861729d93SAxel Dörfler 
134961729d93SAxel Dörfler 			domain->address_module->set_to_defaults(netmask, broadcast,
135061729d93SAxel Dörfler 				interfaceAddress->local, oldNetmask);
135161729d93SAxel Dörfler 		}
135261729d93SAxel Dörfler 
13532b1c0755SAxel Dörfler 		interfaceAddress->AddDefaultRoutes(option);
13542b1c0755SAxel Dörfler 		notify_interface_changed(interface);
135561729d93SAxel Dörfler 	}
135661729d93SAxel Dörfler 
135761729d93SAxel Dörfler 	sAddressTable.Insert(interfaceAddress);
135861729d93SAxel Dörfler 	return status;
135961729d93SAxel Dörfler }
136061729d93SAxel Dörfler 
136161729d93SAxel Dörfler 
136261729d93SAxel Dörfler Interface*
136361729d93SAxel Dörfler get_interface(net_domain* domain, uint32 index)
136461729d93SAxel Dörfler {
136561729d93SAxel Dörfler 	MutexLocker locker(sLock);
136661729d93SAxel Dörfler 
1367ec4fb0f4SAxel Dörfler 	Interface* interface;
136861729d93SAxel Dörfler 	if (index == 0)
1369ec4fb0f4SAxel Dörfler 		interface = sInterfaces.First();
1370ec4fb0f4SAxel Dörfler 	else
1371ec4fb0f4SAxel Dörfler 		interface = find_interface(index);
1372c22d69bfSAxel Dörfler 	if (interface == NULL)
137361729d93SAxel Dörfler 		return NULL;
1374c22d69bfSAxel Dörfler 
137561729d93SAxel Dörfler 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
137661729d93SAxel Dörfler 		return NULL;
137761729d93SAxel Dörfler 
137861729d93SAxel Dörfler 	interface->AcquireReference();
1379c22d69bfSAxel Dörfler 	return interface;
1380c22d69bfSAxel Dörfler }
1381c22d69bfSAxel Dörfler 
138261729d93SAxel Dörfler 
138361729d93SAxel Dörfler Interface*
138461729d93SAxel Dörfler get_interface(net_domain* domain, const char* name)
138561729d93SAxel Dörfler {
138661729d93SAxel Dörfler 	MutexLocker locker(sLock);
138761729d93SAxel Dörfler 
138861729d93SAxel Dörfler 	Interface* interface = find_interface(name);
138961729d93SAxel Dörfler 	if (interface == NULL)
139061729d93SAxel Dörfler 		return NULL;
139161729d93SAxel Dörfler 
139261729d93SAxel Dörfler 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
139361729d93SAxel Dörfler 		return NULL;
139461729d93SAxel Dörfler 
139561729d93SAxel Dörfler 	interface->AcquireReference();
139661729d93SAxel Dörfler 	return interface;
139761729d93SAxel Dörfler }
139861729d93SAxel Dörfler 
139961729d93SAxel Dörfler 
140061729d93SAxel Dörfler Interface*
140161729d93SAxel Dörfler get_interface_for_device(net_domain* domain, uint32 index)
140261729d93SAxel Dörfler {
140361729d93SAxel Dörfler 	MutexLocker locker(sLock);
140461729d93SAxel Dörfler 
140561729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
140661729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
140761729d93SAxel Dörfler 		if (interface->device->index == index) {
140861729d93SAxel Dörfler 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
140961729d93SAxel Dörfler 				return NULL;
141061729d93SAxel Dörfler 
141161729d93SAxel Dörfler 			interface->AcquireReference();
141261729d93SAxel Dörfler 			return interface;
141361729d93SAxel Dörfler 		}
141461729d93SAxel Dörfler 	}
141561729d93SAxel Dörfler 
1416c22d69bfSAxel Dörfler 	return NULL;
1417c22d69bfSAxel Dörfler }
1418c22d69bfSAxel Dörfler 
1419c22d69bfSAxel Dörfler 
1420cd08b9f7SAxel Dörfler /*!	Returns a reference to an Interface that matches the given \a linkAddress.
1421cd08b9f7SAxel Dörfler 	The link address is checked against its hardware address, or its interface
1422cd08b9f7SAxel Dörfler 	name, or finally the interface index.
1423cd08b9f7SAxel Dörfler */
1424cd08b9f7SAxel Dörfler Interface*
1425cd08b9f7SAxel Dörfler get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress)
1426cd08b9f7SAxel Dörfler {
1427cd08b9f7SAxel Dörfler 	sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress;
1428cd08b9f7SAxel Dörfler 
1429cd08b9f7SAxel Dörfler 	MutexLocker locker(sLock);
1430cd08b9f7SAxel Dörfler 
1431cd08b9f7SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1432cd08b9f7SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1433cd08b9f7SAxel Dörfler 		// Test if the hardware address matches, or if the given interface
1434cd08b9f7SAxel Dörfler 		// matches, or if at least the index matches.
1435cd08b9f7SAxel Dörfler 		if ((linkAddress.sdl_alen == interface->device->address.length
1436cd08b9f7SAxel Dörfler 				&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
1437cd08b9f7SAxel Dörfler 					linkAddress.sdl_alen) == 0)
1438cd08b9f7SAxel Dörfler 			|| (linkAddress.sdl_nlen > 0
1439cd08b9f7SAxel Dörfler 				&& !strcmp(interface->name, (const char*)linkAddress.sdl_data))
1440cd08b9f7SAxel Dörfler 			|| (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0
1441cd08b9f7SAxel Dörfler 				&& linkAddress.sdl_index == interface->index)) {
1442cd08b9f7SAxel Dörfler 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
1443cd08b9f7SAxel Dörfler 				return NULL;
1444cd08b9f7SAxel Dörfler 
1445cd08b9f7SAxel Dörfler 			interface->AcquireReference();
1446cd08b9f7SAxel Dörfler 			return interface;
1447cd08b9f7SAxel Dörfler 		}
1448cd08b9f7SAxel Dörfler 	}
1449cd08b9f7SAxel Dörfler 
1450cd08b9f7SAxel Dörfler 	return NULL;
1451cd08b9f7SAxel Dörfler }
1452cd08b9f7SAxel Dörfler 
1453cd08b9f7SAxel Dörfler 
145461729d93SAxel Dörfler InterfaceAddress*
145561729d93SAxel Dörfler get_interface_address(const sockaddr* local)
1456c22d69bfSAxel Dörfler {
145761729d93SAxel Dörfler 	if (local->sa_family == AF_UNSPEC)
145861729d93SAxel Dörfler 		return NULL;
1459c22d69bfSAxel Dörfler 
146061729d93SAxel Dörfler 	MutexLocker locker(sHashLock);
1461c22d69bfSAxel Dörfler 
146261729d93SAxel Dörfler 	InterfaceAddress* address = sAddressTable.Lookup(local);
146361729d93SAxel Dörfler 	if (address == NULL)
146461729d93SAxel Dörfler 		return NULL;
1465c22d69bfSAxel Dörfler 
146661729d93SAxel Dörfler 	address->AcquireReference();
146761729d93SAxel Dörfler 	return address;
146861729d93SAxel Dörfler }
146961729d93SAxel Dörfler 
147061729d93SAxel Dörfler 
147161729d93SAxel Dörfler InterfaceAddress*
147261729d93SAxel Dörfler get_interface_address_for_destination(net_domain* domain,
1473cd08b9f7SAxel Dörfler 	const sockaddr* destination)
147461729d93SAxel Dörfler {
147561729d93SAxel Dörfler 	MutexLocker locker(sLock);
147661729d93SAxel Dörfler 
147761729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
147861729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
147961729d93SAxel Dörfler 		InterfaceAddress* address
148061729d93SAxel Dörfler 			= interface->AddressForDestination(domain, destination);
148161729d93SAxel Dörfler 		if (address != NULL)
148261729d93SAxel Dörfler 			return address;
148361729d93SAxel Dörfler 	}
148461729d93SAxel Dörfler 
148561729d93SAxel Dörfler 	return NULL;
148661729d93SAxel Dörfler }
148761729d93SAxel Dörfler 
148861729d93SAxel Dörfler 
1489cd08b9f7SAxel Dörfler /*!	Returns a reference to an InterfaceAddress of the specified \a domain that
1490cd08b9f7SAxel Dörfler 	belongs to the interface identified via \a linkAddress. Only the hardware
1491cd08b9f7SAxel Dörfler 	address is matched.
1492cd08b9f7SAxel Dörfler 
1493cd08b9f7SAxel Dörfler 	If \a unconfiguredOnly is set, the interface address must not yet be
1494cd08b9f7SAxel Dörfler 	configured, or must currently be in the process of being configured.
1495cd08b9f7SAxel Dörfler */
149661729d93SAxel Dörfler InterfaceAddress*
1497cd08b9f7SAxel Dörfler get_interface_address_for_link(net_domain* domain, const sockaddr* address,
1498cd08b9f7SAxel Dörfler 	bool unconfiguredOnly)
149961729d93SAxel Dörfler {
1500cd08b9f7SAxel Dörfler 	sockaddr_dl& linkAddress = *(sockaddr_dl*)address;
150161729d93SAxel Dörfler 
150261729d93SAxel Dörfler 	MutexLocker locker(sLock);
150361729d93SAxel Dörfler 
150461729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
150561729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1506cd08b9f7SAxel Dörfler 		// Test if the hardware address matches, or if the given interface
1507cd08b9f7SAxel Dörfler 		// matches, or if at least the index matches.
150861729d93SAxel Dörfler 		if (linkAddress.sdl_alen == interface->device->address.length
150961729d93SAxel Dörfler 			&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
151061729d93SAxel Dörfler 				linkAddress.sdl_alen) == 0) {
1511b0cf274aSAxel Dörfler 			TRACE("  %s matches\n", interface->name);
151261729d93SAxel Dörfler 			// link address matches
151361729d93SAxel Dörfler 			if (unconfiguredOnly)
151461729d93SAxel Dörfler 				return interface->FirstUnconfiguredForFamily(domain->family);
151561729d93SAxel Dörfler 
151661729d93SAxel Dörfler 			return interface->FirstForFamily(domain->family);
151761729d93SAxel Dörfler 		}
151861729d93SAxel Dörfler 	}
151961729d93SAxel Dörfler 
152061729d93SAxel Dörfler 	return NULL;
1521c22d69bfSAxel Dörfler }
1522c22d69bfSAxel Dörfler 
1523c22d69bfSAxel Dörfler 
1524c22d69bfSAxel Dörfler uint32
152561729d93SAxel Dörfler count_interfaces()
1526c22d69bfSAxel Dörfler {
152761729d93SAxel Dörfler 	MutexLocker locker(sLock);
1528c22d69bfSAxel Dörfler 
152961729d93SAxel Dörfler 	return sInterfaces.Count();
1530c22d69bfSAxel Dörfler }
1531c22d69bfSAxel Dörfler 
1532c22d69bfSAxel Dörfler 
15333c13a5f5SAxel Dörfler /*!	Dumps a list of all interfaces into the supplied userland buffer.
1534c22d69bfSAxel Dörfler 	If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
1535c22d69bfSAxel Dörfler 	returned.
1536c22d69bfSAxel Dörfler */
1537c22d69bfSAxel Dörfler status_t
153861729d93SAxel Dörfler list_interfaces(int family, void* _buffer, size_t* bufferSize)
1539c22d69bfSAxel Dörfler {
154061729d93SAxel Dörfler 	MutexLocker locker(sLock);
1541c22d69bfSAxel Dörfler 
1542409b1fc0SHugo Santos 	UserBuffer buffer(_buffer, *bufferSize);
1543c22d69bfSAxel Dörfler 
154461729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
154561729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1546715fed44SAxel Dörfler 		// Copy name
1547715fed44SAxel Dörfler 		buffer.Push(interface->name, IF_NAMESIZE);
1548c22d69bfSAxel Dörfler 
1549715fed44SAxel Dörfler 		// Copy address
155061729d93SAxel Dörfler 		InterfaceAddress* address = interface->FirstForFamily(family);
15511f9c8c45SAxel Dörfler 		size_t length = 0;
1552715fed44SAxel Dörfler 
155361729d93SAxel Dörfler 		if (address != NULL && address->local != NULL) {
1554715fed44SAxel Dörfler 			// Actual address
15551f9c8c45SAxel Dörfler 			buffer.Push(address->local, length = address->local->sa_len);
155661729d93SAxel Dörfler 		} else {
1557715fed44SAxel Dörfler 			// Empty address
15581f9c8c45SAxel Dörfler 			sockaddr empty;
15591f9c8c45SAxel Dörfler 			empty.sa_len = 2;
15601f9c8c45SAxel Dörfler 			empty.sa_family = AF_UNSPEC;
15611f9c8c45SAxel Dörfler 			buffer.Push(&empty, length = empty.sa_len);
1562715fed44SAxel Dörfler 		}
1563715fed44SAxel Dörfler 
156461729d93SAxel Dörfler 		if (address != NULL)
156561729d93SAxel Dörfler 			address->ReleaseReference();
156661729d93SAxel Dörfler 
15671f9c8c45SAxel Dörfler 		if (IF_NAMESIZE + length < sizeof(ifreq)) {
15681f9c8c45SAxel Dörfler 			// Make sure at least sizeof(ifreq) bytes are written for each
15691f9c8c45SAxel Dörfler 			// interface for compatibility with other platforms
15701f9c8c45SAxel Dörfler 			buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length);
15711f9c8c45SAxel Dörfler 		}
15721f9c8c45SAxel Dörfler 
15731f9c8c45SAxel Dörfler 		if (buffer.Status() != B_OK)
1574409b1fc0SHugo Santos 			return buffer.Status();
1575c22d69bfSAxel Dörfler 	}
1576c22d69bfSAxel Dörfler 
1577715fed44SAxel Dörfler 	*bufferSize = buffer.BytesConsumed();
1578c22d69bfSAxel Dörfler 	return B_OK;
1579c22d69bfSAxel Dörfler }
1580c22d69bfSAxel Dörfler 
1581c22d69bfSAxel Dörfler 
1582c22d69bfSAxel Dörfler //	#pragma mark -
1583c22d69bfSAxel Dörfler 
1584c22d69bfSAxel Dörfler 
1585c22d69bfSAxel Dörfler status_t
1586c22d69bfSAxel Dörfler init_interfaces()
1587c22d69bfSAxel Dörfler {
158861729d93SAxel Dörfler 	mutex_init(&sLock, "net interfaces");
158961729d93SAxel Dörfler 	mutex_init(&sHashLock, "net local addresses");
1590c22d69bfSAxel Dörfler 
159161729d93SAxel Dörfler 	new (&sInterfaces) InterfaceList;
159261729d93SAxel Dörfler 	new (&sAddressTable) AddressTable;
15939206bb37SAxel Dörfler 		// static C++ objects are not initialized in the module startup
1594a3ec278aSAxel Dörfler 
1595a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1596a3ec278aSAxel Dörfler 	add_debugger_command("net_interface", &dump_interface,
1597a3ec278aSAxel Dörfler 		"Dump the given network interface");
159861729d93SAxel Dörfler 	add_debugger_command("net_interfaces", &dump_interfaces,
159961729d93SAxel Dörfler 		"Dump all network interfaces");
160061729d93SAxel Dörfler 	add_debugger_command("net_local", &dump_local,
160161729d93SAxel Dörfler 		"Dump all local interface addresses");
160261729d93SAxel Dörfler 	add_debugger_command("net_route", &dump_route,
160361729d93SAxel Dörfler 		"Dump the given network route");
1604a3ec278aSAxel Dörfler #endif
1605c22d69bfSAxel Dörfler 	return B_OK;
1606c22d69bfSAxel Dörfler }
1607c22d69bfSAxel Dörfler 
1608c22d69bfSAxel Dörfler 
1609c22d69bfSAxel Dörfler status_t
1610c22d69bfSAxel Dörfler uninit_interfaces()
1611c22d69bfSAxel Dörfler {
1612a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1613a3ec278aSAxel Dörfler 	remove_debugger_command("net_interface", &dump_interface);
1614a3ec278aSAxel Dörfler #endif
1615a3ec278aSAxel Dörfler 
161661729d93SAxel Dörfler 	mutex_destroy(&sLock);
161761729d93SAxel Dörfler 	mutex_destroy(&sHashLock);
1618c22d69bfSAxel Dörfler 	return B_OK;
1619c22d69bfSAxel Dörfler }
1620c22d69bfSAxel Dörfler 
1621