xref: /haiku/src/add-ons/kernel/network/stack/interfaces.cpp (revision 78abd72799a91febaeca4b0300a56af38af4a1cc)
1c22d69bfSAxel Dörfler /*
261729d93SAxel Dörfler  * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3c22d69bfSAxel Dörfler  * Distributed under the terms of the MIT License.
4c22d69bfSAxel Dörfler  *
5c22d69bfSAxel Dörfler  * Authors:
6c22d69bfSAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
7c22d69bfSAxel Dörfler  */
8c22d69bfSAxel Dörfler 
9c22d69bfSAxel Dörfler 
10c22d69bfSAxel Dörfler #include "interfaces.h"
11c22d69bfSAxel Dörfler 
12c22d69bfSAxel Dörfler #include <net/if_dl.h>
13c22d69bfSAxel Dörfler #include <new>
14a1deb55eSHugo Santos #include <stdio.h>
15c22d69bfSAxel Dörfler #include <stdlib.h>
16c22d69bfSAxel Dörfler #include <string.h>
1761729d93SAxel Dörfler #include <sys/sockio.h>
1861729d93SAxel Dörfler 
1961729d93SAxel Dörfler #include <KernelExport.h>
2061729d93SAxel Dörfler 
2161729d93SAxel Dörfler #include <net_device.h>
22b0cf274aSAxel Dörfler #include <NetUtilities.h>
2361729d93SAxel Dörfler 
2461729d93SAxel Dörfler #include "device_interfaces.h"
2561729d93SAxel Dörfler #include "domains.h"
2661729d93SAxel Dörfler #include "stack_private.h"
2761729d93SAxel Dörfler #include "utility.h"
28c22d69bfSAxel Dörfler 
29c22d69bfSAxel Dörfler 
3061729d93SAxel Dörfler //#define TRACE_INTERFACES
31c22d69bfSAxel Dörfler #ifdef TRACE_INTERFACES
3261729d93SAxel Dörfler #	define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x)
33c22d69bfSAxel Dörfler #else
3461729d93SAxel Dörfler #	define TRACE(x...) ;
35c22d69bfSAxel Dörfler #endif
36c22d69bfSAxel Dörfler 
3761729d93SAxel Dörfler 
3861729d93SAxel Dörfler struct AddressHashDefinition {
3961729d93SAxel Dörfler 	typedef const sockaddr* KeyType;
4061729d93SAxel Dörfler 	typedef InterfaceAddress ValueType;
4161729d93SAxel Dörfler 
4261729d93SAxel Dörfler 	AddressHashDefinition()
4361729d93SAxel Dörfler 	{
4461729d93SAxel Dörfler 	}
4561729d93SAxel Dörfler 
4661729d93SAxel Dörfler 	size_t HashKey(const KeyType& key) const
4761729d93SAxel Dörfler 	{
4861729d93SAxel Dörfler 		net_domain* domain = get_domain(key->sa_family);
4961729d93SAxel Dörfler 		if (domain == NULL)
5061729d93SAxel Dörfler 			return 0;
5161729d93SAxel Dörfler 
5261729d93SAxel Dörfler 		return domain->address_module->hash_address(key, false);
5361729d93SAxel Dörfler 	}
5461729d93SAxel Dörfler 
5561729d93SAxel Dörfler 	size_t Hash(InterfaceAddress* address) const
5661729d93SAxel Dörfler 	{
5761729d93SAxel Dörfler 		return address->domain->address_module->hash_address(address->local, false);
5861729d93SAxel Dörfler 	}
5961729d93SAxel Dörfler 
6061729d93SAxel Dörfler 	bool Compare(const KeyType& key, InterfaceAddress* address) const
6161729d93SAxel Dörfler 	{
6261729d93SAxel Dörfler 		if (address->local == NULL)
6361729d93SAxel Dörfler 			return key->sa_family == AF_UNSPEC;
6461729d93SAxel Dörfler 
6561729d93SAxel Dörfler 		if (address->local->sa_family != key->sa_family)
6661729d93SAxel Dörfler 			return false;
6761729d93SAxel Dörfler 
6861729d93SAxel Dörfler 		return address->domain->address_module->equal_addresses(key,
6961729d93SAxel Dörfler 			address->local);
7061729d93SAxel Dörfler 	}
7161729d93SAxel Dörfler 
7261729d93SAxel Dörfler 	InterfaceAddress*& GetLink(InterfaceAddress* address) const
7361729d93SAxel Dörfler 	{
7461729d93SAxel Dörfler 		return address->HashTableLink();
7561729d93SAxel Dörfler 	}
7661729d93SAxel Dörfler };
7761729d93SAxel Dörfler 
7861729d93SAxel Dörfler typedef BOpenHashTable<AddressHashDefinition, true, true> AddressTable;
79a3ec278aSAxel Dörfler 
80c22d69bfSAxel Dörfler 
8161729d93SAxel Dörfler static mutex sLock;
8261729d93SAxel Dörfler static InterfaceList sInterfaces;
8361729d93SAxel Dörfler static mutex sHashLock;
8461729d93SAxel Dörfler static AddressTable sAddressTable;
85c22d69bfSAxel Dörfler static uint32 sInterfaceIndex;
869261b129SHugo Santos 
879261b129SHugo Santos 
88a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
89a3ec278aSAxel Dörfler 
90a3ec278aSAxel Dörfler 
91a3ec278aSAxel Dörfler static int
92a3ec278aSAxel Dörfler dump_interface(int argc, char** argv)
93a3ec278aSAxel Dörfler {
94a3ec278aSAxel Dörfler 	if (argc != 2) {
95a3ec278aSAxel Dörfler 		kprintf("usage: %s [address]\n", argv[0]);
96a3ec278aSAxel Dörfler 		return 0;
97a3ec278aSAxel Dörfler 	}
98a3ec278aSAxel Dörfler 
9961729d93SAxel Dörfler 	Interface* interface = (Interface*)parse_expression(argv[1]);
10061729d93SAxel Dörfler 	interface->Dump();
101a3ec278aSAxel Dörfler 
102a3ec278aSAxel Dörfler 	return 0;
103a3ec278aSAxel Dörfler }
104a3ec278aSAxel Dörfler 
105a3ec278aSAxel Dörfler 
106a3ec278aSAxel Dörfler static int
10761729d93SAxel Dörfler dump_interfaces(int argc, char** argv)
10861729d93SAxel Dörfler {
10961729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
11061729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
11161729d93SAxel Dörfler 		kprintf("%p  %s\n", interface, interface->name);
11261729d93SAxel Dörfler 	}
11361729d93SAxel Dörfler 	return 0;
11461729d93SAxel Dörfler }
11561729d93SAxel Dörfler 
11661729d93SAxel Dörfler 
11761729d93SAxel Dörfler static int
11861729d93SAxel Dörfler dump_local(int argc, char** argv)
11961729d93SAxel Dörfler {
12061729d93SAxel Dörfler 	AddressTable::Iterator iterator = sAddressTable.GetIterator();
12161729d93SAxel Dörfler 	size_t i = 0;
12261729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
12361729d93SAxel Dörfler 		address->Dump(++i);
12461729d93SAxel Dörfler 		dprintf("    hash:          %lu\n",
12561729d93SAxel Dörfler 			address->domain->address_module->hash_address(address->local,
12661729d93SAxel Dörfler 				false));
12761729d93SAxel Dörfler 	}
12861729d93SAxel Dörfler 	return 0;
12961729d93SAxel Dörfler }
13061729d93SAxel Dörfler 
13161729d93SAxel Dörfler 
13261729d93SAxel Dörfler static int
13361729d93SAxel Dörfler dump_route(int argc, char** argv)
134a3ec278aSAxel Dörfler {
135a3ec278aSAxel Dörfler 	if (argc != 2) {
136a3ec278aSAxel Dörfler 		kprintf("usage: %s [address]\n", argv[0]);
137a3ec278aSAxel Dörfler 		return 0;
138a3ec278aSAxel Dörfler 	}
139a3ec278aSAxel Dörfler 
14061729d93SAxel Dörfler 	net_route* route = (net_route*)parse_expression(argv[1]);
14161729d93SAxel Dörfler 	kprintf("destination:       %p\n", route->destination);
14261729d93SAxel Dörfler 	kprintf("mask:              %p\n", route->mask);
14361729d93SAxel Dörfler 	kprintf("gateway:           %p\n", route->gateway);
14461729d93SAxel Dörfler 	kprintf("flags:             %" B_PRIx32 "\n", route->flags);
14561729d93SAxel Dörfler 	kprintf("mtu:               %" B_PRIu32 "\n", route->mtu);
14661729d93SAxel Dörfler 	kprintf("interface address: %p\n", route->interface_address);
147a3ec278aSAxel Dörfler 
14861729d93SAxel Dörfler 	if (route->interface_address != NULL) {
14961729d93SAxel Dörfler 		((InterfaceAddress*)route->interface_address)->Dump();
150a3ec278aSAxel Dörfler 	}
151a3ec278aSAxel Dörfler 
152a3ec278aSAxel Dörfler 	return 0;
153a3ec278aSAxel Dörfler }
154a3ec278aSAxel Dörfler 
155a3ec278aSAxel Dörfler 
156a3ec278aSAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
157a3ec278aSAxel Dörfler 
158a3ec278aSAxel Dörfler 
15961729d93SAxel Dörfler InterfaceAddress::InterfaceAddress()
160c22d69bfSAxel Dörfler {
16161729d93SAxel Dörfler 	_Init(NULL, NULL);
16261729d93SAxel Dörfler }
163c22d69bfSAxel Dörfler 
16461729d93SAxel Dörfler 
16561729d93SAxel Dörfler InterfaceAddress::InterfaceAddress(net_interface* netInterface,
16661729d93SAxel Dörfler 	net_domain* netDomain)
16761729d93SAxel Dörfler {
16861729d93SAxel Dörfler 	_Init(netInterface, netDomain);
16961729d93SAxel Dörfler }
17061729d93SAxel Dörfler 
17161729d93SAxel Dörfler 
17261729d93SAxel Dörfler InterfaceAddress::~InterfaceAddress()
17361729d93SAxel Dörfler {
1742b1c0755SAxel Dörfler 	TRACE("InterfaceAddress %p: destructor\n", this);
1752b1c0755SAxel Dörfler 
1762b1c0755SAxel Dörfler 	if (interface != NULL && (flags & IFAF_DIRECT_ADDRESS) == 0)
1772b1c0755SAxel Dörfler 		((Interface*)interface)->ReleaseReference();
17861729d93SAxel Dörfler }
17961729d93SAxel Dörfler 
18061729d93SAxel Dörfler 
18161729d93SAxel Dörfler status_t
18261729d93SAxel Dörfler InterfaceAddress::SetTo(const ifaliasreq& request)
18361729d93SAxel Dörfler {
18461729d93SAxel Dörfler 	status_t status = SetLocal((const sockaddr*)&request.ifra_addr);
18561729d93SAxel Dörfler 	if (status == B_OK)
18661729d93SAxel Dörfler 		status = SetDestination((const sockaddr*)&request.ifra_broadaddr);
18761729d93SAxel Dörfler 	if (status == B_OK)
18861729d93SAxel Dörfler 		status = SetMask((const sockaddr*)&request.ifra_mask);
18961729d93SAxel Dörfler 
19061729d93SAxel Dörfler 	return status;
19161729d93SAxel Dörfler }
19261729d93SAxel Dörfler 
19361729d93SAxel Dörfler 
19461729d93SAxel Dörfler status_t
19561729d93SAxel Dörfler InterfaceAddress::SetLocal(const sockaddr* to)
19661729d93SAxel Dörfler {
19761729d93SAxel Dörfler 	return Set(&local, to);
19861729d93SAxel Dörfler }
19961729d93SAxel Dörfler 
20061729d93SAxel Dörfler 
20161729d93SAxel Dörfler status_t
20261729d93SAxel Dörfler InterfaceAddress::SetDestination(const sockaddr* to)
20361729d93SAxel Dörfler {
20461729d93SAxel Dörfler 	return Set(&destination, to);
20561729d93SAxel Dörfler }
20661729d93SAxel Dörfler 
20761729d93SAxel Dörfler 
20861729d93SAxel Dörfler status_t
20961729d93SAxel Dörfler InterfaceAddress::SetMask(const sockaddr* to)
21061729d93SAxel Dörfler {
21161729d93SAxel Dörfler 	return Set(&mask, to);
21261729d93SAxel Dörfler }
21361729d93SAxel Dörfler 
21461729d93SAxel Dörfler 
21561729d93SAxel Dörfler sockaddr**
21661729d93SAxel Dörfler InterfaceAddress::AddressFor(int32 option)
21761729d93SAxel Dörfler {
21861729d93SAxel Dörfler 	switch (option) {
21961729d93SAxel Dörfler 		case SIOCSIFADDR:
22061729d93SAxel Dörfler 		case SIOCGIFADDR:
2212b1c0755SAxel Dörfler 		case SIOCDIFADDR:
22261729d93SAxel Dörfler 			return &local;
22361729d93SAxel Dörfler 
22461729d93SAxel Dörfler 		case SIOCSIFNETMASK:
22561729d93SAxel Dörfler 		case SIOCGIFNETMASK:
22661729d93SAxel Dörfler 			return &mask;
22761729d93SAxel Dörfler 
22861729d93SAxel Dörfler 		case SIOCSIFBRDADDR:
22961729d93SAxel Dörfler 		case SIOCSIFDSTADDR:
23061729d93SAxel Dörfler 		case SIOCGIFBRDADDR:
23161729d93SAxel Dörfler 		case SIOCGIFDSTADDR:
23261729d93SAxel Dörfler 			return &destination;
23361729d93SAxel Dörfler 
23461729d93SAxel Dörfler 		default:
23561729d93SAxel Dörfler 			return NULL;
23661729d93SAxel Dörfler 	}
23761729d93SAxel Dörfler }
23861729d93SAxel Dörfler 
23961729d93SAxel Dörfler 
2402b1c0755SAxel Dörfler /*!	Adds the default routes that every interface address needs, ie. the local
2412b1c0755SAxel Dörfler 	host route, and one for the subnet (if set).
2422b1c0755SAxel Dörfler */
2432b1c0755SAxel Dörfler void
2442b1c0755SAxel Dörfler InterfaceAddress::AddDefaultRoutes(int32 option)
2452b1c0755SAxel Dörfler {
2462b1c0755SAxel Dörfler 	net_route route;
2472b1c0755SAxel Dörfler 	route.destination = local;
2482b1c0755SAxel Dörfler 	route.gateway = NULL;
2492b1c0755SAxel Dörfler 	route.interface_address = this;
2502b1c0755SAxel Dörfler 
2512b1c0755SAxel Dörfler 	if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
2522b1c0755SAxel Dörfler 		route.mask = mask;
2532b1c0755SAxel Dörfler 		route.flags = 0;
2542b1c0755SAxel Dörfler 		add_route(domain, &route);
2552b1c0755SAxel Dörfler 	}
2562b1c0755SAxel Dörfler 
2572b1c0755SAxel Dörfler 	if (option == SIOCSIFADDR) {
2582b1c0755SAxel Dörfler 		route.mask = NULL;
2592b1c0755SAxel Dörfler 		route.flags = RTF_LOCAL | RTF_HOST;
2602b1c0755SAxel Dörfler 		add_route(domain, &route);
2612b1c0755SAxel Dörfler 	}
2622b1c0755SAxel Dörfler }
2632b1c0755SAxel Dörfler 
2642b1c0755SAxel Dörfler 
2652b1c0755SAxel Dörfler /*!	Removes the default routes as set by AddDefaultRoutes() again. */
2662b1c0755SAxel Dörfler void
2672b1c0755SAxel Dörfler InterfaceAddress::RemoveDefaultRoutes(int32 option)
2682b1c0755SAxel Dörfler {
2692b1c0755SAxel Dörfler 	net_route route;
2702b1c0755SAxel Dörfler 	route.destination = local;
2712b1c0755SAxel Dörfler 	route.gateway = NULL;
2722b1c0755SAxel Dörfler 	route.interface_address = this;
2732b1c0755SAxel Dörfler 
2742b1c0755SAxel Dörfler 	if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
2752b1c0755SAxel Dörfler 		route.mask = mask;
2762b1c0755SAxel Dörfler 		route.flags = 0;
2772b1c0755SAxel Dörfler 		remove_route(domain, &route);
2782b1c0755SAxel Dörfler 	}
2792b1c0755SAxel Dörfler 
2802b1c0755SAxel Dörfler 	if (option == SIOCSIFADDR) {
2812b1c0755SAxel Dörfler 		route.mask = NULL;
2822b1c0755SAxel Dörfler 		route.flags = RTF_LOCAL | RTF_HOST;
2832b1c0755SAxel Dörfler 		remove_route(domain, &route);
2842b1c0755SAxel Dörfler 	}
2852b1c0755SAxel Dörfler }
2862b1c0755SAxel Dörfler 
2872b1c0755SAxel Dörfler 
28861729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
28961729d93SAxel Dörfler 
29061729d93SAxel Dörfler 
29161729d93SAxel Dörfler void
29261729d93SAxel Dörfler InterfaceAddress::Dump(size_t index, bool hideInterface)
29361729d93SAxel Dörfler {
29461729d93SAxel Dörfler 	if (index)
29561729d93SAxel Dörfler 		kprintf("%2zu. ", index);
29661729d93SAxel Dörfler 	else
29761729d93SAxel Dörfler 		kprintf("    ");
29861729d93SAxel Dörfler 
29961729d93SAxel Dörfler 	if (!hideInterface) {
30061729d93SAxel Dörfler 		kprintf("interface:   %p (%s)\n    ", interface,
30161729d93SAxel Dörfler 			interface != NULL ? interface->name : "-");
30261729d93SAxel Dörfler 	}
30361729d93SAxel Dörfler 
30461729d93SAxel Dörfler 	kprintf("domain:      %p (family %u)\n", domain,
30561729d93SAxel Dörfler 		domain != NULL ? domain->family : AF_UNSPEC);
30661729d93SAxel Dörfler 
30761729d93SAxel Dörfler 	char buffer[64];
30861729d93SAxel Dörfler 	if (local != NULL && domain != NULL) {
30961729d93SAxel Dörfler 		domain->address_module->print_address_buffer(local, buffer,
31061729d93SAxel Dörfler 			sizeof(buffer), false);
31161729d93SAxel Dörfler 	} else
31261729d93SAxel Dörfler 		strcpy(buffer, "-");
31361729d93SAxel Dörfler 	kprintf("    local:       %s\n", buffer);
31461729d93SAxel Dörfler 
31561729d93SAxel Dörfler 	if (mask != NULL && domain != NULL) {
31661729d93SAxel Dörfler 		domain->address_module->print_address_buffer(mask, buffer,
31761729d93SAxel Dörfler 			sizeof(buffer), false);
31861729d93SAxel Dörfler 	} else
31961729d93SAxel Dörfler 		strcpy(buffer, "-");
32061729d93SAxel Dörfler 	kprintf("    mask:        %s\n", buffer);
32161729d93SAxel Dörfler 
32261729d93SAxel Dörfler 	if (destination != NULL && domain != NULL) {
32361729d93SAxel Dörfler 		domain->address_module->print_address_buffer(destination, buffer,
32461729d93SAxel Dörfler 			sizeof(buffer), false);
32561729d93SAxel Dörfler 	} else
32661729d93SAxel Dörfler 		strcpy(buffer, "-");
32761729d93SAxel Dörfler 	kprintf("    destination: %s\n", buffer);
32861729d93SAxel Dörfler }
32961729d93SAxel Dörfler 
33061729d93SAxel Dörfler 
33161729d93SAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
33261729d93SAxel Dörfler 
33361729d93SAxel Dörfler 
33461729d93SAxel Dörfler /*static*/ status_t
33561729d93SAxel Dörfler InterfaceAddress::Set(sockaddr** _address, const sockaddr* to)
33661729d93SAxel Dörfler {
33761729d93SAxel Dörfler 	sockaddr* address = *_address;
33861729d93SAxel Dörfler 
33961729d93SAxel Dörfler 	if (to == NULL || to->sa_family == AF_UNSPEC) {
34061729d93SAxel Dörfler 		// Clear address
34161729d93SAxel Dörfler 		free(address);
34261729d93SAxel Dörfler 		*_address = NULL;
34361729d93SAxel Dörfler 		return B_OK;
34461729d93SAxel Dörfler 	}
34561729d93SAxel Dörfler 
34661729d93SAxel Dörfler 	// Set address
34761729d93SAxel Dörfler 
34861729d93SAxel Dörfler 	size_t size = max_c(to->sa_len, sizeof(sockaddr));
34961729d93SAxel Dörfler 	if (size > sizeof(sockaddr_storage))
35061729d93SAxel Dörfler 		size = sizeof(sockaddr_storage);
35161729d93SAxel Dörfler 
35261729d93SAxel Dörfler 	address = Prepare(_address, size);
35361729d93SAxel Dörfler 	if (address == NULL)
35461729d93SAxel Dörfler 		return B_NO_MEMORY;
35561729d93SAxel Dörfler 
35661729d93SAxel Dörfler 	memcpy(address, to, size);
35761729d93SAxel Dörfler 	address->sa_len = size;
35861729d93SAxel Dörfler 
35961729d93SAxel Dörfler 	return B_OK;
36061729d93SAxel Dörfler }
36161729d93SAxel Dörfler 
36261729d93SAxel Dörfler 
36361729d93SAxel Dörfler /*static*/ sockaddr*
36461729d93SAxel Dörfler InterfaceAddress::Prepare(sockaddr** _address, size_t size)
36561729d93SAxel Dörfler {
36661729d93SAxel Dörfler 	size = max_c(size, sizeof(sockaddr));
36761729d93SAxel Dörfler 	if (size > sizeof(sockaddr_storage))
36861729d93SAxel Dörfler 		size = sizeof(sockaddr_storage);
36961729d93SAxel Dörfler 
37061729d93SAxel Dörfler 	sockaddr* address = *_address;
37161729d93SAxel Dörfler 
37261729d93SAxel Dörfler 	if (address == NULL || size > address->sa_len) {
37361729d93SAxel Dörfler 		address = (sockaddr*)realloc(address, size);
37461729d93SAxel Dörfler 		if (address == NULL)
37561729d93SAxel Dörfler 			return NULL;
37661729d93SAxel Dörfler 	}
37761729d93SAxel Dörfler 
37861729d93SAxel Dörfler 	address->sa_len = size;
37961729d93SAxel Dörfler 
38061729d93SAxel Dörfler 	*_address = address;
38161729d93SAxel Dörfler 	return address;
38261729d93SAxel Dörfler }
38361729d93SAxel Dörfler 
38461729d93SAxel Dörfler 
38561729d93SAxel Dörfler void
38661729d93SAxel Dörfler InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain)
38761729d93SAxel Dörfler {
3882b1c0755SAxel Dörfler 	TRACE("InterfaceAddress %p: init interface %p, domain %p\n", this,
3892b1c0755SAxel Dörfler 		netInterface, netDomain);
3902b1c0755SAxel Dörfler 
39161729d93SAxel Dörfler 	interface = netInterface;
39261729d93SAxel Dörfler 	domain = netDomain;
39361729d93SAxel Dörfler 	local = NULL;
39461729d93SAxel Dörfler 	destination = NULL;
39561729d93SAxel Dörfler 	mask = NULL;
3962b1c0755SAxel Dörfler 	flags = 0;
3972b1c0755SAxel Dörfler 
3982b1c0755SAxel Dörfler 	if (interface != NULL)
3992b1c0755SAxel Dörfler 		((Interface*)interface)->AcquireReference();
40061729d93SAxel Dörfler }
40161729d93SAxel Dörfler 
40261729d93SAxel Dörfler 
40361729d93SAxel Dörfler // #pragma mark -
40461729d93SAxel Dörfler 
40561729d93SAxel Dörfler 
40661729d93SAxel Dörfler Interface::Interface(const char* interfaceName,
40761729d93SAxel Dörfler 	net_device_interface* deviceInterface)
40861729d93SAxel Dörfler {
40961729d93SAxel Dörfler 	TRACE("Interface %p: new \"%s\", device interface %p\n", this,
41061729d93SAxel Dörfler 		interfaceName, deviceInterface);
41161729d93SAxel Dörfler 
412b0cf274aSAxel Dörfler 	int written = strlcpy(name, interfaceName, IF_NAMESIZE);
413b0cf274aSAxel Dörfler 	memset(name + written, 0, IF_NAMESIZE - written);
414b0cf274aSAxel Dörfler 		// Clear remaining space
415b0cf274aSAxel Dörfler 
41661729d93SAxel Dörfler 	device = deviceInterface->device;
41761729d93SAxel Dörfler 
41861729d93SAxel Dörfler 	index = ++sInterfaceIndex;
41961729d93SAxel Dörfler 	flags = 0;
42061729d93SAxel Dörfler 	type = 0;
42161729d93SAxel Dörfler 	mtu = deviceInterface->device->mtu;
42261729d93SAxel Dörfler 	metric = 0;
42361729d93SAxel Dörfler 
42461729d93SAxel Dörfler 	fDeviceInterface = acquire_device_interface(deviceInterface);
42561729d93SAxel Dörfler 
42661729d93SAxel Dörfler 	recursive_lock_init(&fLock, name);
42761729d93SAxel Dörfler 
42861729d93SAxel Dörfler 	// Grab a reference to the networking stack, to make sure it won't be
42961729d93SAxel Dörfler 	// unloaded as long as an interface exists
43061729d93SAxel Dörfler 	module_info* module;
43161729d93SAxel Dörfler 	get_module(gNetStackInterfaceModule.info.name, &module);
43261729d93SAxel Dörfler }
43361729d93SAxel Dörfler 
43461729d93SAxel Dörfler 
43561729d93SAxel Dörfler Interface::~Interface()
43661729d93SAxel Dörfler {
4372b1c0755SAxel Dörfler 	TRACE("Interface %p: destructor\n", this);
4382b1c0755SAxel Dörfler 
4392b1c0755SAxel Dörfler 	put_device_interface(fDeviceInterface);
4402b1c0755SAxel Dörfler 
4412b1c0755SAxel Dörfler 	// Uninitialize the domain datalink protocols
4422b1c0755SAxel Dörfler 
4432b1c0755SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
4442b1c0755SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
4452b1c0755SAxel Dörfler 		put_domain_datalink_protocols(this, datalink->domain);
4462b1c0755SAxel Dörfler 	}
4472b1c0755SAxel Dörfler 
4482b1c0755SAxel Dörfler 	// Free domain datalink objects
4492b1c0755SAxel Dörfler 
4502b1c0755SAxel Dörfler 	domain_datalink* next = fDatalinkTable.Clear(true);
4512b1c0755SAxel Dörfler 	while (next != NULL) {
4522b1c0755SAxel Dörfler 		domain_datalink* datalink = next;
4532b1c0755SAxel Dörfler 		next = next->hash_link;
4542b1c0755SAxel Dörfler 
4552b1c0755SAxel Dörfler 		delete datalink;
4562b1c0755SAxel Dörfler 	}
4572b1c0755SAxel Dörfler 
45861729d93SAxel Dörfler 	recursive_lock_destroy(&fLock);
45961729d93SAxel Dörfler 
46061729d93SAxel Dörfler 	// Release reference of the stack - at this point, our stack may be unloaded
46161729d93SAxel Dörfler 	// if no other interfaces or sockets are left
46261729d93SAxel Dörfler 	put_module(gNetStackInterfaceModule.info.name);
46361729d93SAxel Dörfler }
46461729d93SAxel Dörfler 
46561729d93SAxel Dörfler 
46661729d93SAxel Dörfler /*!	Returns a reference to the first InterfaceAddress that is from the same
46761729d93SAxel Dörfler 	as the specified \a family.
46861729d93SAxel Dörfler */
46961729d93SAxel Dörfler InterfaceAddress*
47061729d93SAxel Dörfler Interface::FirstForFamily(int family)
47161729d93SAxel Dörfler {
47261729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
47361729d93SAxel Dörfler 
47461729d93SAxel Dörfler 	InterfaceAddress* address = _FirstForFamily(family);
47561729d93SAxel Dörfler 	if (address != NULL) {
47661729d93SAxel Dörfler 		address->AcquireReference();
47761729d93SAxel Dörfler 		return address;
47861729d93SAxel Dörfler 	}
47961729d93SAxel Dörfler 
48061729d93SAxel Dörfler 	return NULL;
48161729d93SAxel Dörfler }
48261729d93SAxel Dörfler 
48361729d93SAxel Dörfler 
48461729d93SAxel Dörfler /*!	Returns a reference to the first unconfigured address of this interface
48561729d93SAxel Dörfler 	for the specified \a family.
48661729d93SAxel Dörfler */
48761729d93SAxel Dörfler InterfaceAddress*
48861729d93SAxel Dörfler Interface::FirstUnconfiguredForFamily(int family)
48961729d93SAxel Dörfler {
49061729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
49161729d93SAxel Dörfler 
49261729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
49361729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
49461729d93SAxel Dörfler 		if (address->domain->family == family
49561729d93SAxel Dörfler 			&& (address->local == NULL
49661729d93SAxel Dörfler 				// TODO: this has to be solved differently!!
49761729d93SAxel Dörfler 				|| (flags & IFF_CONFIGURING) != 0)) {
49861729d93SAxel Dörfler 			address->AcquireReference();
49961729d93SAxel Dörfler 			return address;
50061729d93SAxel Dörfler 		}
50161729d93SAxel Dörfler 	}
50261729d93SAxel Dörfler 
50361729d93SAxel Dörfler 	return NULL;
50461729d93SAxel Dörfler }
50561729d93SAxel Dörfler 
50661729d93SAxel Dörfler 
50761729d93SAxel Dörfler /*!	Returns a reference to the InterfaceAddress that has the specified
50861729d93SAxel Dörfler 	\a destination address.
50961729d93SAxel Dörfler */
51061729d93SAxel Dörfler InterfaceAddress*
51161729d93SAxel Dörfler Interface::AddressForDestination(net_domain* domain,
51261729d93SAxel Dörfler 	const sockaddr* destination)
51361729d93SAxel Dörfler {
51461729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
51561729d93SAxel Dörfler 
51661729d93SAxel Dörfler 	if ((device->flags & IFF_BROADCAST) == 0) {
51761729d93SAxel Dörfler 		// The device does not support broadcasting
51861729d93SAxel Dörfler 		return NULL;
51961729d93SAxel Dörfler 	}
52061729d93SAxel Dörfler 
52161729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
52261729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
52361729d93SAxel Dörfler 		if (address->domain == domain
52461729d93SAxel Dörfler 			&& address->destination != NULL
52561729d93SAxel Dörfler 			&& domain->address_module->equal_addresses(address->destination,
52661729d93SAxel Dörfler 					destination)) {
52761729d93SAxel Dörfler 			address->AcquireReference();
52861729d93SAxel Dörfler 			return address;
52961729d93SAxel Dörfler 		}
53061729d93SAxel Dörfler 	}
53161729d93SAxel Dörfler 
53261729d93SAxel Dörfler 	return NULL;
53361729d93SAxel Dörfler }
53461729d93SAxel Dörfler 
53561729d93SAxel Dörfler 
53661729d93SAxel Dörfler status_t
53761729d93SAxel Dörfler Interface::AddAddress(InterfaceAddress* address)
53861729d93SAxel Dörfler {
53961729d93SAxel Dörfler 	net_domain* domain = address->domain;
54061729d93SAxel Dörfler 	if (domain == NULL)
54161729d93SAxel Dörfler 		return B_BAD_VALUE;
54261729d93SAxel Dörfler 
54361729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
54461729d93SAxel Dörfler 	fAddresses.Add(address);
54561729d93SAxel Dörfler 	locker.Unlock();
54661729d93SAxel Dörfler 
54761729d93SAxel Dörfler 	MutexLocker hashLocker(sHashLock);
54861729d93SAxel Dörfler 	sAddressTable.Insert(address);
54961729d93SAxel Dörfler 	return B_OK;
55061729d93SAxel Dörfler }
55161729d93SAxel Dörfler 
55261729d93SAxel Dörfler 
55361729d93SAxel Dörfler void
55461729d93SAxel Dörfler Interface::RemoveAddress(InterfaceAddress* address)
55561729d93SAxel Dörfler {
55661729d93SAxel Dörfler 	net_domain* domain = address->domain;
55761729d93SAxel Dörfler 	if (domain == NULL)
55861729d93SAxel Dörfler 		return;
55961729d93SAxel Dörfler 
56061729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
56161729d93SAxel Dörfler 
56261729d93SAxel Dörfler 	fAddresses.Remove(address);
56361729d93SAxel Dörfler 	address->GetDoublyLinkedListLink()->next = NULL;
56461729d93SAxel Dörfler 
56561729d93SAxel Dörfler 	locker.Unlock();
56661729d93SAxel Dörfler 
56761729d93SAxel Dörfler 	MutexLocker hashLocker(sHashLock);
56861729d93SAxel Dörfler 	sAddressTable.Remove(address);
56961729d93SAxel Dörfler }
57061729d93SAxel Dörfler 
57161729d93SAxel Dörfler 
57261729d93SAxel Dörfler bool
57361729d93SAxel Dörfler Interface::GetNextAddress(InterfaceAddress** _address)
57461729d93SAxel Dörfler {
57561729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
57661729d93SAxel Dörfler 
57761729d93SAxel Dörfler 	InterfaceAddress* address = *_address;
57861729d93SAxel Dörfler 	if (address == NULL) {
57961729d93SAxel Dörfler 		// get first address
58061729d93SAxel Dörfler 		address = fAddresses.First();
58161729d93SAxel Dörfler 	} else {
58261729d93SAxel Dörfler 		// get next, if possible
58361729d93SAxel Dörfler 		InterfaceAddress* next = fAddresses.GetNext(address);
58461729d93SAxel Dörfler 		address->ReleaseReference();
58561729d93SAxel Dörfler 		address = next;
58661729d93SAxel Dörfler 	}
58761729d93SAxel Dörfler 
58861729d93SAxel Dörfler 	*_address = address;
58961729d93SAxel Dörfler 
59061729d93SAxel Dörfler 	if (address == NULL)
59161729d93SAxel Dörfler 		return false;
59261729d93SAxel Dörfler 
59361729d93SAxel Dörfler 	address->AcquireReference();
59461729d93SAxel Dörfler 	return true;
59561729d93SAxel Dörfler }
59661729d93SAxel Dörfler 
59761729d93SAxel Dörfler 
5989d771afbSAxel Dörfler InterfaceAddress*
5999d771afbSAxel Dörfler Interface::AddressAt(size_t index)
6009d771afbSAxel Dörfler {
6019d771afbSAxel Dörfler 	RecursiveLocker locker(fLock);
6029d771afbSAxel Dörfler 
6039d771afbSAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
6049d771afbSAxel Dörfler 	size_t i = 0;
6059d771afbSAxel Dörfler 
6069d771afbSAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
6079d771afbSAxel Dörfler 		if (i++ == index) {
6089d771afbSAxel Dörfler 			address->AcquireReference();
6099d771afbSAxel Dörfler 			return address;
6109d771afbSAxel Dörfler 		}
6119d771afbSAxel Dörfler 	}
6129d771afbSAxel Dörfler 
6139d771afbSAxel Dörfler 	return NULL;
6149d771afbSAxel Dörfler }
6159d771afbSAxel Dörfler 
6169d771afbSAxel Dörfler 
6179d771afbSAxel Dörfler size_t
6189d771afbSAxel Dörfler Interface::CountAddresses()
6199d771afbSAxel Dörfler {
6209d771afbSAxel Dörfler 	RecursiveLocker locker(fLock);
6219d771afbSAxel Dörfler 	return fAddresses.Count();
6229d771afbSAxel Dörfler }
6239d771afbSAxel Dörfler 
6249d771afbSAxel Dörfler 
6252b1c0755SAxel Dörfler void
6262b1c0755SAxel Dörfler Interface::RemoveAddresses()
6272b1c0755SAxel Dörfler {
6282b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
6292b1c0755SAxel Dörfler 
6302b1c0755SAxel Dörfler 	while (InterfaceAddress* address = fAddresses.RemoveHead()) {
6312b1c0755SAxel Dörfler 		address->ReleaseReference();
6322b1c0755SAxel Dörfler 	}
6332b1c0755SAxel Dörfler }
6342b1c0755SAxel Dörfler 
6352b1c0755SAxel Dörfler 
6369d771afbSAxel Dörfler /*!	This is called in order to call the correct methods of the datalink
6379d771afbSAxel Dörfler 	protocols, ie. it will translate address changes to
6389d771afbSAxel Dörfler 	net_datalink_protocol::change_address(), and IFF_UP changes to
6399d771afbSAxel Dörfler 	net_datalink_protocol::interface_up(), and interface_down().
6409d771afbSAxel Dörfler 
6419d771afbSAxel Dörfler 	Everything else is passed unchanged to net_datalink_protocol::control().
6429d771afbSAxel Dörfler */
64361729d93SAxel Dörfler status_t
64461729d93SAxel Dörfler Interface::Control(net_domain* domain, int32 option, ifreq& request,
64561729d93SAxel Dörfler 	ifreq* userRequest, size_t length)
64661729d93SAxel Dörfler {
64761729d93SAxel Dörfler 	switch (option) {
64861729d93SAxel Dörfler 		case SIOCSIFFLAGS:
64961729d93SAxel Dörfler 		{
65061729d93SAxel Dörfler 			uint32 requestFlags = request.ifr_flags;
65161729d93SAxel Dörfler 			uint32 oldFlags = flags;
65261729d93SAxel Dörfler 			status_t status = B_OK;
65361729d93SAxel Dörfler 
65461729d93SAxel Dörfler 			request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST);
65561729d93SAxel Dörfler 
65661729d93SAxel Dörfler 			if ((requestFlags & IFF_UP) != (flags & IFF_UP)) {
65761729d93SAxel Dörfler 				if ((requestFlags & IFF_UP) != 0)
65861729d93SAxel Dörfler 					status = _SetUp();
65961729d93SAxel Dörfler 				else
6602b1c0755SAxel Dörfler 					SetDown();
66161729d93SAxel Dörfler 			}
66261729d93SAxel Dörfler 
66361729d93SAxel Dörfler 			if (status == B_OK) {
66461729d93SAxel Dörfler 				// TODO: maybe allow deleting IFF_BROADCAST on the interface
66561729d93SAxel Dörfler 				// level?
66661729d93SAxel Dörfler 				flags &= IFF_UP | IFF_LINK | IFF_BROADCAST;
66761729d93SAxel Dörfler 				flags |= request.ifr_flags;
66861729d93SAxel Dörfler 			}
66961729d93SAxel Dörfler 
67061729d93SAxel Dörfler 			if (oldFlags != flags)
67161729d93SAxel Dörfler 				notify_interface_changed(this, oldFlags, flags);
67261729d93SAxel Dörfler 
67361729d93SAxel Dörfler 			return status;
67461729d93SAxel Dörfler 		}
67561729d93SAxel Dörfler 
6762b1c0755SAxel Dörfler 		case B_SOCKET_SET_ALIAS:
6779d771afbSAxel Dörfler 		{
6789d771afbSAxel Dörfler 			RecursiveLocker locker(fLock);
6799d771afbSAxel Dörfler 
6809d771afbSAxel Dörfler 			ifaliasreq aliasRequest;
6819d771afbSAxel Dörfler 			if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq))
6829d771afbSAxel Dörfler 					!= B_OK)
6839d771afbSAxel Dörfler 				return B_BAD_ADDRESS;
6849d771afbSAxel Dörfler 
6859d771afbSAxel Dörfler 			InterfaceAddress* address = AddressAt(aliasRequest.ifra_index);
6869d771afbSAxel Dörfler 			if (address == NULL)
6879d771afbSAxel Dörfler 				return B_BAD_VALUE;
6889d771afbSAxel Dörfler 
6899d771afbSAxel Dörfler 			status_t status = B_OK;
6909d771afbSAxel Dörfler 			address->AcquireReference();
6919d771afbSAxel Dörfler 				// _ChangeAddress() currently unlocks, so we need another
6929d771afbSAxel Dörfler 				// reference to make sure "address" is not going away.
6939d771afbSAxel Dörfler 
6949d771afbSAxel Dörfler 			if (!domain->address_module->equal_addresses(
6959d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_addr, address->local)) {
6969d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address, SIOCSIFADDR,
6979d771afbSAxel Dörfler 					address->local, (sockaddr*)&aliasRequest.ifra_addr);
6989d771afbSAxel Dörfler 			}
6999d771afbSAxel Dörfler 
7009d771afbSAxel Dörfler 			if (status == B_OK && !domain->address_module->equal_addresses(
7019d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_mask, address->mask)) {
7029d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address, SIOCSIFNETMASK,
7039d771afbSAxel Dörfler 					address->mask, (sockaddr*)&aliasRequest.ifra_mask);
7049d771afbSAxel Dörfler 			}
7059d771afbSAxel Dörfler 
7069d771afbSAxel Dörfler 			if (status == B_OK && !domain->address_module->equal_addresses(
7079d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination,
7089d771afbSAxel Dörfler 					address->destination)) {
7099d771afbSAxel Dörfler 				status = _ChangeAddress(locker, address,
7109d771afbSAxel Dörfler 					(domain->address_module->flags
7119d771afbSAxel Dörfler 						& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0
7129d771afbSAxel Dörfler 							? SIOCSIFBRDADDR : SIOCSIFDSTADDR,
7139d771afbSAxel Dörfler 					address->destination,
7149d771afbSAxel Dörfler 					(sockaddr*)&aliasRequest.ifra_destination);
7159d771afbSAxel Dörfler 			}
7169d771afbSAxel Dörfler 
7179d771afbSAxel Dörfler 			address->ReleaseReference();
7189d771afbSAxel Dörfler 			return status;
7199d771afbSAxel Dörfler 		}
7209d771afbSAxel Dörfler 
72161729d93SAxel Dörfler 		case SIOCSIFADDR:
72261729d93SAxel Dörfler 		case SIOCSIFNETMASK:
72361729d93SAxel Dörfler 		case SIOCSIFBRDADDR:
72461729d93SAxel Dörfler 		case SIOCSIFDSTADDR:
72561729d93SAxel Dörfler 		case SIOCDIFADDR:
72661729d93SAxel Dörfler 		{
72761729d93SAxel Dörfler 			RecursiveLocker locker(fLock);
72861729d93SAxel Dörfler 
72961729d93SAxel Dörfler 			InterfaceAddress* address = NULL;
73061729d93SAxel Dörfler 			sockaddr_storage newAddress;
73161729d93SAxel Dörfler 
73261729d93SAxel Dörfler 			size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr));
73361729d93SAxel Dörfler 			if (size > sizeof(sockaddr_storage))
73461729d93SAxel Dörfler 				size = sizeof(sockaddr_storage);
73561729d93SAxel Dörfler 
73661729d93SAxel Dörfler 			if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK)
73761729d93SAxel Dörfler 				return B_BAD_ADDRESS;
73861729d93SAxel Dörfler 
73961729d93SAxel Dörfler 			if (option == SIOCDIFADDR) {
74061729d93SAxel Dörfler 				// Find referring address - we can't use the hash, as another
74161729d93SAxel Dörfler 				// interface might use the same address.
74261729d93SAxel Dörfler 				AddressList::Iterator iterator = fAddresses.GetIterator();
74361729d93SAxel Dörfler 				while ((address = iterator.Next()) != NULL) {
74461729d93SAxel Dörfler 					if (address->domain == domain
74561729d93SAxel Dörfler 						&& domain->address_module->equal_addresses(
74661729d93SAxel Dörfler 							address->local, (sockaddr*)&newAddress))
74761729d93SAxel Dörfler 						break;
74861729d93SAxel Dörfler 				}
74961729d93SAxel Dörfler 
75061729d93SAxel Dörfler 				if (address == NULL)
75161729d93SAxel Dörfler 					return B_BAD_VALUE;
752*78abd727SAxel Dörfler 			} else {
753*78abd727SAxel Dörfler 				// Just use the first address for this family
754*78abd727SAxel Dörfler 				address = _FirstForFamily(domain->family);
755*78abd727SAxel Dörfler 				if (address == NULL) {
756*78abd727SAxel Dörfler 					// Create new on the fly
757*78abd727SAxel Dörfler 					address = new(std::nothrow) InterfaceAddress(this, domain);
758*78abd727SAxel Dörfler 					if (address == NULL)
759*78abd727SAxel Dörfler 						return B_NO_MEMORY;
760*78abd727SAxel Dörfler 
761*78abd727SAxel Dörfler 					status_t status = AddAddress(address);
762*78abd727SAxel Dörfler 					if (status != B_OK)
763*78abd727SAxel Dörfler 						return status;
764*78abd727SAxel Dörfler 
765*78abd727SAxel Dörfler 					// Note, even if setting the address failed, the empty
766*78abd727SAxel Dörfler 					// address added here will still be added to the interface.
767*78abd727SAxel Dörfler 				}
768*78abd727SAxel Dörfler 			}
76961729d93SAxel Dörfler 
7709d771afbSAxel Dörfler 			return _ChangeAddress(locker, address, option,
7719d771afbSAxel Dörfler 				*address->AddressFor(option),
77261729d93SAxel Dörfler 				option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL);
77361729d93SAxel Dörfler 		}
77461729d93SAxel Dörfler 
77561729d93SAxel Dörfler 		default:
77661729d93SAxel Dörfler 			// pass the request into the datalink protocol stack
77761729d93SAxel Dörfler 			domain_datalink* datalink = DomainDatalink(domain->family);
77861729d93SAxel Dörfler 			if (datalink->first_info != NULL) {
77961729d93SAxel Dörfler 				return datalink->first_info->control(
78061729d93SAxel Dörfler 					datalink->first_protocol, option, userRequest, length);
78161729d93SAxel Dörfler 			}
78261729d93SAxel Dörfler 			break;
78361729d93SAxel Dörfler 	}
78461729d93SAxel Dörfler 
78561729d93SAxel Dörfler 	return B_BAD_VALUE;
78661729d93SAxel Dörfler }
78761729d93SAxel Dörfler 
78861729d93SAxel Dörfler 
7892b1c0755SAxel Dörfler void
7902b1c0755SAxel Dörfler Interface::SetDown()
7912b1c0755SAxel Dörfler {
7922b1c0755SAxel Dörfler 	if ((flags & IFF_UP) == 0)
7932b1c0755SAxel Dörfler 		return;
7942b1c0755SAxel Dörfler 
7952b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
7962b1c0755SAxel Dörfler 
7972b1c0755SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
7982b1c0755SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
7992b1c0755SAxel Dörfler 		datalink->first_info->interface_down(datalink->first_protocol);
8002b1c0755SAxel Dörfler 	}
8012b1c0755SAxel Dörfler 
8022b1c0755SAxel Dörfler 	flags &= ~IFF_UP;
8032b1c0755SAxel Dörfler }
8042b1c0755SAxel Dörfler 
8052b1c0755SAxel Dörfler 
8062b1c0755SAxel Dörfler /*!	Called when a device lost its IFF_UP status. We will invalidate all
8072b1c0755SAxel Dörfler 	interface routes here.
8082b1c0755SAxel Dörfler */
8092b1c0755SAxel Dörfler void
8102b1c0755SAxel Dörfler Interface::WentDown()
8112b1c0755SAxel Dörfler {
8122b1c0755SAxel Dörfler 	RecursiveLocker locker(fLock);
8132b1c0755SAxel Dörfler 
8142b1c0755SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
8152b1c0755SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
8162b1c0755SAxel Dörfler 		if (address->domain != NULL)
8172b1c0755SAxel Dörfler 			invalidate_routes(address->domain, this);
8182b1c0755SAxel Dörfler 	}
8192b1c0755SAxel Dörfler }
8202b1c0755SAxel Dörfler 
8212b1c0755SAxel Dörfler 
82261729d93SAxel Dörfler status_t
82361729d93SAxel Dörfler Interface::CreateDomainDatalinkIfNeeded(net_domain* domain)
82461729d93SAxel Dörfler {
82561729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
82661729d93SAxel Dörfler 
82761729d93SAxel Dörfler 	if (fDatalinkTable.Lookup(domain->family) != NULL)
82861729d93SAxel Dörfler 		return B_OK;
82961729d93SAxel Dörfler 
83061729d93SAxel Dörfler 	TRACE("Interface %p: create domain datalink for domain %p\n", this, domain);
83161729d93SAxel Dörfler 
83261729d93SAxel Dörfler 	domain_datalink* datalink = new(std::nothrow) domain_datalink;
83361729d93SAxel Dörfler 	if (datalink == NULL)
83461729d93SAxel Dörfler 		return B_NO_MEMORY;
83561729d93SAxel Dörfler 
83661729d93SAxel Dörfler 	datalink->domain = domain;
83761729d93SAxel Dörfler 
83861729d93SAxel Dörfler 	// setup direct route for bound devices
83961729d93SAxel Dörfler 	datalink->direct_route.destination = NULL;
84061729d93SAxel Dörfler 	datalink->direct_route.mask = NULL;
84161729d93SAxel Dörfler 	datalink->direct_route.gateway = NULL;
84261729d93SAxel Dörfler 	datalink->direct_route.flags = 0;
84361729d93SAxel Dörfler 	datalink->direct_route.mtu = 0;
84461729d93SAxel Dörfler 	datalink->direct_route.interface_address = &datalink->direct_address;
84561729d93SAxel Dörfler 	datalink->direct_route.ref_count = 1;
84661729d93SAxel Dörfler 		// make sure this doesn't get deleted accidently
84761729d93SAxel Dörfler 
84861729d93SAxel Dörfler 	// provide its link back to the interface
84961729d93SAxel Dörfler 	datalink->direct_address.local = NULL;
85061729d93SAxel Dörfler 	datalink->direct_address.destination = NULL;
85161729d93SAxel Dörfler 	datalink->direct_address.mask = NULL;
85261729d93SAxel Dörfler 	datalink->direct_address.domain = domain;
85361729d93SAxel Dörfler 	datalink->direct_address.interface = this;
8542b1c0755SAxel Dörfler 	datalink->direct_address.flags = IFAF_DIRECT_ADDRESS;
85561729d93SAxel Dörfler 
85661729d93SAxel Dörfler 	fDatalinkTable.Insert(datalink);
85761729d93SAxel Dörfler 
85861729d93SAxel Dörfler 	status_t status = get_domain_datalink_protocols(this, domain);
85961729d93SAxel Dörfler 	if (status == B_OK)
86061729d93SAxel Dörfler 		return B_OK;
86161729d93SAxel Dörfler 
86261729d93SAxel Dörfler 	fDatalinkTable.Remove(datalink);
86361729d93SAxel Dörfler 	delete datalink;
86461729d93SAxel Dörfler 
86561729d93SAxel Dörfler 	return status;
86661729d93SAxel Dörfler }
86761729d93SAxel Dörfler 
86861729d93SAxel Dörfler 
86961729d93SAxel Dörfler domain_datalink*
87061729d93SAxel Dörfler Interface::DomainDatalink(uint8 family)
87161729d93SAxel Dörfler {
87261729d93SAxel Dörfler 	// Note: domain datalinks cannot be removed while the interface is alive,
87361729d93SAxel Dörfler 	// since this would require us either to hold the lock while calling this
87461729d93SAxel Dörfler 	// function, or introduce reference counting for the domain_datalink
87561729d93SAxel Dörfler 	// structure.
87661729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
87761729d93SAxel Dörfler 	return fDatalinkTable.Lookup(family);
87861729d93SAxel Dörfler }
87961729d93SAxel Dörfler 
88061729d93SAxel Dörfler 
88161729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
88261729d93SAxel Dörfler 
88361729d93SAxel Dörfler 
88461729d93SAxel Dörfler void
88561729d93SAxel Dörfler Interface::Dump() const
88661729d93SAxel Dörfler {
88761729d93SAxel Dörfler 	kprintf("name:                %s\n", name);
88861729d93SAxel Dörfler 	kprintf("device:              %p\n", device);
88961729d93SAxel Dörfler 	kprintf("device_interface:    %p\n", fDeviceInterface);
89061729d93SAxel Dörfler 	kprintf("index:               %" B_PRIu32 "\n", index);
89161729d93SAxel Dörfler 	kprintf("flags:               %#" B_PRIx32 "\n", flags);
89261729d93SAxel Dörfler 	kprintf("type:                %u\n", type);
89361729d93SAxel Dörfler 	kprintf("mtu:                 %" B_PRIu32 "\n", mtu);
89461729d93SAxel Dörfler 	kprintf("metric:              %" B_PRIu32 "\n", metric);
89561729d93SAxel Dörfler 
89661729d93SAxel Dörfler 	kprintf("datalink protocols:\n");
89761729d93SAxel Dörfler 
89861729d93SAxel Dörfler 	DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator();
89961729d93SAxel Dörfler 	size_t i = 0;
90061729d93SAxel Dörfler 	while (domain_datalink* datalink = datalinkIterator.Next()) {
90161729d93SAxel Dörfler 		kprintf("%2zu. domain:          %p\n", ++i, datalink->domain);
90261729d93SAxel Dörfler 		kprintf("    first_protocol:  %p\n", datalink->first_protocol);
90361729d93SAxel Dörfler 		kprintf("    first_info:      %p\n", datalink->first_info);
90461729d93SAxel Dörfler 		kprintf("    direct_route:    %p\n", &datalink->direct_route);
90561729d93SAxel Dörfler 	}
90661729d93SAxel Dörfler 
90761729d93SAxel Dörfler 	kprintf("addresses:\n");
90861729d93SAxel Dörfler 
90961729d93SAxel Dörfler 	AddressList::ConstIterator iterator = fAddresses.GetIterator();
91061729d93SAxel Dörfler 	i = 0;
91161729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
91261729d93SAxel Dörfler 		address->Dump(++i, true);
91361729d93SAxel Dörfler 	}
91461729d93SAxel Dörfler }
91561729d93SAxel Dörfler 
91661729d93SAxel Dörfler 
91761729d93SAxel Dörfler #endif	// ENABLE_DEBUGGER_COMMANDS
91861729d93SAxel Dörfler 
91961729d93SAxel Dörfler 
92061729d93SAxel Dörfler status_t
92161729d93SAxel Dörfler Interface::_SetUp()
92261729d93SAxel Dörfler {
92361729d93SAxel Dörfler 	status_t status = up_device_interface(fDeviceInterface);
92461729d93SAxel Dörfler 	if (status != B_OK)
92561729d93SAxel Dörfler 		return status;
92661729d93SAxel Dörfler 
9272b1c0755SAxel Dörfler 	// Propagate flag to all datalink protocols
92861729d93SAxel Dörfler 
92961729d93SAxel Dörfler 	RecursiveLocker locker(fLock);
93061729d93SAxel Dörfler 
93161729d93SAxel Dörfler 	DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
93261729d93SAxel Dörfler 	while (domain_datalink* datalink = iterator.Next()) {
93361729d93SAxel Dörfler 		status = datalink->first_info->interface_up(datalink->first_protocol);
93461729d93SAxel Dörfler 		if (status != B_OK) {
93561729d93SAxel Dörfler 			// Revert "up" status
93661729d93SAxel Dörfler 			DatalinkTable::Iterator secondIterator
93761729d93SAxel Dörfler 				= fDatalinkTable.GetIterator();
93861729d93SAxel Dörfler 			while (secondIterator.HasNext()) {
93961729d93SAxel Dörfler 				domain_datalink* secondDatalink = secondIterator.Next();
94061729d93SAxel Dörfler 				if (secondDatalink == NULL || secondDatalink == datalink)
941c22d69bfSAxel Dörfler 					break;
942c22d69bfSAxel Dörfler 
94361729d93SAxel Dörfler 				secondDatalink->first_info->interface_down(
94461729d93SAxel Dörfler 					secondDatalink->first_protocol);
94561729d93SAxel Dörfler 			}
94661729d93SAxel Dörfler 
94761729d93SAxel Dörfler 			down_device_interface(fDeviceInterface);
94861729d93SAxel Dörfler 			return status;
94961729d93SAxel Dörfler 		}
95061729d93SAxel Dörfler 	}
95161729d93SAxel Dörfler 
9522b1c0755SAxel Dörfler 	// Add default routes for the existing addresses
9532b1c0755SAxel Dörfler 
9542b1c0755SAxel Dörfler 	AddressList::Iterator addressIterator = fAddresses.GetIterator();
9552b1c0755SAxel Dörfler 	while (InterfaceAddress* address = addressIterator.Next()) {
9562b1c0755SAxel Dörfler 		address->AddDefaultRoutes(SIOCSIFADDR);
9572b1c0755SAxel Dörfler 	}
9582b1c0755SAxel Dörfler 
95961729d93SAxel Dörfler 	flags |= IFF_UP;
96061729d93SAxel Dörfler 	return B_OK;
96161729d93SAxel Dörfler }
96261729d93SAxel Dörfler 
96361729d93SAxel Dörfler 
96461729d93SAxel Dörfler InterfaceAddress*
96561729d93SAxel Dörfler Interface::_FirstForFamily(int family)
96661729d93SAxel Dörfler {
96761729d93SAxel Dörfler 	ASSERT_LOCKED_RECURSIVE(&fLock);
96861729d93SAxel Dörfler 
96961729d93SAxel Dörfler 	AddressList::Iterator iterator = fAddresses.GetIterator();
97061729d93SAxel Dörfler 	while (InterfaceAddress* address = iterator.Next()) {
97161729d93SAxel Dörfler 		if (address->domain != NULL && address->domain->family == family)
97261729d93SAxel Dörfler 			return address;
97361729d93SAxel Dörfler 	}
97461729d93SAxel Dörfler 
97561729d93SAxel Dörfler 	return NULL;
97661729d93SAxel Dörfler }
97761729d93SAxel Dörfler 
97861729d93SAxel Dörfler 
9799d771afbSAxel Dörfler status_t
9809d771afbSAxel Dörfler Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address,
981b0cf274aSAxel Dörfler 	int32 option, const sockaddr* originalAddress,
982b0cf274aSAxel Dörfler 	const sockaddr* requestedAddress)
9839d771afbSAxel Dörfler {
984b0cf274aSAxel Dörfler 	// Copy old address
9859d771afbSAxel Dörfler 	sockaddr_storage oldAddress;
9869d771afbSAxel Dörfler 	if (address->domain->address_module->set_to((sockaddr*)&oldAddress,
9879d771afbSAxel Dörfler 			originalAddress) != B_OK)
9889d771afbSAxel Dörfler 		oldAddress.ss_family = AF_UNSPEC;
9899d771afbSAxel Dörfler 
990b0cf274aSAxel Dörfler 	// Copy new address (this also makes sure that sockaddr::sa_len is set
991b0cf274aSAxel Dörfler 	// correctly)
992b0cf274aSAxel Dörfler 	sockaddr_storage newAddress;
993b0cf274aSAxel Dörfler 	if (address->domain->address_module->set_to((sockaddr*)&newAddress,
994b0cf274aSAxel Dörfler 			requestedAddress) != B_OK)
995b0cf274aSAxel Dörfler 		newAddress.ss_family = AF_UNSPEC;
996b0cf274aSAxel Dörfler 
9976b1e1488SAxel Dörfler 	// Test if anything changed for real
998b0cf274aSAxel Dörfler 	if (address->domain->address_module->equal_addresses(
999b0cf274aSAxel Dörfler 			(sockaddr*)&oldAddress, (sockaddr*)&newAddress)) {
10006b1e1488SAxel Dörfler 		// Nothing to do
1001b0cf274aSAxel Dörfler 		TRACE("  option %" B_PRId32 " addresses are equal!\n", option);
10026b1e1488SAxel Dörfler 		return B_OK;
10036b1e1488SAxel Dörfler 	}
10046b1e1488SAxel Dörfler 
10059d771afbSAxel Dörfler 	// TODO: mark this address busy or call while holding the lock!
10069d771afbSAxel Dörfler 	address->AcquireReference();
10079d771afbSAxel Dörfler 	locker.Unlock();
10089d771afbSAxel Dörfler 
10099d771afbSAxel Dörfler 	domain_datalink* datalink = DomainDatalink(address->domain);
10109d771afbSAxel Dörfler 	status_t status = datalink->first_protocol->module->change_address(
10119d771afbSAxel Dörfler 		datalink->first_protocol, address, option,
10129d771afbSAxel Dörfler 		oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL,
1013b0cf274aSAxel Dörfler 		newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL);
10149d771afbSAxel Dörfler 
10159d771afbSAxel Dörfler 	locker.Lock();
10169d771afbSAxel Dörfler 	address->ReleaseReference();
10179d771afbSAxel Dörfler 	return status;
10189d771afbSAxel Dörfler }
10199d771afbSAxel Dörfler 
10209d771afbSAxel Dörfler 
102161729d93SAxel Dörfler // #pragma mark -
102261729d93SAxel Dörfler 
102361729d93SAxel Dörfler 
102461729d93SAxel Dörfler /*!	Searches for a specific interface by name.
102561729d93SAxel Dörfler 	You need to have the interface list's lock hold when calling this function.
102661729d93SAxel Dörfler */
102761729d93SAxel Dörfler static struct Interface*
102861729d93SAxel Dörfler find_interface(const char* name)
102961729d93SAxel Dörfler {
103061729d93SAxel Dörfler 	ASSERT_LOCKED_MUTEX(&sLock);
103161729d93SAxel Dörfler 
103261729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
103361729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1034c22d69bfSAxel Dörfler 		if (!strcmp(interface->name, name))
1035c22d69bfSAxel Dörfler 			return interface;
1036c22d69bfSAxel Dörfler 	}
1037c22d69bfSAxel Dörfler 
1038c22d69bfSAxel Dörfler 	return NULL;
1039c22d69bfSAxel Dörfler }
1040c22d69bfSAxel Dörfler 
1041c22d69bfSAxel Dörfler 
104261729d93SAxel Dörfler /*!	Searches for a specific interface by index.
104361729d93SAxel Dörfler 	You need to have the interface list's lock hold when calling this function.
1044c22d69bfSAxel Dörfler */
104561729d93SAxel Dörfler static struct Interface*
104661729d93SAxel Dörfler find_interface(uint32 index)
1047c22d69bfSAxel Dörfler {
104861729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
104961729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1050c22d69bfSAxel Dörfler 		if (interface->index == index)
1051c22d69bfSAxel Dörfler 			return interface;
1052c22d69bfSAxel Dörfler 	}
1053c22d69bfSAxel Dörfler 
1054c22d69bfSAxel Dörfler 	return NULL;
1055c22d69bfSAxel Dörfler }
1056c22d69bfSAxel Dörfler 
1057c22d69bfSAxel Dörfler 
105861729d93SAxel Dörfler // #pragma mark -
105961729d93SAxel Dörfler 
106061729d93SAxel Dörfler 
106161729d93SAxel Dörfler status_t
106261729d93SAxel Dörfler add_interface(const char* name, net_domain_private* domain,
106361729d93SAxel Dörfler 	const ifaliasreq& request, net_device_interface* deviceInterface)
106461729d93SAxel Dörfler {
106561729d93SAxel Dörfler 	MutexLocker locker(sLock);
106661729d93SAxel Dörfler 
106761729d93SAxel Dörfler 	if (find_interface(name) != NULL)
106861729d93SAxel Dörfler 		return B_NAME_IN_USE;
106961729d93SAxel Dörfler 
107061729d93SAxel Dörfler 	Interface* interface
107161729d93SAxel Dörfler 		= new(std::nothrow) Interface(name, deviceInterface);
1072c22d69bfSAxel Dörfler 	if (interface == NULL)
1073c22d69bfSAxel Dörfler 		return B_NO_MEMORY;
1074c22d69bfSAxel Dörfler 
107561729d93SAxel Dörfler 	sInterfaces.Add(interface);
107661729d93SAxel Dörfler 	interface->AcquireReference();
107761729d93SAxel Dörfler 		// We need another reference to be able to use the interface without
107861729d93SAxel Dörfler 		// holding sLock.
1079c22d69bfSAxel Dörfler 
108061729d93SAxel Dörfler 	locker.Unlock();
1081c22d69bfSAxel Dörfler 
108261729d93SAxel Dörfler 	notify_interface_added(interface);
108361729d93SAxel Dörfler 	add_interface_address(interface, domain, request);
1084c22d69bfSAxel Dörfler 
108561729d93SAxel Dörfler 	interface->ReleaseReference();
108627e0dea9SAxel Dörfler 
1087c22d69bfSAxel Dörfler 	return B_OK;
1088c22d69bfSAxel Dörfler }
1089c22d69bfSAxel Dörfler 
1090c22d69bfSAxel Dörfler 
109161729d93SAxel Dörfler /*!	Removes the interface from the list, and puts the stack's reference to it.
109261729d93SAxel Dörfler */
10937aa2819cSAxel Dörfler void
109461729d93SAxel Dörfler remove_interface(Interface* interface)
1095c64feccaSHugo Santos {
10962b1c0755SAxel Dörfler 	interface->SetDown();
10972b1c0755SAxel Dörfler 	interface->RemoveAddresses();
1098c64feccaSHugo Santos 
10992b1c0755SAxel Dörfler 	MutexLocker locker(sLock);
11002b1c0755SAxel Dörfler 	sInterfaces.Remove(interface);
11012b1c0755SAxel Dörfler 	locker.Unlock();
1102f6d219a1SAxel Dörfler 
110361729d93SAxel Dörfler 	notify_interface_removed(interface);
1104c22d69bfSAxel Dörfler 
11052b1c0755SAxel Dörfler 	interface->ReleaseReference();
11067aa2819cSAxel Dörfler }
11077aa2819cSAxel Dörfler 
11087aa2819cSAxel Dörfler 
11097aa2819cSAxel Dörfler /*!	This is called whenever a device interface is being removed. We will get
11107aa2819cSAxel Dörfler 	the corresponding Interface, and remove it.
11117aa2819cSAxel Dörfler */
11127aa2819cSAxel Dörfler void
11137aa2819cSAxel Dörfler interface_removed_device_interface(net_device_interface* deviceInterface)
11147aa2819cSAxel Dörfler {
11157aa2819cSAxel Dörfler 	MutexLocker locker(sLock);
11167aa2819cSAxel Dörfler 
11177aa2819cSAxel Dörfler 	Interface* interface = find_interface(deviceInterface->device->name);
11187aa2819cSAxel Dörfler 	if (interface != NULL)
11197aa2819cSAxel Dörfler 		remove_interface(interface);
1120c22d69bfSAxel Dörfler }
1121c22d69bfSAxel Dörfler 
1122c22d69bfSAxel Dörfler 
112361729d93SAxel Dörfler status_t
112461729d93SAxel Dörfler add_interface_address(Interface* interface, net_domain_private* domain,
112561729d93SAxel Dörfler 	const ifaliasreq& request)
1126c22d69bfSAxel Dörfler {
112761729d93SAxel Dörfler 	// Make sure the family of the provided addresses is valid
112861729d93SAxel Dörfler 	if ((request.ifra_addr.ss_family != domain->family
112961729d93SAxel Dörfler 			&& request.ifra_addr.ss_family != AF_UNSPEC)
113061729d93SAxel Dörfler 		|| (request.ifra_mask.ss_family != domain->family
113161729d93SAxel Dörfler 			&& request.ifra_mask.ss_family != AF_UNSPEC)
113261729d93SAxel Dörfler 		|| (request.ifra_broadaddr.ss_family != domain->family
113361729d93SAxel Dörfler 			&& request.ifra_broadaddr.ss_family != AF_UNSPEC))
113461729d93SAxel Dörfler 		return B_BAD_VALUE;
1135c22d69bfSAxel Dörfler 
113661729d93SAxel Dörfler 	RecursiveLocker locker(interface->Lock());
113761729d93SAxel Dörfler 
113861729d93SAxel Dörfler 	InterfaceAddress* address
113961729d93SAxel Dörfler 		= new(std::nothrow) InterfaceAddress(interface, domain);
114061729d93SAxel Dörfler 	if (address == NULL)
114161729d93SAxel Dörfler 		return B_NO_MEMORY;
114261729d93SAxel Dörfler 
114361729d93SAxel Dörfler 	status_t status = address->SetTo(request);
114461729d93SAxel Dörfler 	if (status == B_OK)
114561729d93SAxel Dörfler 		status = interface->CreateDomainDatalinkIfNeeded(domain);
114661729d93SAxel Dörfler 	if (status == B_OK)
114761729d93SAxel Dörfler 		status = interface->AddAddress(address);
114861729d93SAxel Dörfler 
114961729d93SAxel Dörfler 	if (status == B_OK && address->local != NULL) {
115061729d93SAxel Dörfler 		// update the datalink protocols
115161729d93SAxel Dörfler 		domain_datalink* datalink = interface->DomainDatalink(domain->family);
115261729d93SAxel Dörfler 
115361729d93SAxel Dörfler 		status = datalink->first_protocol->module->change_address(
115461729d93SAxel Dörfler 			datalink->first_protocol, address, SIOCAIFADDR, NULL,
115561729d93SAxel Dörfler 			address->local);
115661729d93SAxel Dörfler 		if (status != B_OK)
115761729d93SAxel Dörfler 			interface->RemoveAddress(address);
115861729d93SAxel Dörfler 	}
115961729d93SAxel Dörfler 	if (status == B_OK)
116061729d93SAxel Dörfler 		notify_interface_changed(interface);
116161729d93SAxel Dörfler 	else
116261729d93SAxel Dörfler 		delete address;
116361729d93SAxel Dörfler 
116461729d93SAxel Dörfler 	return status;
116561729d93SAxel Dörfler }
116661729d93SAxel Dörfler 
116761729d93SAxel Dörfler 
116861729d93SAxel Dörfler status_t
116961729d93SAxel Dörfler update_interface_address(InterfaceAddress* interfaceAddress, int32 option,
117061729d93SAxel Dörfler 	const sockaddr* oldAddress, const sockaddr* newAddress)
117161729d93SAxel Dörfler {
1172b0cf274aSAxel Dörfler 	TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress "
1173b0cf274aSAxel Dörfler 		"%s)\n", __FUNCTION__, interfaceAddress, option,
1174b0cf274aSAxel Dörfler 		AddressString(interfaceAddress->domain, oldAddress).Data(),
1175b0cf274aSAxel Dörfler 		AddressString(interfaceAddress->domain, newAddress).Data());
1176b0cf274aSAxel Dörfler 
117761729d93SAxel Dörfler 	MutexLocker locker(sHashLock);
117861729d93SAxel Dörfler 
117961729d93SAxel Dörfler 	// set logical interface address
118061729d93SAxel Dörfler 	sockaddr** _address = interfaceAddress->AddressFor(option);
118161729d93SAxel Dörfler 	if (_address == NULL)
118261729d93SAxel Dörfler 		return B_BAD_VALUE;
118361729d93SAxel Dörfler 
11842b1c0755SAxel Dörfler 	Interface* interface = (Interface*)interfaceAddress->interface;
11852b1c0755SAxel Dörfler 
11862b1c0755SAxel Dörfler 	interfaceAddress->RemoveDefaultRoutes(option);
11872b1c0755SAxel Dörfler 
11882b1c0755SAxel Dörfler 	if (option == SIOCDIFADDR) {
11892b1c0755SAxel Dörfler 		// Remove address, and release its reference (causing our caller to
11902b1c0755SAxel Dörfler 		// delete it)
11912b1c0755SAxel Dörfler 		locker.Unlock();
11922b1c0755SAxel Dörfler 
11932b1c0755SAxel Dörfler 		invalidate_routes(interfaceAddress);
11942b1c0755SAxel Dörfler 
11952b1c0755SAxel Dörfler 		interface->RemoveAddress(interfaceAddress);
11962b1c0755SAxel Dörfler 		interfaceAddress->ReleaseReference();
11972b1c0755SAxel Dörfler 		return B_OK;
11982b1c0755SAxel Dörfler 	}
11992b1c0755SAxel Dörfler 
120061729d93SAxel Dörfler 	sAddressTable.Remove(interfaceAddress);
120161729d93SAxel Dörfler 
120261729d93SAxel Dörfler 	// Copy new address over
120361729d93SAxel Dörfler 	status_t status = InterfaceAddress::Set(_address, newAddress);
120461729d93SAxel Dörfler 	if (status == B_OK) {
120561729d93SAxel Dörfler 		sockaddr* address = *_address;
120661729d93SAxel Dörfler 
120761729d93SAxel Dörfler 		if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) {
120861729d93SAxel Dörfler 			// Reset netmask and broadcast addresses to defaults
120961729d93SAxel Dörfler 			net_domain* domain = interfaceAddress->domain;
121061729d93SAxel Dörfler 			sockaddr* netmask = NULL;
121161729d93SAxel Dörfler 			const sockaddr* oldNetmask = NULL;
121261729d93SAxel Dörfler 			if (option == SIOCSIFADDR) {
121361729d93SAxel Dörfler 				netmask = InterfaceAddress::Prepare(
121461729d93SAxel Dörfler 					&interfaceAddress->mask, address->sa_len);
121561729d93SAxel Dörfler 			} else {
121661729d93SAxel Dörfler 				oldNetmask = oldAddress;
121761729d93SAxel Dörfler 				netmask = interfaceAddress->mask;
121861729d93SAxel Dörfler 			}
121961729d93SAxel Dörfler 
122061729d93SAxel Dörfler 			// Reset the broadcast address if the address family has
122161729d93SAxel Dörfler 			// such
122261729d93SAxel Dörfler 			sockaddr* broadcast = NULL;
122361729d93SAxel Dörfler 			if ((domain->address_module->flags
122461729d93SAxel Dörfler 					& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) {
122561729d93SAxel Dörfler 				broadcast = InterfaceAddress::Prepare(
122661729d93SAxel Dörfler 					&interfaceAddress->destination, address->sa_len);
122761729d93SAxel Dörfler 			} else
122861729d93SAxel Dörfler 				InterfaceAddress::Set(&interfaceAddress->destination, NULL);
122961729d93SAxel Dörfler 
123061729d93SAxel Dörfler 			domain->address_module->set_to_defaults(netmask, broadcast,
123161729d93SAxel Dörfler 				interfaceAddress->local, oldNetmask);
123261729d93SAxel Dörfler 		}
123361729d93SAxel Dörfler 
12342b1c0755SAxel Dörfler 		interfaceAddress->AddDefaultRoutes(option);
12352b1c0755SAxel Dörfler 		notify_interface_changed(interface);
123661729d93SAxel Dörfler 	}
123761729d93SAxel Dörfler 
123861729d93SAxel Dörfler 	sAddressTable.Insert(interfaceAddress);
123961729d93SAxel Dörfler 	return status;
124061729d93SAxel Dörfler }
124161729d93SAxel Dörfler 
124261729d93SAxel Dörfler 
124361729d93SAxel Dörfler Interface*
124461729d93SAxel Dörfler get_interface(net_domain* domain, uint32 index)
124561729d93SAxel Dörfler {
124661729d93SAxel Dörfler 	MutexLocker locker(sLock);
124761729d93SAxel Dörfler 
124861729d93SAxel Dörfler 	if (index == 0)
124961729d93SAxel Dörfler 		return sInterfaces.First();
125061729d93SAxel Dörfler 
125161729d93SAxel Dörfler 	Interface* interface = find_interface(index);
1252c22d69bfSAxel Dörfler 	if (interface == NULL)
125361729d93SAxel Dörfler 		return NULL;
1254c22d69bfSAxel Dörfler 
125561729d93SAxel Dörfler 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
125661729d93SAxel Dörfler 		return NULL;
125761729d93SAxel Dörfler 
125861729d93SAxel Dörfler 	interface->AcquireReference();
1259c22d69bfSAxel Dörfler 	return interface;
1260c22d69bfSAxel Dörfler }
1261c22d69bfSAxel Dörfler 
126261729d93SAxel Dörfler 
126361729d93SAxel Dörfler Interface*
126461729d93SAxel Dörfler get_interface(net_domain* domain, const char* name)
126561729d93SAxel Dörfler {
126661729d93SAxel Dörfler 	MutexLocker locker(sLock);
126761729d93SAxel Dörfler 
126861729d93SAxel Dörfler 	Interface* interface = find_interface(name);
126961729d93SAxel Dörfler 	if (interface == NULL)
127061729d93SAxel Dörfler 		return NULL;
127161729d93SAxel Dörfler 
127261729d93SAxel Dörfler 	if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
127361729d93SAxel Dörfler 		return NULL;
127461729d93SAxel Dörfler 
127561729d93SAxel Dörfler 	interface->AcquireReference();
127661729d93SAxel Dörfler 	return interface;
127761729d93SAxel Dörfler }
127861729d93SAxel Dörfler 
127961729d93SAxel Dörfler 
128061729d93SAxel Dörfler Interface*
128161729d93SAxel Dörfler get_interface_for_device(net_domain* domain, uint32 index)
128261729d93SAxel Dörfler {
128361729d93SAxel Dörfler 	MutexLocker locker(sLock);
128461729d93SAxel Dörfler 
128561729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
128661729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
128761729d93SAxel Dörfler 		if (interface->device->index == index) {
128861729d93SAxel Dörfler 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
128961729d93SAxel Dörfler 				return NULL;
129061729d93SAxel Dörfler 
129161729d93SAxel Dörfler 			interface->AcquireReference();
129261729d93SAxel Dörfler 			return interface;
129361729d93SAxel Dörfler 		}
129461729d93SAxel Dörfler 	}
129561729d93SAxel Dörfler 
1296c22d69bfSAxel Dörfler 	return NULL;
1297c22d69bfSAxel Dörfler }
1298c22d69bfSAxel Dörfler 
1299c22d69bfSAxel Dörfler 
1300cd08b9f7SAxel Dörfler /*!	Returns a reference to an Interface that matches the given \a linkAddress.
1301cd08b9f7SAxel Dörfler 	The link address is checked against its hardware address, or its interface
1302cd08b9f7SAxel Dörfler 	name, or finally the interface index.
1303cd08b9f7SAxel Dörfler */
1304cd08b9f7SAxel Dörfler Interface*
1305cd08b9f7SAxel Dörfler get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress)
1306cd08b9f7SAxel Dörfler {
1307cd08b9f7SAxel Dörfler 	sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress;
1308cd08b9f7SAxel Dörfler 
1309cd08b9f7SAxel Dörfler 	MutexLocker locker(sLock);
1310cd08b9f7SAxel Dörfler 
1311cd08b9f7SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1312cd08b9f7SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1313cd08b9f7SAxel Dörfler 		// Test if the hardware address matches, or if the given interface
1314cd08b9f7SAxel Dörfler 		// matches, or if at least the index matches.
1315cd08b9f7SAxel Dörfler 		if ((linkAddress.sdl_alen == interface->device->address.length
1316cd08b9f7SAxel Dörfler 				&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
1317cd08b9f7SAxel Dörfler 					linkAddress.sdl_alen) == 0)
1318cd08b9f7SAxel Dörfler 			|| (linkAddress.sdl_nlen > 0
1319cd08b9f7SAxel Dörfler 				&& !strcmp(interface->name, (const char*)linkAddress.sdl_data))
1320cd08b9f7SAxel Dörfler 			|| (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0
1321cd08b9f7SAxel Dörfler 				&& linkAddress.sdl_index == interface->index)) {
1322cd08b9f7SAxel Dörfler 			if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
1323cd08b9f7SAxel Dörfler 				return NULL;
1324cd08b9f7SAxel Dörfler 
1325cd08b9f7SAxel Dörfler 			interface->AcquireReference();
1326cd08b9f7SAxel Dörfler 			return interface;
1327cd08b9f7SAxel Dörfler 		}
1328cd08b9f7SAxel Dörfler 	}
1329cd08b9f7SAxel Dörfler 
1330cd08b9f7SAxel Dörfler 	return NULL;
1331cd08b9f7SAxel Dörfler }
1332cd08b9f7SAxel Dörfler 
1333cd08b9f7SAxel Dörfler 
133461729d93SAxel Dörfler InterfaceAddress*
133561729d93SAxel Dörfler get_interface_address(const sockaddr* local)
1336c22d69bfSAxel Dörfler {
133761729d93SAxel Dörfler 	if (local->sa_family == AF_UNSPEC)
133861729d93SAxel Dörfler 		return NULL;
1339c22d69bfSAxel Dörfler 
134061729d93SAxel Dörfler 	MutexLocker locker(sHashLock);
1341c22d69bfSAxel Dörfler 
134261729d93SAxel Dörfler 	InterfaceAddress* address = sAddressTable.Lookup(local);
134361729d93SAxel Dörfler 	if (address == NULL)
134461729d93SAxel Dörfler 		return NULL;
1345c22d69bfSAxel Dörfler 
134661729d93SAxel Dörfler 	address->AcquireReference();
134761729d93SAxel Dörfler 	return address;
134861729d93SAxel Dörfler }
134961729d93SAxel Dörfler 
135061729d93SAxel Dörfler 
135161729d93SAxel Dörfler InterfaceAddress*
135261729d93SAxel Dörfler get_interface_address_for_destination(net_domain* domain,
1353cd08b9f7SAxel Dörfler 	const sockaddr* destination)
135461729d93SAxel Dörfler {
135561729d93SAxel Dörfler 	MutexLocker locker(sLock);
135661729d93SAxel Dörfler 
135761729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
135861729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
135961729d93SAxel Dörfler 		InterfaceAddress* address
136061729d93SAxel Dörfler 			= interface->AddressForDestination(domain, destination);
136161729d93SAxel Dörfler 		if (address != NULL)
136261729d93SAxel Dörfler 			return address;
136361729d93SAxel Dörfler 	}
136461729d93SAxel Dörfler 
136561729d93SAxel Dörfler 	return NULL;
136661729d93SAxel Dörfler }
136761729d93SAxel Dörfler 
136861729d93SAxel Dörfler 
1369cd08b9f7SAxel Dörfler /*!	Returns a reference to an InterfaceAddress of the specified \a domain that
1370cd08b9f7SAxel Dörfler 	belongs to the interface identified via \a linkAddress. Only the hardware
1371cd08b9f7SAxel Dörfler 	address is matched.
1372cd08b9f7SAxel Dörfler 
1373cd08b9f7SAxel Dörfler 	If \a unconfiguredOnly is set, the interface address must not yet be
1374cd08b9f7SAxel Dörfler 	configured, or must currently be in the process of being configured.
1375cd08b9f7SAxel Dörfler */
137661729d93SAxel Dörfler InterfaceAddress*
1377cd08b9f7SAxel Dörfler get_interface_address_for_link(net_domain* domain, const sockaddr* address,
1378cd08b9f7SAxel Dörfler 	bool unconfiguredOnly)
137961729d93SAxel Dörfler {
1380cd08b9f7SAxel Dörfler 	sockaddr_dl& linkAddress = *(sockaddr_dl*)address;
138161729d93SAxel Dörfler 
138261729d93SAxel Dörfler 	MutexLocker locker(sLock);
138361729d93SAxel Dörfler 
138461729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
138561729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1386cd08b9f7SAxel Dörfler 		// Test if the hardware address matches, or if the given interface
1387cd08b9f7SAxel Dörfler 		// matches, or if at least the index matches.
138861729d93SAxel Dörfler 		if (linkAddress.sdl_alen == interface->device->address.length
138961729d93SAxel Dörfler 			&& memcmp(LLADDR(&linkAddress), interface->device->address.data,
139061729d93SAxel Dörfler 				linkAddress.sdl_alen) == 0) {
1391b0cf274aSAxel Dörfler 			TRACE("  %s matches\n", interface->name);
139261729d93SAxel Dörfler 			// link address matches
139361729d93SAxel Dörfler 			if (unconfiguredOnly)
139461729d93SAxel Dörfler 				return interface->FirstUnconfiguredForFamily(domain->family);
139561729d93SAxel Dörfler 
139661729d93SAxel Dörfler 			return interface->FirstForFamily(domain->family);
139761729d93SAxel Dörfler 		}
139861729d93SAxel Dörfler 	}
139961729d93SAxel Dörfler 
140061729d93SAxel Dörfler 	return NULL;
1401c22d69bfSAxel Dörfler }
1402c22d69bfSAxel Dörfler 
1403c22d69bfSAxel Dörfler 
1404c22d69bfSAxel Dörfler uint32
140561729d93SAxel Dörfler count_interfaces()
1406c22d69bfSAxel Dörfler {
140761729d93SAxel Dörfler 	MutexLocker locker(sLock);
1408c22d69bfSAxel Dörfler 
140961729d93SAxel Dörfler 	return sInterfaces.Count();
1410c22d69bfSAxel Dörfler }
1411c22d69bfSAxel Dörfler 
1412c22d69bfSAxel Dörfler 
14133c13a5f5SAxel Dörfler /*!	Dumps a list of all interfaces into the supplied userland buffer.
1414c22d69bfSAxel Dörfler 	If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
1415c22d69bfSAxel Dörfler 	returned.
1416c22d69bfSAxel Dörfler */
1417c22d69bfSAxel Dörfler status_t
141861729d93SAxel Dörfler list_interfaces(int family, void* _buffer, size_t* bufferSize)
1419c22d69bfSAxel Dörfler {
142061729d93SAxel Dörfler 	MutexLocker locker(sLock);
1421c22d69bfSAxel Dörfler 
1422409b1fc0SHugo Santos 	UserBuffer buffer(_buffer, *bufferSize);
1423c22d69bfSAxel Dörfler 
142461729d93SAxel Dörfler 	InterfaceList::Iterator iterator = sInterfaces.GetIterator();
142561729d93SAxel Dörfler 	while (Interface* interface = iterator.Next()) {
1426715fed44SAxel Dörfler 		// Copy name
1427715fed44SAxel Dörfler 		buffer.Push(interface->name, IF_NAMESIZE);
1428c22d69bfSAxel Dörfler 
1429715fed44SAxel Dörfler 		// Copy address
143061729d93SAxel Dörfler 		InterfaceAddress* address = interface->FirstForFamily(family);
14311f9c8c45SAxel Dörfler 		size_t length = 0;
1432715fed44SAxel Dörfler 
143361729d93SAxel Dörfler 		if (address != NULL && address->local != NULL) {
1434715fed44SAxel Dörfler 			// Actual address
14351f9c8c45SAxel Dörfler 			buffer.Push(address->local, length = address->local->sa_len);
143661729d93SAxel Dörfler 		} else {
1437715fed44SAxel Dörfler 			// Empty address
14381f9c8c45SAxel Dörfler 			sockaddr empty;
14391f9c8c45SAxel Dörfler 			empty.sa_len = 2;
14401f9c8c45SAxel Dörfler 			empty.sa_family = AF_UNSPEC;
14411f9c8c45SAxel Dörfler 			buffer.Push(&empty, length = empty.sa_len);
1442715fed44SAxel Dörfler 		}
1443715fed44SAxel Dörfler 
144461729d93SAxel Dörfler 		if (address != NULL)
144561729d93SAxel Dörfler 			address->ReleaseReference();
144661729d93SAxel Dörfler 
14471f9c8c45SAxel Dörfler 		if (IF_NAMESIZE + length < sizeof(ifreq)) {
14481f9c8c45SAxel Dörfler 			// Make sure at least sizeof(ifreq) bytes are written for each
14491f9c8c45SAxel Dörfler 			// interface for compatibility with other platforms
14501f9c8c45SAxel Dörfler 			buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length);
14511f9c8c45SAxel Dörfler 		}
14521f9c8c45SAxel Dörfler 
14531f9c8c45SAxel Dörfler 		if (buffer.Status() != B_OK)
1454409b1fc0SHugo Santos 			return buffer.Status();
1455c22d69bfSAxel Dörfler 	}
1456c22d69bfSAxel Dörfler 
1457715fed44SAxel Dörfler 	*bufferSize = buffer.BytesConsumed();
1458c22d69bfSAxel Dörfler 	return B_OK;
1459c22d69bfSAxel Dörfler }
1460c22d69bfSAxel Dörfler 
1461c22d69bfSAxel Dörfler 
1462c22d69bfSAxel Dörfler //	#pragma mark -
1463c22d69bfSAxel Dörfler 
1464c22d69bfSAxel Dörfler 
1465c22d69bfSAxel Dörfler status_t
1466c22d69bfSAxel Dörfler init_interfaces()
1467c22d69bfSAxel Dörfler {
146861729d93SAxel Dörfler 	mutex_init(&sLock, "net interfaces");
146961729d93SAxel Dörfler 	mutex_init(&sHashLock, "net local addresses");
1470c22d69bfSAxel Dörfler 
147161729d93SAxel Dörfler 	new (&sInterfaces) InterfaceList;
147261729d93SAxel Dörfler 	new (&sAddressTable) AddressTable;
14739206bb37SAxel Dörfler 		// static C++ objects are not initialized in the module startup
1474a3ec278aSAxel Dörfler 
1475a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1476a3ec278aSAxel Dörfler 	add_debugger_command("net_interface", &dump_interface,
1477a3ec278aSAxel Dörfler 		"Dump the given network interface");
147861729d93SAxel Dörfler 	add_debugger_command("net_interfaces", &dump_interfaces,
147961729d93SAxel Dörfler 		"Dump all network interfaces");
148061729d93SAxel Dörfler 	add_debugger_command("net_local", &dump_local,
148161729d93SAxel Dörfler 		"Dump all local interface addresses");
148261729d93SAxel Dörfler 	add_debugger_command("net_route", &dump_route,
148361729d93SAxel Dörfler 		"Dump the given network route");
1484a3ec278aSAxel Dörfler #endif
1485c22d69bfSAxel Dörfler 	return B_OK;
1486c22d69bfSAxel Dörfler }
1487c22d69bfSAxel Dörfler 
1488c22d69bfSAxel Dörfler 
1489c22d69bfSAxel Dörfler status_t
1490c22d69bfSAxel Dörfler uninit_interfaces()
1491c22d69bfSAxel Dörfler {
1492a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1493a3ec278aSAxel Dörfler 	remove_debugger_command("net_interface", &dump_interface);
1494a3ec278aSAxel Dörfler #endif
1495a3ec278aSAxel Dörfler 
149661729d93SAxel Dörfler 	mutex_destroy(&sLock);
149761729d93SAxel Dörfler 	mutex_destroy(&sHashLock);
1498c22d69bfSAxel Dörfler 	return B_OK;
1499c22d69bfSAxel Dörfler }
1500c22d69bfSAxel Dörfler 
1501