1c22d69bfSAxel Dörfler /*
24ae58630SAxel Dörfler * Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
3c22d69bfSAxel Dörfler * Distributed under the terms of the MIT License.
4c22d69bfSAxel Dörfler *
5c22d69bfSAxel Dörfler * Authors:
6c22d69bfSAxel Dörfler * Axel Dörfler, axeld@pinc-software.de
7c22d69bfSAxel Dörfler */
8c22d69bfSAxel Dörfler
9c22d69bfSAxel Dörfler
10c22d69bfSAxel Dörfler #include "interfaces.h"
11c22d69bfSAxel Dörfler
12c22d69bfSAxel Dörfler #include <net/if_dl.h>
13c22d69bfSAxel Dörfler #include <new>
14a1deb55eSHugo Santos #include <stdio.h>
15c22d69bfSAxel Dörfler #include <stdlib.h>
16c22d69bfSAxel Dörfler #include <string.h>
1761729d93SAxel Dörfler #include <sys/sockio.h>
1861729d93SAxel Dörfler
1961729d93SAxel Dörfler #include <KernelExport.h>
2061729d93SAxel Dörfler
2161729d93SAxel Dörfler #include <net_device.h>
22b0cf274aSAxel Dörfler #include <NetUtilities.h>
2361729d93SAxel Dörfler
2461729d93SAxel Dörfler #include "device_interfaces.h"
2561729d93SAxel Dörfler #include "domains.h"
2661729d93SAxel Dörfler #include "stack_private.h"
2761729d93SAxel Dörfler #include "utility.h"
28c22d69bfSAxel Dörfler
29c22d69bfSAxel Dörfler
3061729d93SAxel Dörfler //#define TRACE_INTERFACES
31c22d69bfSAxel Dörfler #ifdef TRACE_INTERFACES
3261729d93SAxel Dörfler # define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x)
33c22d69bfSAxel Dörfler #else
3461729d93SAxel Dörfler # define TRACE(x...) ;
35c22d69bfSAxel Dörfler #endif
36c22d69bfSAxel Dörfler
3761729d93SAxel Dörfler
3861729d93SAxel Dörfler struct AddressHashDefinition {
3961729d93SAxel Dörfler typedef const sockaddr* KeyType;
4061729d93SAxel Dörfler typedef InterfaceAddress ValueType;
4161729d93SAxel Dörfler
AddressHashDefinitionAddressHashDefinition4261729d93SAxel Dörfler AddressHashDefinition()
4361729d93SAxel Dörfler {
4461729d93SAxel Dörfler }
4561729d93SAxel Dörfler
HashKeyAddressHashDefinition4661729d93SAxel 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
HashAddressHashDefinition5561729d93SAxel Dörfler size_t Hash(InterfaceAddress* address) const
5661729d93SAxel Dörfler {
574ae58630SAxel Dörfler return address->domain->address_module->hash_address(address->local,
584ae58630SAxel Dörfler false);
5961729d93SAxel Dörfler }
6061729d93SAxel Dörfler
CompareAddressHashDefinition6161729d93SAxel Dörfler bool Compare(const KeyType& key, InterfaceAddress* address) const
6261729d93SAxel Dörfler {
6361729d93SAxel Dörfler if (address->local == NULL)
6461729d93SAxel Dörfler return key->sa_family == AF_UNSPEC;
6561729d93SAxel Dörfler
6661729d93SAxel Dörfler if (address->local->sa_family != key->sa_family)
6761729d93SAxel Dörfler return false;
6861729d93SAxel Dörfler
6961729d93SAxel Dörfler return address->domain->address_module->equal_addresses(key,
7061729d93SAxel Dörfler address->local);
7161729d93SAxel Dörfler }
7261729d93SAxel Dörfler
GetLinkAddressHashDefinition7361729d93SAxel Dörfler InterfaceAddress*& GetLink(InterfaceAddress* address) const
7461729d93SAxel Dörfler {
7561729d93SAxel Dörfler return address->HashTableLink();
7661729d93SAxel Dörfler }
7761729d93SAxel Dörfler };
7861729d93SAxel Dörfler
794ae58630SAxel Dörfler typedef BOpenHashTable<AddressHashDefinition, true, false> AddressTable;
80a3ec278aSAxel Dörfler
81c22d69bfSAxel Dörfler
828a6337d0SStefano Ceccherini static recursive_lock sLock;
8361729d93SAxel Dörfler static InterfaceList sInterfaces;
8461729d93SAxel Dörfler static mutex sHashLock;
8561729d93SAxel Dörfler static AddressTable sAddressTable;
86c22d69bfSAxel Dörfler static uint32 sInterfaceIndex;
879261b129SHugo Santos
889261b129SHugo Santos
89ec4fb0f4SAxel Dörfler #if 0
90ec4fb0f4SAxel Dörfler //! For debugging purposes only
91ec4fb0f4SAxel Dörfler void
92ec4fb0f4SAxel Dörfler dump_interface_refs(void)
93ec4fb0f4SAxel Dörfler {
948a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
95ec4fb0f4SAxel Dörfler
96ec4fb0f4SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator();
97ec4fb0f4SAxel Dörfler while (Interface* interface = iterator.Next()) {
98ec4fb0f4SAxel Dörfler dprintf("%p: %s, %ld\n", interface, interface->name,
99ec4fb0f4SAxel Dörfler interface->CountReferences());
100ec4fb0f4SAxel Dörfler }
101ec4fb0f4SAxel Dörfler }
102ec4fb0f4SAxel Dörfler #endif
103ec4fb0f4SAxel Dörfler
104ec4fb0f4SAxel Dörfler
105a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
106a3ec278aSAxel Dörfler
107a3ec278aSAxel Dörfler
108a3ec278aSAxel Dörfler static int
dump_interface(int argc,char ** argv)109a3ec278aSAxel Dörfler dump_interface(int argc, char** argv)
110a3ec278aSAxel Dörfler {
111a3ec278aSAxel Dörfler if (argc != 2) {
11211eccb54SAxel Dörfler kprintf("usage: %s [name|address]\n", argv[0]);
113a3ec278aSAxel Dörfler return 0;
114a3ec278aSAxel Dörfler }
115a3ec278aSAxel Dörfler
11611eccb54SAxel Dörfler Interface* interface = NULL;
11711eccb54SAxel Dörfler
11811eccb54SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator();
11911eccb54SAxel Dörfler while ((interface = iterator.Next()) != NULL) {
12011eccb54SAxel Dörfler if (!strcmp(argv[1], interface->name))
12111eccb54SAxel Dörfler break;
12211eccb54SAxel Dörfler }
12311eccb54SAxel Dörfler
12411eccb54SAxel Dörfler if (interface == NULL)
12511eccb54SAxel Dörfler interface = (Interface*)parse_expression(argv[1]);
12611eccb54SAxel Dörfler
12761729d93SAxel Dörfler interface->Dump();
128a3ec278aSAxel Dörfler
129a3ec278aSAxel Dörfler return 0;
130a3ec278aSAxel Dörfler }
131a3ec278aSAxel Dörfler
132a3ec278aSAxel Dörfler
133a3ec278aSAxel Dörfler static int
dump_interfaces(int argc,char ** argv)13461729d93SAxel Dörfler dump_interfaces(int argc, char** argv)
13561729d93SAxel Dörfler {
13661729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator();
13761729d93SAxel Dörfler while (Interface* interface = iterator.Next()) {
13861729d93SAxel Dörfler kprintf("%p %s\n", interface, interface->name);
13961729d93SAxel Dörfler }
14061729d93SAxel Dörfler return 0;
14161729d93SAxel Dörfler }
14261729d93SAxel Dörfler
14361729d93SAxel Dörfler
14461729d93SAxel Dörfler static int
dump_local(int argc,char ** argv)14561729d93SAxel Dörfler dump_local(int argc, char** argv)
14661729d93SAxel Dörfler {
14761729d93SAxel Dörfler AddressTable::Iterator iterator = sAddressTable.GetIterator();
14861729d93SAxel Dörfler size_t i = 0;
14961729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) {
15061729d93SAxel Dörfler address->Dump(++i);
1516d796a84SAlex Smith dprintf(" hash: %" B_PRIu32 "\n",
15261729d93SAxel Dörfler address->domain->address_module->hash_address(address->local,
15361729d93SAxel Dörfler false));
15461729d93SAxel Dörfler }
15561729d93SAxel Dörfler return 0;
15661729d93SAxel Dörfler }
15761729d93SAxel Dörfler
15861729d93SAxel Dörfler
15961729d93SAxel Dörfler static int
dump_route(int argc,char ** argv)16061729d93SAxel Dörfler dump_route(int argc, char** argv)
161a3ec278aSAxel Dörfler {
162a3ec278aSAxel Dörfler if (argc != 2) {
163a3ec278aSAxel Dörfler kprintf("usage: %s [address]\n", argv[0]);
164a3ec278aSAxel Dörfler return 0;
165a3ec278aSAxel Dörfler }
166a3ec278aSAxel Dörfler
16761729d93SAxel Dörfler net_route* route = (net_route*)parse_expression(argv[1]);
16861729d93SAxel Dörfler kprintf("destination: %p\n", route->destination);
16961729d93SAxel Dörfler kprintf("mask: %p\n", route->mask);
17061729d93SAxel Dörfler kprintf("gateway: %p\n", route->gateway);
17161729d93SAxel Dörfler kprintf("flags: %" B_PRIx32 "\n", route->flags);
17261729d93SAxel Dörfler kprintf("mtu: %" B_PRIu32 "\n", route->mtu);
17361729d93SAxel Dörfler kprintf("interface address: %p\n", route->interface_address);
174a3ec278aSAxel Dörfler
17561729d93SAxel Dörfler if (route->interface_address != NULL) {
17661729d93SAxel Dörfler ((InterfaceAddress*)route->interface_address)->Dump();
177a3ec278aSAxel Dörfler }
178a3ec278aSAxel Dörfler
179a3ec278aSAxel Dörfler return 0;
180a3ec278aSAxel Dörfler }
181a3ec278aSAxel Dörfler
182a3ec278aSAxel Dörfler
183a3ec278aSAxel Dörfler #endif // ENABLE_DEBUGGER_COMMANDS
184a3ec278aSAxel Dörfler
185a3ec278aSAxel Dörfler
InterfaceAddress()18661729d93SAxel Dörfler InterfaceAddress::InterfaceAddress()
187c22d69bfSAxel Dörfler {
18861729d93SAxel Dörfler _Init(NULL, NULL);
18961729d93SAxel Dörfler }
190c22d69bfSAxel Dörfler
19161729d93SAxel Dörfler
InterfaceAddress(net_interface * netInterface,net_domain * netDomain)19261729d93SAxel Dörfler InterfaceAddress::InterfaceAddress(net_interface* netInterface,
19361729d93SAxel Dörfler net_domain* netDomain)
19461729d93SAxel Dörfler {
19561729d93SAxel Dörfler _Init(netInterface, netDomain);
19661729d93SAxel Dörfler }
19761729d93SAxel Dörfler
19861729d93SAxel Dörfler
~InterfaceAddress()19961729d93SAxel Dörfler InterfaceAddress::~InterfaceAddress()
20061729d93SAxel Dörfler {
2012b1c0755SAxel Dörfler TRACE("InterfaceAddress %p: destructor\n", this);
2022b1c0755SAxel Dörfler
2032b1c0755SAxel Dörfler if (interface != NULL && (flags & IFAF_DIRECT_ADDRESS) == 0)
2042b1c0755SAxel Dörfler ((Interface*)interface)->ReleaseReference();
20561729d93SAxel Dörfler }
20661729d93SAxel Dörfler
20761729d93SAxel Dörfler
20861729d93SAxel Dörfler status_t
SetTo(const ifaliasreq & request)20961729d93SAxel Dörfler InterfaceAddress::SetTo(const ifaliasreq& request)
21061729d93SAxel Dörfler {
21161729d93SAxel Dörfler status_t status = SetLocal((const sockaddr*)&request.ifra_addr);
21261729d93SAxel Dörfler if (status == B_OK)
21361729d93SAxel Dörfler status = SetDestination((const sockaddr*)&request.ifra_broadaddr);
21461729d93SAxel Dörfler if (status == B_OK)
21561729d93SAxel Dörfler status = SetMask((const sockaddr*)&request.ifra_mask);
21661729d93SAxel Dörfler
21761729d93SAxel Dörfler return status;
21861729d93SAxel Dörfler }
21961729d93SAxel Dörfler
22061729d93SAxel Dörfler
22161729d93SAxel Dörfler status_t
SetLocal(const sockaddr * to)22261729d93SAxel Dörfler InterfaceAddress::SetLocal(const sockaddr* to)
22361729d93SAxel Dörfler {
22461729d93SAxel Dörfler return Set(&local, to);
22561729d93SAxel Dörfler }
22661729d93SAxel Dörfler
22761729d93SAxel Dörfler
22861729d93SAxel Dörfler status_t
SetDestination(const sockaddr * to)22961729d93SAxel Dörfler InterfaceAddress::SetDestination(const sockaddr* to)
23061729d93SAxel Dörfler {
23161729d93SAxel Dörfler return Set(&destination, to);
23261729d93SAxel Dörfler }
23361729d93SAxel Dörfler
23461729d93SAxel Dörfler
23561729d93SAxel Dörfler status_t
SetMask(const sockaddr * to)23661729d93SAxel Dörfler InterfaceAddress::SetMask(const sockaddr* to)
23761729d93SAxel Dörfler {
23861729d93SAxel Dörfler return Set(&mask, to);
23961729d93SAxel Dörfler }
24061729d93SAxel Dörfler
24161729d93SAxel Dörfler
24261729d93SAxel Dörfler sockaddr**
AddressFor(int32 option)24361729d93SAxel Dörfler InterfaceAddress::AddressFor(int32 option)
24461729d93SAxel Dörfler {
24561729d93SAxel Dörfler switch (option) {
24661729d93SAxel Dörfler case SIOCSIFADDR:
24761729d93SAxel Dörfler case SIOCGIFADDR:
2482b1c0755SAxel Dörfler case SIOCDIFADDR:
24961729d93SAxel Dörfler return &local;
25061729d93SAxel Dörfler
25161729d93SAxel Dörfler case SIOCSIFNETMASK:
25261729d93SAxel Dörfler case SIOCGIFNETMASK:
25361729d93SAxel Dörfler return &mask;
25461729d93SAxel Dörfler
25561729d93SAxel Dörfler case SIOCSIFBRDADDR:
25661729d93SAxel Dörfler case SIOCSIFDSTADDR:
25761729d93SAxel Dörfler case SIOCGIFBRDADDR:
25861729d93SAxel Dörfler case SIOCGIFDSTADDR:
25961729d93SAxel Dörfler return &destination;
26061729d93SAxel Dörfler
26161729d93SAxel Dörfler default:
26261729d93SAxel Dörfler return NULL;
26361729d93SAxel Dörfler }
26461729d93SAxel Dörfler }
26561729d93SAxel Dörfler
26661729d93SAxel Dörfler
2672b1c0755SAxel Dörfler /*! Adds the default routes that every interface address needs, ie. the local
2682b1c0755SAxel Dörfler host route, and one for the subnet (if set).
2692b1c0755SAxel Dörfler */
2702b1c0755SAxel Dörfler void
AddDefaultRoutes(int32 option)2712b1c0755SAxel Dörfler InterfaceAddress::AddDefaultRoutes(int32 option)
2722b1c0755SAxel Dörfler {
2732b1c0755SAxel Dörfler net_route route;
2742b1c0755SAxel Dörfler route.destination = local;
2752b1c0755SAxel Dörfler route.gateway = NULL;
2762b1c0755SAxel Dörfler route.interface_address = this;
2772b1c0755SAxel Dörfler
2782b1c0755SAxel Dörfler if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
2792b1c0755SAxel Dörfler route.mask = mask;
2802b1c0755SAxel Dörfler route.flags = 0;
2812b1c0755SAxel Dörfler add_route(domain, &route);
2822b1c0755SAxel Dörfler }
2832b1c0755SAxel Dörfler
2842b1c0755SAxel Dörfler if (option == SIOCSIFADDR) {
2852b1c0755SAxel Dörfler route.mask = NULL;
2862b1c0755SAxel Dörfler route.flags = RTF_LOCAL | RTF_HOST;
2872b1c0755SAxel Dörfler add_route(domain, &route);
2882b1c0755SAxel Dörfler }
2892b1c0755SAxel Dörfler }
2902b1c0755SAxel Dörfler
2912b1c0755SAxel Dörfler
2922b1c0755SAxel Dörfler /*! Removes the default routes as set by AddDefaultRoutes() again. */
2932b1c0755SAxel Dörfler void
RemoveDefaultRoutes(int32 option)2942b1c0755SAxel Dörfler InterfaceAddress::RemoveDefaultRoutes(int32 option)
2952b1c0755SAxel Dörfler {
2962b1c0755SAxel Dörfler net_route route;
2972b1c0755SAxel Dörfler route.destination = local;
2982b1c0755SAxel Dörfler route.gateway = NULL;
2992b1c0755SAxel Dörfler route.interface_address = this;
3002b1c0755SAxel Dörfler
3012b1c0755SAxel Dörfler if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
3022b1c0755SAxel Dörfler route.mask = mask;
3032b1c0755SAxel Dörfler route.flags = 0;
3042b1c0755SAxel Dörfler remove_route(domain, &route);
3052b1c0755SAxel Dörfler }
3062b1c0755SAxel Dörfler
3072b1c0755SAxel Dörfler if (option == SIOCSIFADDR) {
3082b1c0755SAxel Dörfler route.mask = NULL;
3092b1c0755SAxel Dörfler route.flags = RTF_LOCAL | RTF_HOST;
3102b1c0755SAxel Dörfler remove_route(domain, &route);
3112b1c0755SAxel Dörfler }
3122b1c0755SAxel Dörfler }
3132b1c0755SAxel Dörfler
3142b1c0755SAxel Dörfler
3154ae58630SAxel Dörfler bool
LocalIsDefined() const3164ae58630SAxel Dörfler InterfaceAddress::LocalIsDefined() const
3174ae58630SAxel Dörfler {
3184ae58630SAxel Dörfler return local != NULL && local->sa_family != AF_UNSPEC;
3194ae58630SAxel Dörfler }
3204ae58630SAxel Dörfler
3214ae58630SAxel Dörfler
32261729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
32361729d93SAxel Dörfler
32461729d93SAxel Dörfler
32561729d93SAxel Dörfler void
Dump(size_t index,bool hideInterface)32661729d93SAxel Dörfler InterfaceAddress::Dump(size_t index, bool hideInterface)
32761729d93SAxel Dörfler {
32861729d93SAxel Dörfler if (index)
32961729d93SAxel Dörfler kprintf("%2zu. ", index);
33061729d93SAxel Dörfler else
33161729d93SAxel Dörfler kprintf(" ");
33261729d93SAxel Dörfler
33361729d93SAxel Dörfler if (!hideInterface) {
33461729d93SAxel Dörfler kprintf("interface: %p (%s)\n ", interface,
33561729d93SAxel Dörfler interface != NULL ? interface->name : "-");
33661729d93SAxel Dörfler }
33761729d93SAxel Dörfler
33861729d93SAxel Dörfler kprintf("domain: %p (family %u)\n", domain,
33961729d93SAxel Dörfler domain != NULL ? domain->family : AF_UNSPEC);
34061729d93SAxel Dörfler
34161729d93SAxel Dörfler char buffer[64];
34261729d93SAxel Dörfler if (local != NULL && domain != NULL) {
34361729d93SAxel Dörfler domain->address_module->print_address_buffer(local, buffer,
34461729d93SAxel Dörfler sizeof(buffer), false);
34561729d93SAxel Dörfler } else
34661729d93SAxel Dörfler strcpy(buffer, "-");
34761729d93SAxel Dörfler kprintf(" local: %s\n", buffer);
34861729d93SAxel Dörfler
34961729d93SAxel Dörfler if (mask != NULL && domain != NULL) {
35061729d93SAxel Dörfler domain->address_module->print_address_buffer(mask, buffer,
35161729d93SAxel Dörfler sizeof(buffer), false);
35261729d93SAxel Dörfler } else
35361729d93SAxel Dörfler strcpy(buffer, "-");
35461729d93SAxel Dörfler kprintf(" mask: %s\n", buffer);
35561729d93SAxel Dörfler
35661729d93SAxel Dörfler if (destination != NULL && domain != NULL) {
35761729d93SAxel Dörfler domain->address_module->print_address_buffer(destination, buffer,
35861729d93SAxel Dörfler sizeof(buffer), false);
35961729d93SAxel Dörfler } else
36061729d93SAxel Dörfler strcpy(buffer, "-");
36161729d93SAxel Dörfler kprintf(" destination: %s\n", buffer);
3624af124a1SAxel Dörfler
3634af124a1SAxel Dörfler kprintf(" ref count: %" B_PRId32 "\n", CountReferences());
36461729d93SAxel Dörfler }
36561729d93SAxel Dörfler
36661729d93SAxel Dörfler
36761729d93SAxel Dörfler #endif // ENABLE_DEBUGGER_COMMANDS
36861729d93SAxel Dörfler
36961729d93SAxel Dörfler
37061729d93SAxel Dörfler /*static*/ status_t
Set(sockaddr ** _address,const sockaddr * to)37161729d93SAxel Dörfler InterfaceAddress::Set(sockaddr** _address, const sockaddr* to)
37261729d93SAxel Dörfler {
37361729d93SAxel Dörfler sockaddr* address = *_address;
37461729d93SAxel Dörfler
37561729d93SAxel Dörfler if (to == NULL || to->sa_family == AF_UNSPEC) {
37661729d93SAxel Dörfler // Clear address
37761729d93SAxel Dörfler free(address);
37861729d93SAxel Dörfler *_address = NULL;
37961729d93SAxel Dörfler return B_OK;
38061729d93SAxel Dörfler }
38161729d93SAxel Dörfler
38261729d93SAxel Dörfler // Set address
38361729d93SAxel Dörfler
38461729d93SAxel Dörfler size_t size = max_c(to->sa_len, sizeof(sockaddr));
38561729d93SAxel Dörfler if (size > sizeof(sockaddr_storage))
38661729d93SAxel Dörfler size = sizeof(sockaddr_storage);
38761729d93SAxel Dörfler
38861729d93SAxel Dörfler address = Prepare(_address, size);
38961729d93SAxel Dörfler if (address == NULL)
39061729d93SAxel Dörfler return B_NO_MEMORY;
39161729d93SAxel Dörfler
39261729d93SAxel Dörfler memcpy(address, to, size);
39361729d93SAxel Dörfler address->sa_len = size;
39461729d93SAxel Dörfler
39561729d93SAxel Dörfler return B_OK;
39661729d93SAxel Dörfler }
39761729d93SAxel Dörfler
39861729d93SAxel Dörfler
3995ebd9548SAxel Dörfler /*! Makes sure that the sockaddr object pointed to by \a _address is large
4005ebd9548SAxel Dörfler enough to hold \a size bytes.
4015ebd9548SAxel Dörfler \a _address may point to NULL when calling this method.
4025ebd9548SAxel Dörfler */
40361729d93SAxel Dörfler /*static*/ sockaddr*
Prepare(sockaddr ** _address,size_t size)40461729d93SAxel Dörfler InterfaceAddress::Prepare(sockaddr** _address, size_t size)
40561729d93SAxel Dörfler {
40661729d93SAxel Dörfler size = max_c(size, sizeof(sockaddr));
40761729d93SAxel Dörfler if (size > sizeof(sockaddr_storage))
40861729d93SAxel Dörfler size = sizeof(sockaddr_storage);
40961729d93SAxel Dörfler
41061729d93SAxel Dörfler sockaddr* address = *_address;
41161729d93SAxel Dörfler
412ab1adabfSDario Casalinuovo if (address == NULL || size > address->sa_len) {
413ab1adabfSDario Casalinuovo sockaddr* resized = (sockaddr*)realloc(address, size);
414ab1adabfSDario Casalinuovo if (resized == NULL) {
415ab1adabfSDario Casalinuovo free(address);
416ab1adabfSDario Casalinuovo return NULL;
417ab1adabfSDario Casalinuovo }
418ab1adabfSDario Casalinuovo
419ab1adabfSDario Casalinuovo address = resized;
420ab1adabfSDario Casalinuovo }
421466081d0SPhil Costin
42261729d93SAxel Dörfler address->sa_len = size;
42361729d93SAxel Dörfler
42461729d93SAxel Dörfler *_address = address;
42561729d93SAxel Dörfler return address;
42661729d93SAxel Dörfler }
42761729d93SAxel Dörfler
42861729d93SAxel Dörfler
42961729d93SAxel Dörfler void
_Init(net_interface * netInterface,net_domain * netDomain)43061729d93SAxel Dörfler InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain)
43161729d93SAxel Dörfler {
4322b1c0755SAxel Dörfler TRACE("InterfaceAddress %p: init interface %p, domain %p\n", this,
4332b1c0755SAxel Dörfler netInterface, netDomain);
4342b1c0755SAxel Dörfler
43561729d93SAxel Dörfler interface = netInterface;
43661729d93SAxel Dörfler domain = netDomain;
43761729d93SAxel Dörfler local = NULL;
43861729d93SAxel Dörfler destination = NULL;
43961729d93SAxel Dörfler mask = NULL;
4402b1c0755SAxel Dörfler flags = 0;
4412b1c0755SAxel Dörfler
4422b1c0755SAxel Dörfler if (interface != NULL)
4432b1c0755SAxel Dörfler ((Interface*)interface)->AcquireReference();
44461729d93SAxel Dörfler }
44561729d93SAxel Dörfler
44661729d93SAxel Dörfler
44761729d93SAxel Dörfler // #pragma mark -
44861729d93SAxel Dörfler
44961729d93SAxel Dörfler
Interface(const char * interfaceName,net_device_interface * deviceInterface)45061729d93SAxel Dörfler Interface::Interface(const char* interfaceName,
45161729d93SAxel Dörfler net_device_interface* deviceInterface)
452ff8c8dfcSStefano Ceccherini :
453ff8c8dfcSStefano Ceccherini fBusy(false)
45461729d93SAxel Dörfler {
45561729d93SAxel Dörfler TRACE("Interface %p: new \"%s\", device interface %p\n", this,
45661729d93SAxel Dörfler interfaceName, deviceInterface);
45761729d93SAxel Dörfler
458b0cf274aSAxel Dörfler int written = strlcpy(name, interfaceName, IF_NAMESIZE);
459b0cf274aSAxel Dörfler memset(name + written, 0, IF_NAMESIZE - written);
460b0cf274aSAxel Dörfler // Clear remaining space
461b0cf274aSAxel Dörfler
46261729d93SAxel Dörfler device = deviceInterface->device;
46361729d93SAxel Dörfler
46461729d93SAxel Dörfler index = ++sInterfaceIndex;
46561729d93SAxel Dörfler flags = 0;
46661729d93SAxel Dörfler type = 0;
46761729d93SAxel Dörfler metric = 0;
46861729d93SAxel Dörfler
46961729d93SAxel Dörfler fDeviceInterface = acquire_device_interface(deviceInterface);
47061729d93SAxel Dörfler
47161729d93SAxel Dörfler recursive_lock_init(&fLock, name);
47261729d93SAxel Dörfler
47361729d93SAxel Dörfler // Grab a reference to the networking stack, to make sure it won't be
47461729d93SAxel Dörfler // unloaded as long as an interface exists
47561729d93SAxel Dörfler module_info* module;
47661729d93SAxel Dörfler get_module(gNetStackInterfaceModule.info.name, &module);
47761729d93SAxel Dörfler }
47861729d93SAxel Dörfler
47961729d93SAxel Dörfler
~Interface()48061729d93SAxel Dörfler Interface::~Interface()
48161729d93SAxel Dörfler {
4822b1c0755SAxel Dörfler TRACE("Interface %p: destructor\n", this);
483*91f94b82SAugustin Cavalier ASSERT((flags & IFF_UP) == 0);
4842b1c0755SAxel Dörfler
4852b1c0755SAxel Dörfler // Uninitialize the domain datalink protocols
4862b1c0755SAxel Dörfler
4872b1c0755SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
4882b1c0755SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) {
4892b1c0755SAxel Dörfler put_domain_datalink_protocols(this, datalink->domain);
4902b1c0755SAxel Dörfler }
4912b1c0755SAxel Dörfler
4922b1c0755SAxel Dörfler // Free domain datalink objects
4932b1c0755SAxel Dörfler
4942b1c0755SAxel Dörfler domain_datalink* next = fDatalinkTable.Clear(true);
4952b1c0755SAxel Dörfler while (next != NULL) {
4962b1c0755SAxel Dörfler domain_datalink* datalink = next;
4972b1c0755SAxel Dörfler next = next->hash_link;
4982b1c0755SAxel Dörfler
4992b1c0755SAxel Dörfler delete datalink;
5002b1c0755SAxel Dörfler }
5012b1c0755SAxel Dörfler
5029923dd5cSJackBurton79 put_device_interface(fDeviceInterface);
5039923dd5cSJackBurton79
50461729d93SAxel Dörfler recursive_lock_destroy(&fLock);
50561729d93SAxel Dörfler
50661729d93SAxel Dörfler // Release reference of the stack - at this point, our stack may be unloaded
50761729d93SAxel Dörfler // if no other interfaces or sockets are left
50861729d93SAxel Dörfler put_module(gNetStackInterfaceModule.info.name);
50961729d93SAxel Dörfler }
51061729d93SAxel Dörfler
51161729d93SAxel Dörfler
51261729d93SAxel Dörfler /*! Returns a reference to the first InterfaceAddress that is from the same
51361729d93SAxel Dörfler as the specified \a family.
51461729d93SAxel Dörfler */
51561729d93SAxel Dörfler InterfaceAddress*
FirstForFamily(int family)51661729d93SAxel Dörfler Interface::FirstForFamily(int family)
51761729d93SAxel Dörfler {
51861729d93SAxel Dörfler RecursiveLocker locker(fLock);
51961729d93SAxel Dörfler
52061729d93SAxel Dörfler InterfaceAddress* address = _FirstForFamily(family);
52161729d93SAxel Dörfler if (address != NULL) {
52261729d93SAxel Dörfler address->AcquireReference();
52361729d93SAxel Dörfler return address;
52461729d93SAxel Dörfler }
52561729d93SAxel Dörfler
52661729d93SAxel Dörfler return NULL;
52761729d93SAxel Dörfler }
52861729d93SAxel Dörfler
52961729d93SAxel Dörfler
53061729d93SAxel Dörfler /*! Returns a reference to the first unconfigured address of this interface
53161729d93SAxel Dörfler for the specified \a family.
53261729d93SAxel Dörfler */
53361729d93SAxel Dörfler InterfaceAddress*
FirstUnconfiguredForFamily(int family)53461729d93SAxel Dörfler Interface::FirstUnconfiguredForFamily(int family)
53561729d93SAxel Dörfler {
53661729d93SAxel Dörfler RecursiveLocker locker(fLock);
53761729d93SAxel Dörfler
53861729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator();
53961729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) {
54061729d93SAxel Dörfler if (address->domain->family == family
54161729d93SAxel Dörfler && (address->local == NULL
54261729d93SAxel Dörfler // TODO: this has to be solved differently!!
54361729d93SAxel Dörfler || (flags & IFF_CONFIGURING) != 0)) {
54461729d93SAxel Dörfler address->AcquireReference();
54561729d93SAxel Dörfler return address;
54661729d93SAxel Dörfler }
54761729d93SAxel Dörfler }
54861729d93SAxel Dörfler
54961729d93SAxel Dörfler return NULL;
55061729d93SAxel Dörfler }
55161729d93SAxel Dörfler
55261729d93SAxel Dörfler
55361729d93SAxel Dörfler /*! Returns a reference to the InterfaceAddress that has the specified
55461729d93SAxel Dörfler \a destination address.
55561729d93SAxel Dörfler */
55661729d93SAxel Dörfler InterfaceAddress*
AddressForDestination(net_domain * domain,const sockaddr * destination)55761729d93SAxel Dörfler Interface::AddressForDestination(net_domain* domain,
55861729d93SAxel Dörfler const sockaddr* destination)
55961729d93SAxel Dörfler {
56061729d93SAxel Dörfler RecursiveLocker locker(fLock);
56161729d93SAxel Dörfler
56261729d93SAxel Dörfler if ((device->flags & IFF_BROADCAST) == 0) {
56361729d93SAxel Dörfler // The device does not support broadcasting
56461729d93SAxel Dörfler return NULL;
56561729d93SAxel Dörfler }
56661729d93SAxel Dörfler
56761729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator();
56861729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) {
56961729d93SAxel Dörfler if (address->domain == domain
57061729d93SAxel Dörfler && address->destination != NULL
57161729d93SAxel Dörfler && domain->address_module->equal_addresses(address->destination,
57261729d93SAxel Dörfler destination)) {
57361729d93SAxel Dörfler address->AcquireReference();
57461729d93SAxel Dörfler return address;
57561729d93SAxel Dörfler }
57661729d93SAxel Dörfler }
57761729d93SAxel Dörfler
57861729d93SAxel Dörfler return NULL;
57961729d93SAxel Dörfler }
58061729d93SAxel Dörfler
58161729d93SAxel Dörfler
582910ffb32SAxel Dörfler /*! Returns a reference to the InterfaceAddress that has the specified
583910ffb32SAxel Dörfler \a local address.
584910ffb32SAxel Dörfler */
585910ffb32SAxel Dörfler InterfaceAddress*
AddressForLocal(net_domain * domain,const sockaddr * local)586910ffb32SAxel Dörfler Interface::AddressForLocal(net_domain* domain, const sockaddr* local)
587910ffb32SAxel Dörfler {
588910ffb32SAxel Dörfler RecursiveLocker locker(fLock);
589910ffb32SAxel Dörfler
590910ffb32SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator();
591910ffb32SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) {
592910ffb32SAxel Dörfler if (address->domain == domain
593910ffb32SAxel Dörfler && address->local != NULL
594910ffb32SAxel Dörfler && domain->address_module->equal_addresses(address->local, local)) {
595910ffb32SAxel Dörfler address->AcquireReference();
596910ffb32SAxel Dörfler return address;
597910ffb32SAxel Dörfler }
598910ffb32SAxel Dörfler }
599910ffb32SAxel Dörfler
600910ffb32SAxel Dörfler return NULL;
601910ffb32SAxel Dörfler }
602910ffb32SAxel Dörfler
603910ffb32SAxel Dörfler
60461729d93SAxel Dörfler status_t
AddAddress(InterfaceAddress * address)60561729d93SAxel Dörfler Interface::AddAddress(InterfaceAddress* address)
60661729d93SAxel Dörfler {
60761729d93SAxel Dörfler net_domain* domain = address->domain;
60861729d93SAxel Dörfler if (domain == NULL)
60961729d93SAxel Dörfler return B_BAD_VALUE;
61061729d93SAxel Dörfler
61161729d93SAxel Dörfler RecursiveLocker locker(fLock);
61261729d93SAxel Dörfler fAddresses.Add(address);
61361729d93SAxel Dörfler locker.Unlock();
61461729d93SAxel Dörfler
6154ae58630SAxel Dörfler if (address->LocalIsDefined()) {
61661729d93SAxel Dörfler MutexLocker hashLocker(sHashLock);
61761729d93SAxel Dörfler sAddressTable.Insert(address);
6184ae58630SAxel Dörfler }
61961729d93SAxel Dörfler return B_OK;
62061729d93SAxel Dörfler }
62161729d93SAxel Dörfler
62261729d93SAxel Dörfler
62361729d93SAxel Dörfler void
RemoveAddress(InterfaceAddress * address)62461729d93SAxel Dörfler Interface::RemoveAddress(InterfaceAddress* address)
62561729d93SAxel Dörfler {
62661729d93SAxel Dörfler net_domain* domain = address->domain;
62761729d93SAxel Dörfler if (domain == NULL)
62861729d93SAxel Dörfler return;
62961729d93SAxel Dörfler
63061729d93SAxel Dörfler RecursiveLocker locker(fLock);
63161729d93SAxel Dörfler
63261729d93SAxel Dörfler fAddresses.Remove(address);
63361729d93SAxel Dörfler address->GetDoublyLinkedListLink()->next = NULL;
63461729d93SAxel Dörfler
63561729d93SAxel Dörfler locker.Unlock();
63661729d93SAxel Dörfler
6374ae58630SAxel Dörfler if (address->LocalIsDefined()) {
63861729d93SAxel Dörfler MutexLocker hashLocker(sHashLock);
63961729d93SAxel Dörfler sAddressTable.Remove(address);
64061729d93SAxel Dörfler }
6414ae58630SAxel Dörfler }
64261729d93SAxel Dörfler
64361729d93SAxel Dörfler
64461729d93SAxel Dörfler bool
GetNextAddress(InterfaceAddress ** _address)64561729d93SAxel Dörfler Interface::GetNextAddress(InterfaceAddress** _address)
64661729d93SAxel Dörfler {
64761729d93SAxel Dörfler RecursiveLocker locker(fLock);
64861729d93SAxel Dörfler
64961729d93SAxel Dörfler InterfaceAddress* address = *_address;
65061729d93SAxel Dörfler if (address == NULL) {
65161729d93SAxel Dörfler // get first address
65261729d93SAxel Dörfler address = fAddresses.First();
65361729d93SAxel Dörfler } else {
65461729d93SAxel Dörfler // get next, if possible
65561729d93SAxel Dörfler InterfaceAddress* next = fAddresses.GetNext(address);
65661729d93SAxel Dörfler address->ReleaseReference();
65761729d93SAxel Dörfler address = next;
65861729d93SAxel Dörfler }
65961729d93SAxel Dörfler
66061729d93SAxel Dörfler *_address = address;
66161729d93SAxel Dörfler
66261729d93SAxel Dörfler if (address == NULL)
66361729d93SAxel Dörfler return false;
66461729d93SAxel Dörfler
66561729d93SAxel Dörfler address->AcquireReference();
66661729d93SAxel Dörfler return true;
66761729d93SAxel Dörfler }
66861729d93SAxel Dörfler
66961729d93SAxel Dörfler
6709d771afbSAxel Dörfler InterfaceAddress*
AddressAt(size_t index)6719d771afbSAxel Dörfler Interface::AddressAt(size_t index)
6729d771afbSAxel Dörfler {
6739d771afbSAxel Dörfler RecursiveLocker locker(fLock);
6749d771afbSAxel Dörfler
6759d771afbSAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator();
6769d771afbSAxel Dörfler size_t i = 0;
6779d771afbSAxel Dörfler
6789d771afbSAxel Dörfler while (InterfaceAddress* address = iterator.Next()) {
6799d771afbSAxel Dörfler if (i++ == index) {
6809d771afbSAxel Dörfler address->AcquireReference();
6819d771afbSAxel Dörfler return address;
6829d771afbSAxel Dörfler }
6839d771afbSAxel Dörfler }
6849d771afbSAxel Dörfler
6859d771afbSAxel Dörfler return NULL;
6869d771afbSAxel Dörfler }
6879d771afbSAxel Dörfler
6889d771afbSAxel Dörfler
6892c12b8a3SAxel Dörfler int32
IndexOfAddress(InterfaceAddress * address)6902c12b8a3SAxel Dörfler Interface::IndexOfAddress(InterfaceAddress* address)
6912c12b8a3SAxel Dörfler {
692b0766602SAxel Dörfler if (address == NULL)
693b0766602SAxel Dörfler return -1;
694b0766602SAxel Dörfler
6952c12b8a3SAxel Dörfler RecursiveLocker locker(fLock);
6962c12b8a3SAxel Dörfler
6972c12b8a3SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator();
6982c12b8a3SAxel Dörfler int32 index = 0;
6992c12b8a3SAxel Dörfler
7002c12b8a3SAxel Dörfler while (iterator.HasNext()) {
7012c12b8a3SAxel Dörfler if (address == iterator.Next())
7022c12b8a3SAxel Dörfler return index;
7032c12b8a3SAxel Dörfler
7042c12b8a3SAxel Dörfler index++;
7052c12b8a3SAxel Dörfler }
7062c12b8a3SAxel Dörfler
7072c12b8a3SAxel Dörfler return -1;
7082c12b8a3SAxel Dörfler }
7092c12b8a3SAxel Dörfler
7102c12b8a3SAxel Dörfler
7119d771afbSAxel Dörfler size_t
CountAddresses()7129d771afbSAxel Dörfler Interface::CountAddresses()
7139d771afbSAxel Dörfler {
7149d771afbSAxel Dörfler RecursiveLocker locker(fLock);
7159d771afbSAxel Dörfler return fAddresses.Count();
7169d771afbSAxel Dörfler }
7179d771afbSAxel Dörfler
7189d771afbSAxel Dörfler
7192b1c0755SAxel Dörfler void
RemoveAddresses()7202b1c0755SAxel Dörfler Interface::RemoveAddresses()
7212b1c0755SAxel Dörfler {
7222b1c0755SAxel Dörfler RecursiveLocker locker(fLock);
7232b1c0755SAxel Dörfler
7242b1c0755SAxel Dörfler while (InterfaceAddress* address = fAddresses.RemoveHead()) {
725b0766602SAxel Dörfler locker.Unlock();
726b0766602SAxel Dörfler
727b0766602SAxel Dörfler if (address->LocalIsDefined()) {
728b0766602SAxel Dörfler MutexLocker hashLocker(sHashLock);
729b0766602SAxel Dörfler sAddressTable.Remove(address);
730b0766602SAxel Dörfler }
7315ebd9548SAxel Dörfler address->ReleaseReference();
732b0766602SAxel Dörfler
733b0766602SAxel Dörfler locker.Lock();
7342b1c0755SAxel Dörfler }
7352b1c0755SAxel Dörfler }
7362b1c0755SAxel Dörfler
7372b1c0755SAxel Dörfler
7389d771afbSAxel Dörfler /*! This is called in order to call the correct methods of the datalink
7399d771afbSAxel Dörfler protocols, ie. it will translate address changes to
7409d771afbSAxel Dörfler net_datalink_protocol::change_address(), and IFF_UP changes to
7419d771afbSAxel Dörfler net_datalink_protocol::interface_up(), and interface_down().
7429d771afbSAxel Dörfler
7439d771afbSAxel Dörfler Everything else is passed unchanged to net_datalink_protocol::control().
7449d771afbSAxel Dörfler */
74561729d93SAxel Dörfler status_t
Control(net_domain * domain,int32 option,ifreq & request,ifreq * userRequest,size_t length)74661729d93SAxel Dörfler Interface::Control(net_domain* domain, int32 option, ifreq& request,
74761729d93SAxel Dörfler ifreq* userRequest, size_t length)
74861729d93SAxel Dörfler {
74961729d93SAxel Dörfler switch (option) {
75061729d93SAxel Dörfler case SIOCSIFFLAGS:
75161729d93SAxel Dörfler {
752e8802e49SAxel Dörfler if (length != sizeof(ifreq))
753e8802e49SAxel Dörfler return B_BAD_VALUE;
754e8802e49SAxel Dörfler
75561729d93SAxel Dörfler uint32 requestFlags = request.ifr_flags;
75661729d93SAxel Dörfler uint32 oldFlags = flags;
75761729d93SAxel Dörfler status_t status = B_OK;
75861729d93SAxel Dörfler
75961729d93SAxel Dörfler request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST);
76061729d93SAxel Dörfler
76161729d93SAxel Dörfler if ((requestFlags & IFF_UP) != (flags & IFF_UP)) {
76261729d93SAxel Dörfler if ((requestFlags & IFF_UP) != 0)
76361729d93SAxel Dörfler status = _SetUp();
76461729d93SAxel Dörfler else
7652b1c0755SAxel Dörfler SetDown();
76661729d93SAxel Dörfler }
76761729d93SAxel Dörfler
76861729d93SAxel Dörfler if (status == B_OK) {
76961729d93SAxel Dörfler // TODO: maybe allow deleting IFF_BROADCAST on the interface
77061729d93SAxel Dörfler // level?
77161729d93SAxel Dörfler flags &= IFF_UP | IFF_LINK | IFF_BROADCAST;
77261729d93SAxel Dörfler flags |= request.ifr_flags;
77361729d93SAxel Dörfler }
77461729d93SAxel Dörfler
775e78fea43SAxel Dörfler if (oldFlags != flags) {
776e78fea43SAxel Dörfler TRACE("Interface %p: flags changed from %" B_PRIx32 " to %"
777e78fea43SAxel Dörfler B_PRIx32 "\n", this, oldFlags, flags);
77861729d93SAxel Dörfler notify_interface_changed(this, oldFlags, flags);
779e78fea43SAxel Dörfler }
78061729d93SAxel Dörfler
78161729d93SAxel Dörfler return status;
78261729d93SAxel Dörfler }
78361729d93SAxel Dörfler
7842b1c0755SAxel Dörfler case B_SOCKET_SET_ALIAS:
7859d771afbSAxel Dörfler {
786e8802e49SAxel Dörfler if (length != sizeof(ifaliasreq))
787e8802e49SAxel Dörfler return B_BAD_VALUE;
788e8802e49SAxel Dörfler
7899d771afbSAxel Dörfler RecursiveLocker locker(fLock);
7909d771afbSAxel Dörfler
7919d771afbSAxel Dörfler ifaliasreq aliasRequest;
7929d771afbSAxel Dörfler if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq))
7939d771afbSAxel Dörfler != B_OK)
7949d771afbSAxel Dörfler return B_BAD_ADDRESS;
7959d771afbSAxel Dörfler
796910ffb32SAxel Dörfler InterfaceAddress* address = NULL;
797910ffb32SAxel Dörfler if (aliasRequest.ifra_index < 0) {
798910ffb32SAxel Dörfler if (!domain->address_module->is_empty_address(
799910ffb32SAxel Dörfler (const sockaddr*)&aliasRequest.ifra_addr, false)) {
800910ffb32SAxel Dörfler // Find first address that matches the local address
801910ffb32SAxel Dörfler address = AddressForLocal(domain,
802910ffb32SAxel Dörfler (const sockaddr*)&aliasRequest.ifra_addr);
803910ffb32SAxel Dörfler }
804910ffb32SAxel Dörfler if (address == NULL) {
805910ffb32SAxel Dörfler // Find first address for family
806910ffb32SAxel Dörfler address = FirstForFamily(domain->family);
807910ffb32SAxel Dörfler }
808a271028eSAxel Dörfler if (address == NULL) {
809a271028eSAxel Dörfler // Create new on the fly
810a271028eSAxel Dörfler address = new(std::nothrow) InterfaceAddress(this, domain);
811a271028eSAxel Dörfler if (address == NULL)
812a271028eSAxel Dörfler return B_NO_MEMORY;
813a271028eSAxel Dörfler
814a271028eSAxel Dörfler status_t status = AddAddress(address);
815095f97a6SAxel Dörfler if (status != B_OK) {
816095f97a6SAxel Dörfler delete address;
817a271028eSAxel Dörfler return status;
818095f97a6SAxel Dörfler }
819a271028eSAxel Dörfler
820a271028eSAxel Dörfler // Note, even if setting the address failed, the empty
821a271028eSAxel Dörfler // address added here will still be added to the interface.
8228dcde8b1SAxel Dörfler address->AcquireReference();
823a271028eSAxel Dörfler }
824910ffb32SAxel Dörfler } else
825910ffb32SAxel Dörfler address = AddressAt(aliasRequest.ifra_index);
826910ffb32SAxel Dörfler
8279d771afbSAxel Dörfler if (address == NULL)
8289d771afbSAxel Dörfler return B_BAD_VALUE;
8299d771afbSAxel Dörfler
8309d771afbSAxel Dörfler status_t status = B_OK;
8319d771afbSAxel Dörfler
8329d771afbSAxel Dörfler if (!domain->address_module->equal_addresses(
8339d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_addr, address->local)) {
8349d771afbSAxel Dörfler status = _ChangeAddress(locker, address, SIOCSIFADDR,
8359d771afbSAxel Dörfler address->local, (sockaddr*)&aliasRequest.ifra_addr);
8369d771afbSAxel Dörfler }
8379d771afbSAxel Dörfler
8389d771afbSAxel Dörfler if (status == B_OK && !domain->address_module->equal_addresses(
839910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_mask, address->mask)
840910ffb32SAxel Dörfler && !domain->address_module->is_empty_address(
841910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_mask, false)) {
8429d771afbSAxel Dörfler status = _ChangeAddress(locker, address, SIOCSIFNETMASK,
8439d771afbSAxel Dörfler address->mask, (sockaddr*)&aliasRequest.ifra_mask);
8449d771afbSAxel Dörfler }
8459d771afbSAxel Dörfler
8469d771afbSAxel Dörfler if (status == B_OK && !domain->address_module->equal_addresses(
8479d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination,
848910ffb32SAxel Dörfler address->destination)
849910ffb32SAxel Dörfler && !domain->address_module->is_empty_address(
850910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination, false)) {
8519d771afbSAxel Dörfler status = _ChangeAddress(locker, address,
8529d771afbSAxel Dörfler (domain->address_module->flags
8539d771afbSAxel Dörfler & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0
8549d771afbSAxel Dörfler ? SIOCSIFBRDADDR : SIOCSIFDSTADDR,
8559d771afbSAxel Dörfler address->destination,
8569d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination);
8579d771afbSAxel Dörfler }
8589d771afbSAxel Dörfler
8599d771afbSAxel Dörfler address->ReleaseReference();
8609d771afbSAxel Dörfler return status;
8619d771afbSAxel Dörfler }
8629d771afbSAxel Dörfler
86361729d93SAxel Dörfler case SIOCSIFADDR:
86461729d93SAxel Dörfler case SIOCSIFNETMASK:
86561729d93SAxel Dörfler case SIOCSIFBRDADDR:
86661729d93SAxel Dörfler case SIOCSIFDSTADDR:
86761729d93SAxel Dörfler case SIOCDIFADDR:
86861729d93SAxel Dörfler {
869e8802e49SAxel Dörfler if (length != sizeof(ifreq))
870e8802e49SAxel Dörfler return B_BAD_VALUE;
871e8802e49SAxel Dörfler
87261729d93SAxel Dörfler RecursiveLocker locker(fLock);
87361729d93SAxel Dörfler
87461729d93SAxel Dörfler InterfaceAddress* address = NULL;
87561729d93SAxel Dörfler sockaddr_storage newAddress;
87661729d93SAxel Dörfler
87761729d93SAxel Dörfler size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr));
87861729d93SAxel Dörfler if (size > sizeof(sockaddr_storage))
87961729d93SAxel Dörfler size = sizeof(sockaddr_storage);
88061729d93SAxel Dörfler
88161729d93SAxel Dörfler if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK)
88261729d93SAxel Dörfler return B_BAD_ADDRESS;
88361729d93SAxel Dörfler
88461729d93SAxel Dörfler if (option == SIOCDIFADDR) {
88561729d93SAxel Dörfler // Find referring address - we can't use the hash, as another
88661729d93SAxel Dörfler // interface might use the same address.
88761729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator();
88861729d93SAxel Dörfler while ((address = iterator.Next()) != NULL) {
88961729d93SAxel Dörfler if (address->domain == domain
89061729d93SAxel Dörfler && domain->address_module->equal_addresses(
89161729d93SAxel Dörfler address->local, (sockaddr*)&newAddress))
89261729d93SAxel Dörfler break;
89361729d93SAxel Dörfler }
89461729d93SAxel Dörfler
89561729d93SAxel Dörfler if (address == NULL)
89661729d93SAxel Dörfler return B_BAD_VALUE;
89778abd727SAxel Dörfler } else {
89878abd727SAxel Dörfler // Just use the first address for this family
89978abd727SAxel Dörfler address = _FirstForFamily(domain->family);
90078abd727SAxel Dörfler if (address == NULL) {
90178abd727SAxel Dörfler // Create new on the fly
90278abd727SAxel Dörfler address = new(std::nothrow) InterfaceAddress(this, domain);
90378abd727SAxel Dörfler if (address == NULL)
90478abd727SAxel Dörfler return B_NO_MEMORY;
90578abd727SAxel Dörfler
90678abd727SAxel Dörfler status_t status = AddAddress(address);
907095f97a6SAxel Dörfler if (status != B_OK) {
908095f97a6SAxel Dörfler delete address;
90978abd727SAxel Dörfler return status;
910095f97a6SAxel Dörfler }
91178abd727SAxel Dörfler
91278abd727SAxel Dörfler // Note, even if setting the address failed, the empty
91378abd727SAxel Dörfler // address added here will still be added to the interface.
91478abd727SAxel Dörfler }
91578abd727SAxel Dörfler }
91661729d93SAxel Dörfler
9179d771afbSAxel Dörfler return _ChangeAddress(locker, address, option,
9189d771afbSAxel Dörfler *address->AddressFor(option),
91961729d93SAxel Dörfler option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL);
92061729d93SAxel Dörfler }
92161729d93SAxel Dörfler
92261729d93SAxel Dörfler default:
92361729d93SAxel Dörfler // pass the request into the datalink protocol stack
92461729d93SAxel Dörfler domain_datalink* datalink = DomainDatalink(domain->family);
92561729d93SAxel Dörfler if (datalink->first_info != NULL) {
92661729d93SAxel Dörfler return datalink->first_info->control(
92761729d93SAxel Dörfler datalink->first_protocol, option, userRequest, length);
92861729d93SAxel Dörfler }
92961729d93SAxel Dörfler break;
93061729d93SAxel Dörfler }
93161729d93SAxel Dörfler
93261729d93SAxel Dörfler return B_BAD_VALUE;
93361729d93SAxel Dörfler }
93461729d93SAxel Dörfler
93561729d93SAxel Dörfler
9362b1c0755SAxel Dörfler void
SetDown()9372b1c0755SAxel Dörfler Interface::SetDown()
9382b1c0755SAxel Dörfler {
9392b1c0755SAxel Dörfler if ((flags & IFF_UP) == 0)
9402b1c0755SAxel Dörfler return;
9412b1c0755SAxel Dörfler
9427ed2a443SStefano Ceccherini RecursiveLocker interfacesLocker(sLock);
943ff8c8dfcSStefano Ceccherini
944ff8c8dfcSStefano Ceccherini if (IsBusy())
945ff8c8dfcSStefano Ceccherini return;
946ff8c8dfcSStefano Ceccherini
947ff8c8dfcSStefano Ceccherini SetBusy(true);
9487ed2a443SStefano Ceccherini interfacesLocker.Unlock();
9492b1c0755SAxel Dörfler
9502b1c0755SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
9512b1c0755SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) {
9522b1c0755SAxel Dörfler datalink->first_info->interface_down(datalink->first_protocol);
9532b1c0755SAxel Dörfler }
9542b1c0755SAxel Dörfler
9552b1c0755SAxel Dörfler flags &= ~IFF_UP;
956ff8c8dfcSStefano Ceccherini
957ff8c8dfcSStefano Ceccherini SetBusy(false);
9582b1c0755SAxel Dörfler }
9592b1c0755SAxel Dörfler
9602b1c0755SAxel Dörfler
9612b1c0755SAxel Dörfler /*! Called when a device lost its IFF_UP status. We will invalidate all
9622b1c0755SAxel Dörfler interface routes here.
9632b1c0755SAxel Dörfler */
9642b1c0755SAxel Dörfler void
WentDown()9652b1c0755SAxel Dörfler Interface::WentDown()
9662b1c0755SAxel Dörfler {
967ed18d7cfSAxel Dörfler TRACE("Interface %p: went down\n", this);
968ed18d7cfSAxel Dörfler
9692b1c0755SAxel Dörfler RecursiveLocker locker(fLock);
9702b1c0755SAxel Dörfler
9712b1c0755SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator();
9722b1c0755SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) {
9732b1c0755SAxel Dörfler if (address->domain != NULL)
9742b1c0755SAxel Dörfler invalidate_routes(address->domain, this);
9752b1c0755SAxel Dörfler }
9762b1c0755SAxel Dörfler }
9772b1c0755SAxel Dörfler
9782b1c0755SAxel Dörfler
97961729d93SAxel Dörfler status_t
CreateDomainDatalinkIfNeeded(net_domain * domain)98061729d93SAxel Dörfler Interface::CreateDomainDatalinkIfNeeded(net_domain* domain)
98161729d93SAxel Dörfler {
98261729d93SAxel Dörfler RecursiveLocker locker(fLock);
98361729d93SAxel Dörfler
98461729d93SAxel Dörfler if (fDatalinkTable.Lookup(domain->family) != NULL)
98561729d93SAxel Dörfler return B_OK;
98661729d93SAxel Dörfler
98761729d93SAxel Dörfler TRACE("Interface %p: create domain datalink for domain %p\n", this, domain);
98861729d93SAxel Dörfler
98961729d93SAxel Dörfler domain_datalink* datalink = new(std::nothrow) domain_datalink;
99061729d93SAxel Dörfler if (datalink == NULL)
99161729d93SAxel Dörfler return B_NO_MEMORY;
99261729d93SAxel Dörfler
993ed18d7cfSAxel Dörfler datalink->first_protocol = NULL;
994ed18d7cfSAxel Dörfler datalink->first_info = NULL;
99561729d93SAxel Dörfler datalink->domain = domain;
99661729d93SAxel Dörfler
99761729d93SAxel Dörfler // setup direct route for bound devices
99861729d93SAxel Dörfler datalink->direct_route.destination = NULL;
99961729d93SAxel Dörfler datalink->direct_route.mask = NULL;
100061729d93SAxel Dörfler datalink->direct_route.gateway = NULL;
100161729d93SAxel Dörfler datalink->direct_route.flags = 0;
100261729d93SAxel Dörfler datalink->direct_route.mtu = 0;
100361729d93SAxel Dörfler datalink->direct_route.interface_address = &datalink->direct_address;
100461729d93SAxel Dörfler datalink->direct_route.ref_count = 1;
100561729d93SAxel Dörfler // make sure this doesn't get deleted accidently
100661729d93SAxel Dörfler
100761729d93SAxel Dörfler // provide its link back to the interface
100861729d93SAxel Dörfler datalink->direct_address.local = NULL;
100961729d93SAxel Dörfler datalink->direct_address.destination = NULL;
101061729d93SAxel Dörfler datalink->direct_address.mask = NULL;
101161729d93SAxel Dörfler datalink->direct_address.domain = domain;
101261729d93SAxel Dörfler datalink->direct_address.interface = this;
10132b1c0755SAxel Dörfler datalink->direct_address.flags = IFAF_DIRECT_ADDRESS;
101461729d93SAxel Dörfler
101561729d93SAxel Dörfler fDatalinkTable.Insert(datalink);
101661729d93SAxel Dörfler
101761729d93SAxel Dörfler status_t status = get_domain_datalink_protocols(this, domain);
101861729d93SAxel Dörfler if (status == B_OK)
101961729d93SAxel Dörfler return B_OK;
102061729d93SAxel Dörfler
102161729d93SAxel Dörfler fDatalinkTable.Remove(datalink);
102261729d93SAxel Dörfler delete datalink;
102361729d93SAxel Dörfler
102461729d93SAxel Dörfler return status;
102561729d93SAxel Dörfler }
102661729d93SAxel Dörfler
102761729d93SAxel Dörfler
102861729d93SAxel Dörfler domain_datalink*
DomainDatalink(uint8 family)102961729d93SAxel Dörfler Interface::DomainDatalink(uint8 family)
103061729d93SAxel Dörfler {
103161729d93SAxel Dörfler // Note: domain datalinks cannot be removed while the interface is alive,
103261729d93SAxel Dörfler // since this would require us either to hold the lock while calling this
103361729d93SAxel Dörfler // function, or introduce reference counting for the domain_datalink
103461729d93SAxel Dörfler // structure.
103561729d93SAxel Dörfler RecursiveLocker locker(fLock);
103661729d93SAxel Dörfler return fDatalinkTable.Lookup(family);
103761729d93SAxel Dörfler }
103861729d93SAxel Dörfler
103961729d93SAxel Dörfler
104061729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
104161729d93SAxel Dörfler
104261729d93SAxel Dörfler
104361729d93SAxel Dörfler void
Dump() const104461729d93SAxel Dörfler Interface::Dump() const
104561729d93SAxel Dörfler {
104661729d93SAxel Dörfler kprintf("name: %s\n", name);
104761729d93SAxel Dörfler kprintf("device: %p\n", device);
104861729d93SAxel Dörfler kprintf("device_interface: %p\n", fDeviceInterface);
104961729d93SAxel Dörfler kprintf("index: %" B_PRIu32 "\n", index);
105061729d93SAxel Dörfler kprintf("flags: %#" B_PRIx32 "\n", flags);
105161729d93SAxel Dörfler kprintf("type: %u\n", type);
105261729d93SAxel Dörfler kprintf("metric: %" B_PRIu32 "\n", metric);
1053ed18d7cfSAxel Dörfler kprintf("ref count: %" B_PRId32 "\n", CountReferences());
105461729d93SAxel Dörfler
105561729d93SAxel Dörfler kprintf("datalink protocols:\n");
105661729d93SAxel Dörfler
105761729d93SAxel Dörfler DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator();
105861729d93SAxel Dörfler size_t i = 0;
105961729d93SAxel Dörfler while (domain_datalink* datalink = datalinkIterator.Next()) {
106061729d93SAxel Dörfler kprintf("%2zu. domain: %p\n", ++i, datalink->domain);
106161729d93SAxel Dörfler kprintf(" first_protocol: %p\n", datalink->first_protocol);
106261729d93SAxel Dörfler kprintf(" first_info: %p\n", datalink->first_info);
106361729d93SAxel Dörfler kprintf(" direct_route: %p\n", &datalink->direct_route);
106461729d93SAxel Dörfler }
106561729d93SAxel Dörfler
106661729d93SAxel Dörfler kprintf("addresses:\n");
106761729d93SAxel Dörfler
106861729d93SAxel Dörfler AddressList::ConstIterator iterator = fAddresses.GetIterator();
106961729d93SAxel Dörfler i = 0;
107061729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) {
107161729d93SAxel Dörfler address->Dump(++i, true);
107261729d93SAxel Dörfler }
107361729d93SAxel Dörfler }
107461729d93SAxel Dörfler
107561729d93SAxel Dörfler
107661729d93SAxel Dörfler #endif // ENABLE_DEBUGGER_COMMANDS
107761729d93SAxel Dörfler
107861729d93SAxel Dörfler
107961729d93SAxel Dörfler status_t
_SetUp()108061729d93SAxel Dörfler Interface::_SetUp()
108161729d93SAxel Dörfler {
108261729d93SAxel Dörfler status_t status = up_device_interface(fDeviceInterface);
108361729d93SAxel Dörfler if (status != B_OK)
108461729d93SAxel Dörfler return status;
108561729d93SAxel Dörfler
1086ff8c8dfcSStefano Ceccherini RecursiveLocker interfacesLocker(sLock);
1087ff8c8dfcSStefano Ceccherini SetBusy(true);
1088ff8c8dfcSStefano Ceccherini interfacesLocker.Unlock();
1089ff8c8dfcSStefano Ceccherini
10902b1c0755SAxel Dörfler // Propagate flag to all datalink protocols
109161729d93SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
109261729d93SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) {
109361729d93SAxel Dörfler status = datalink->first_info->interface_up(datalink->first_protocol);
109461729d93SAxel Dörfler if (status != B_OK) {
109561729d93SAxel Dörfler // Revert "up" status
109661729d93SAxel Dörfler DatalinkTable::Iterator secondIterator
109761729d93SAxel Dörfler = fDatalinkTable.GetIterator();
109861729d93SAxel Dörfler while (secondIterator.HasNext()) {
109961729d93SAxel Dörfler domain_datalink* secondDatalink = secondIterator.Next();
110061729d93SAxel Dörfler if (secondDatalink == NULL || secondDatalink == datalink)
1101c22d69bfSAxel Dörfler break;
1102c22d69bfSAxel Dörfler
110361729d93SAxel Dörfler secondDatalink->first_info->interface_down(
110461729d93SAxel Dörfler secondDatalink->first_protocol);
110561729d93SAxel Dörfler }
110661729d93SAxel Dörfler
110761729d93SAxel Dörfler down_device_interface(fDeviceInterface);
1108ff8c8dfcSStefano Ceccherini SetBusy(false);
110961729d93SAxel Dörfler return status;
111061729d93SAxel Dörfler }
111161729d93SAxel Dörfler }
111261729d93SAxel Dörfler
11132b1c0755SAxel Dörfler // Add default routes for the existing addresses
11142b1c0755SAxel Dörfler
11152b1c0755SAxel Dörfler AddressList::Iterator addressIterator = fAddresses.GetIterator();
11162b1c0755SAxel Dörfler while (InterfaceAddress* address = addressIterator.Next()) {
11172b1c0755SAxel Dörfler address->AddDefaultRoutes(SIOCSIFADDR);
11182b1c0755SAxel Dörfler }
11192b1c0755SAxel Dörfler
112061729d93SAxel Dörfler flags |= IFF_UP;
1121ff8c8dfcSStefano Ceccherini SetBusy(false);
1122ff8c8dfcSStefano Ceccherini
112361729d93SAxel Dörfler return B_OK;
112461729d93SAxel Dörfler }
112561729d93SAxel Dörfler
112661729d93SAxel Dörfler
112761729d93SAxel Dörfler InterfaceAddress*
_FirstForFamily(int family)112861729d93SAxel Dörfler Interface::_FirstForFamily(int family)
112961729d93SAxel Dörfler {
113061729d93SAxel Dörfler ASSERT_LOCKED_RECURSIVE(&fLock);
113161729d93SAxel Dörfler
113261729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator();
113361729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) {
113461729d93SAxel Dörfler if (address->domain != NULL && address->domain->family == family)
113561729d93SAxel Dörfler return address;
113661729d93SAxel Dörfler }
113761729d93SAxel Dörfler
113861729d93SAxel Dörfler return NULL;
113961729d93SAxel Dörfler }
114061729d93SAxel Dörfler
114161729d93SAxel Dörfler
11429d771afbSAxel Dörfler status_t
_ChangeAddress(RecursiveLocker & locker,InterfaceAddress * address,int32 option,const sockaddr * originalAddress,const sockaddr * requestedAddress)11439d771afbSAxel Dörfler Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address,
1144b0cf274aSAxel Dörfler int32 option, const sockaddr* originalAddress,
1145b0cf274aSAxel Dörfler const sockaddr* requestedAddress)
11469d771afbSAxel Dörfler {
1147b0cf274aSAxel Dörfler // Copy old address
11489d771afbSAxel Dörfler sockaddr_storage oldAddress;
11499d771afbSAxel Dörfler if (address->domain->address_module->set_to((sockaddr*)&oldAddress,
11509d771afbSAxel Dörfler originalAddress) != B_OK)
11519d771afbSAxel Dörfler oldAddress.ss_family = AF_UNSPEC;
11529d771afbSAxel Dörfler
1153b0cf274aSAxel Dörfler // Copy new address (this also makes sure that sockaddr::sa_len is set
1154b0cf274aSAxel Dörfler // correctly)
1155b0cf274aSAxel Dörfler sockaddr_storage newAddress;
1156b0cf274aSAxel Dörfler if (address->domain->address_module->set_to((sockaddr*)&newAddress,
1157b0cf274aSAxel Dörfler requestedAddress) != B_OK)
1158b0cf274aSAxel Dörfler newAddress.ss_family = AF_UNSPEC;
1159b0cf274aSAxel Dörfler
11606b1e1488SAxel Dörfler // Test if anything changed for real
1161b0cf274aSAxel Dörfler if (address->domain->address_module->equal_addresses(
1162b0cf274aSAxel Dörfler (sockaddr*)&oldAddress, (sockaddr*)&newAddress)) {
11636b1e1488SAxel Dörfler // Nothing to do
1164b0cf274aSAxel Dörfler TRACE(" option %" B_PRId32 " addresses are equal!\n", option);
11656b1e1488SAxel Dörfler return B_OK;
11666b1e1488SAxel Dörfler }
11676b1e1488SAxel Dörfler
11689d771afbSAxel Dörfler // TODO: mark this address busy or call while holding the lock!
11699d771afbSAxel Dörfler address->AcquireReference();
11709d771afbSAxel Dörfler locker.Unlock();
11719d771afbSAxel Dörfler
11729d771afbSAxel Dörfler domain_datalink* datalink = DomainDatalink(address->domain);
11739d771afbSAxel Dörfler status_t status = datalink->first_protocol->module->change_address(
11749d771afbSAxel Dörfler datalink->first_protocol, address, option,
11759d771afbSAxel Dörfler oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL,
1176b0cf274aSAxel Dörfler newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL);
11779d771afbSAxel Dörfler
11789d771afbSAxel Dörfler locker.Lock();
11799d771afbSAxel Dörfler address->ReleaseReference();
11809d771afbSAxel Dörfler return status;
11819d771afbSAxel Dörfler }
11829d771afbSAxel Dörfler
11839d771afbSAxel Dörfler
118461729d93SAxel Dörfler // #pragma mark -
118561729d93SAxel Dörfler
118661729d93SAxel Dörfler
118761729d93SAxel Dörfler /*! Searches for a specific interface by name.
118861729d93SAxel Dörfler You need to have the interface list's lock hold when calling this function.
118961729d93SAxel Dörfler */
11908844a67eSAugustin Cavalier static Interface*
find_interface(const char * name)119161729d93SAxel Dörfler find_interface(const char* name)
119261729d93SAxel Dörfler {
11938a6337d0SStefano Ceccherini ASSERT_LOCKED_RECURSIVE(&sLock);
119461729d93SAxel Dörfler
119561729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator();
119661729d93SAxel Dörfler while (Interface* interface = iterator.Next()) {
1197c22d69bfSAxel Dörfler if (!strcmp(interface->name, name))
1198c22d69bfSAxel Dörfler return interface;
1199c22d69bfSAxel Dörfler }
1200c22d69bfSAxel Dörfler
1201c22d69bfSAxel Dörfler return NULL;
1202c22d69bfSAxel Dörfler }
1203c22d69bfSAxel Dörfler
1204c22d69bfSAxel Dörfler
120561729d93SAxel Dörfler /*! Searches for a specific interface by index.
120661729d93SAxel Dörfler You need to have the interface list's lock hold when calling this function.
1207c22d69bfSAxel Dörfler */
12088844a67eSAugustin Cavalier static Interface*
find_interface(uint32 index)120961729d93SAxel Dörfler find_interface(uint32 index)
1210c22d69bfSAxel Dörfler {
12112828ed2fSAugustin Cavalier ASSERT_LOCKED_RECURSIVE(&sLock);
12122828ed2fSAugustin Cavalier
121361729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator();
121461729d93SAxel Dörfler while (Interface* interface = iterator.Next()) {
1215c22d69bfSAxel Dörfler if (interface->index == index)
1216c22d69bfSAxel Dörfler return interface;
1217c22d69bfSAxel Dörfler }
1218c22d69bfSAxel Dörfler
1219c22d69bfSAxel Dörfler return NULL;
1220c22d69bfSAxel Dörfler }
1221c22d69bfSAxel Dörfler
1222c22d69bfSAxel Dörfler
122361729d93SAxel Dörfler // #pragma mark -
122461729d93SAxel Dörfler
122561729d93SAxel Dörfler
122661729d93SAxel Dörfler status_t
add_interface(const char * name,net_domain_private * domain,const ifaliasreq & request,net_device_interface * deviceInterface)122761729d93SAxel Dörfler add_interface(const char* name, net_domain_private* domain,
122861729d93SAxel Dörfler const ifaliasreq& request, net_device_interface* deviceInterface)
122961729d93SAxel Dörfler {
12308a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
123161729d93SAxel Dörfler
123261729d93SAxel Dörfler if (find_interface(name) != NULL)
123361729d93SAxel Dörfler return B_NAME_IN_USE;
123461729d93SAxel Dörfler
123561729d93SAxel Dörfler Interface* interface
123661729d93SAxel Dörfler = new(std::nothrow) Interface(name, deviceInterface);
1237c22d69bfSAxel Dörfler if (interface == NULL)
1238c22d69bfSAxel Dörfler return B_NO_MEMORY;
1239c22d69bfSAxel Dörfler
124061729d93SAxel Dörfler sInterfaces.Add(interface);
124161729d93SAxel Dörfler interface->AcquireReference();
124261729d93SAxel Dörfler // We need another reference to be able to use the interface without
124361729d93SAxel Dörfler // holding sLock.
1244c22d69bfSAxel Dörfler
124561729d93SAxel Dörfler locker.Unlock();
1246c22d69bfSAxel Dörfler
12474ae58630SAxel Dörfler status_t status = add_interface_address(interface, domain, request);
12484ae58630SAxel Dörfler if (status == B_OK)
124961729d93SAxel Dörfler notify_interface_added(interface);
12504ae58630SAxel Dörfler else {
12514ae58630SAxel Dörfler locker.Lock();
12524ae58630SAxel Dörfler sInterfaces.Remove(interface);
12534ae58630SAxel Dörfler locker.Unlock();
12544ae58630SAxel Dörfler interface->ReleaseReference();
12554ae58630SAxel Dörfler }
1256c22d69bfSAxel Dörfler
125761729d93SAxel Dörfler interface->ReleaseReference();
125827e0dea9SAxel Dörfler
12594ae58630SAxel Dörfler return status;
1260c22d69bfSAxel Dörfler }
1261c22d69bfSAxel Dörfler
1262c22d69bfSAxel Dörfler
126361729d93SAxel Dörfler /*! Removes the interface from the list, and puts the stack's reference to it.
126461729d93SAxel Dörfler */
12657aa2819cSAxel Dörfler void
remove_interface(Interface * interface)126661729d93SAxel Dörfler remove_interface(Interface* interface)
1267c64feccaSHugo Santos {
12682b1c0755SAxel Dörfler interface->SetDown();
12692b1c0755SAxel Dörfler interface->RemoveAddresses();
1270c64feccaSHugo Santos
12718a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
12722b1c0755SAxel Dörfler sInterfaces.Remove(interface);
12732b1c0755SAxel Dörfler locker.Unlock();
1274f6d219a1SAxel Dörfler
127561729d93SAxel Dörfler notify_interface_removed(interface);
1276c22d69bfSAxel Dörfler
12772b1c0755SAxel Dörfler interface->ReleaseReference();
12787aa2819cSAxel Dörfler }
12797aa2819cSAxel Dörfler
12807aa2819cSAxel Dörfler
12817aa2819cSAxel Dörfler /*! This is called whenever a device interface is being removed. We will get
12827aa2819cSAxel Dörfler the corresponding Interface, and remove it.
12837aa2819cSAxel Dörfler */
12847aa2819cSAxel Dörfler void
interface_removed_device_interface(net_device_interface * deviceInterface)12857aa2819cSAxel Dörfler interface_removed_device_interface(net_device_interface* deviceInterface)
12867aa2819cSAxel Dörfler {
12878a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
12887aa2819cSAxel Dörfler
12897aa2819cSAxel Dörfler Interface* interface = find_interface(deviceInterface->device->name);
12907aa2819cSAxel Dörfler if (interface != NULL)
12917aa2819cSAxel Dörfler remove_interface(interface);
1292c22d69bfSAxel Dörfler }
1293c22d69bfSAxel Dörfler
1294c22d69bfSAxel Dörfler
129561729d93SAxel Dörfler status_t
add_interface_address(Interface * interface,net_domain_private * domain,const ifaliasreq & request)129661729d93SAxel Dörfler add_interface_address(Interface* interface, net_domain_private* domain,
129761729d93SAxel Dörfler const ifaliasreq& request)
1298c22d69bfSAxel Dörfler {
129961729d93SAxel Dörfler // Make sure the family of the provided addresses is valid
130061729d93SAxel Dörfler if ((request.ifra_addr.ss_family != domain->family
130161729d93SAxel Dörfler && request.ifra_addr.ss_family != AF_UNSPEC)
130261729d93SAxel Dörfler || (request.ifra_mask.ss_family != domain->family
130361729d93SAxel Dörfler && request.ifra_mask.ss_family != AF_UNSPEC)
130461729d93SAxel Dörfler || (request.ifra_broadaddr.ss_family != domain->family
130561729d93SAxel Dörfler && request.ifra_broadaddr.ss_family != AF_UNSPEC))
130661729d93SAxel Dörfler return B_BAD_VALUE;
1307c22d69bfSAxel Dörfler
130861729d93SAxel Dörfler RecursiveLocker locker(interface->Lock());
130961729d93SAxel Dörfler
131061729d93SAxel Dörfler InterfaceAddress* address
131161729d93SAxel Dörfler = new(std::nothrow) InterfaceAddress(interface, domain);
131261729d93SAxel Dörfler if (address == NULL)
131361729d93SAxel Dörfler return B_NO_MEMORY;
131461729d93SAxel Dörfler
131561729d93SAxel Dörfler status_t status = address->SetTo(request);
131661729d93SAxel Dörfler if (status == B_OK)
131761729d93SAxel Dörfler status = interface->CreateDomainDatalinkIfNeeded(domain);
131861729d93SAxel Dörfler if (status == B_OK)
131961729d93SAxel Dörfler status = interface->AddAddress(address);
132061729d93SAxel Dörfler
132161729d93SAxel Dörfler if (status == B_OK && address->local != NULL) {
132261729d93SAxel Dörfler // update the datalink protocols
132361729d93SAxel Dörfler domain_datalink* datalink = interface->DomainDatalink(domain->family);
132461729d93SAxel Dörfler
132561729d93SAxel Dörfler status = datalink->first_protocol->module->change_address(
132661729d93SAxel Dörfler datalink->first_protocol, address, SIOCAIFADDR, NULL,
132761729d93SAxel Dörfler address->local);
132861729d93SAxel Dörfler if (status != B_OK)
132961729d93SAxel Dörfler interface->RemoveAddress(address);
133061729d93SAxel Dörfler }
133161729d93SAxel Dörfler if (status == B_OK)
133261729d93SAxel Dörfler notify_interface_changed(interface);
133361729d93SAxel Dörfler else
133461729d93SAxel Dörfler delete address;
133561729d93SAxel Dörfler
133661729d93SAxel Dörfler return status;
133761729d93SAxel Dörfler }
133861729d93SAxel Dörfler
133961729d93SAxel Dörfler
134061729d93SAxel Dörfler status_t
update_interface_address(InterfaceAddress * interfaceAddress,int32 option,const sockaddr * oldAddress,const sockaddr * newAddress)134161729d93SAxel Dörfler update_interface_address(InterfaceAddress* interfaceAddress, int32 option,
134261729d93SAxel Dörfler const sockaddr* oldAddress, const sockaddr* newAddress)
134361729d93SAxel Dörfler {
1344b0cf274aSAxel Dörfler TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress "
1345b0cf274aSAxel Dörfler "%s)\n", __FUNCTION__, interfaceAddress, option,
1346b0cf274aSAxel Dörfler AddressString(interfaceAddress->domain, oldAddress).Data(),
1347b0cf274aSAxel Dörfler AddressString(interfaceAddress->domain, newAddress).Data());
1348b0cf274aSAxel Dörfler
134961729d93SAxel Dörfler MutexLocker locker(sHashLock);
135061729d93SAxel Dörfler
135161729d93SAxel Dörfler // set logical interface address
135261729d93SAxel Dörfler sockaddr** _address = interfaceAddress->AddressFor(option);
135361729d93SAxel Dörfler if (_address == NULL)
135461729d93SAxel Dörfler return B_BAD_VALUE;
135561729d93SAxel Dörfler
13562b1c0755SAxel Dörfler Interface* interface = (Interface*)interfaceAddress->interface;
13572b1c0755SAxel Dörfler
13582b1c0755SAxel Dörfler interfaceAddress->RemoveDefaultRoutes(option);
13592b1c0755SAxel Dörfler
13602b1c0755SAxel Dörfler if (option == SIOCDIFADDR) {
13612b1c0755SAxel Dörfler // Remove address, and release its reference (causing our caller to
13622b1c0755SAxel Dörfler // delete it)
13632b1c0755SAxel Dörfler locker.Unlock();
13642b1c0755SAxel Dörfler
13652b1c0755SAxel Dörfler invalidate_routes(interfaceAddress);
13662b1c0755SAxel Dörfler
13672b1c0755SAxel Dörfler interface->RemoveAddress(interfaceAddress);
13682b1c0755SAxel Dörfler interfaceAddress->ReleaseReference();
13692b1c0755SAxel Dörfler return B_OK;
13702b1c0755SAxel Dörfler }
13712b1c0755SAxel Dörfler
13724ae58630SAxel Dörfler if (interfaceAddress->LocalIsDefined())
137361729d93SAxel Dörfler sAddressTable.Remove(interfaceAddress);
137461729d93SAxel Dörfler
137561729d93SAxel Dörfler // Copy new address over
137661729d93SAxel Dörfler status_t status = InterfaceAddress::Set(_address, newAddress);
137761729d93SAxel Dörfler if (status == B_OK) {
137861729d93SAxel Dörfler sockaddr* address = *_address;
137961729d93SAxel Dörfler
13805ebd9548SAxel Dörfler if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) {
138161729d93SAxel Dörfler // Reset netmask and broadcast addresses to defaults
138261729d93SAxel Dörfler net_domain* domain = interfaceAddress->domain;
13835ebd9548SAxel Dörfler sockaddr* defaultNetmask = NULL;
13845ebd9548SAxel Dörfler const sockaddr* netmask = NULL;
138561729d93SAxel Dörfler if (option == SIOCSIFADDR) {
13865ebd9548SAxel Dörfler defaultNetmask = InterfaceAddress::Prepare(
138761729d93SAxel Dörfler &interfaceAddress->mask, address->sa_len);
13885ebd9548SAxel Dörfler } else
13895ebd9548SAxel Dörfler netmask = newAddress;
139061729d93SAxel Dörfler
139161729d93SAxel Dörfler // Reset the broadcast address if the address family has
139261729d93SAxel Dörfler // such
13935ebd9548SAxel Dörfler sockaddr* defaultBroadcast = NULL;
139461729d93SAxel Dörfler if ((domain->address_module->flags
139561729d93SAxel Dörfler & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) {
13965ebd9548SAxel Dörfler defaultBroadcast = InterfaceAddress::Prepare(
139761729d93SAxel Dörfler &interfaceAddress->destination, address->sa_len);
139861729d93SAxel Dörfler } else
139961729d93SAxel Dörfler InterfaceAddress::Set(&interfaceAddress->destination, NULL);
140061729d93SAxel Dörfler
14015ebd9548SAxel Dörfler domain->address_module->set_to_defaults(defaultNetmask,
14025ebd9548SAxel Dörfler defaultBroadcast, interfaceAddress->local, netmask);
140361729d93SAxel Dörfler }
140461729d93SAxel Dörfler
14052b1c0755SAxel Dörfler interfaceAddress->AddDefaultRoutes(option);
14062b1c0755SAxel Dörfler notify_interface_changed(interface);
140761729d93SAxel Dörfler }
140861729d93SAxel Dörfler
14094ae58630SAxel Dörfler if (interfaceAddress->LocalIsDefined())
141061729d93SAxel Dörfler sAddressTable.Insert(interfaceAddress);
141161729d93SAxel Dörfler return status;
141261729d93SAxel Dörfler }
141361729d93SAxel Dörfler
141461729d93SAxel Dörfler
141561729d93SAxel Dörfler Interface*
get_interface(net_domain * domain,uint32 index)141661729d93SAxel Dörfler get_interface(net_domain* domain, uint32 index)
141761729d93SAxel Dörfler {
14188a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
141961729d93SAxel Dörfler
1420ec4fb0f4SAxel Dörfler Interface* interface;
142161729d93SAxel Dörfler if (index == 0)
1422ec4fb0f4SAxel Dörfler interface = sInterfaces.First();
1423ec4fb0f4SAxel Dörfler else
1424ec4fb0f4SAxel Dörfler interface = find_interface(index);
1425ff8c8dfcSStefano Ceccherini if (interface == NULL || interface->IsBusy())
142661729d93SAxel Dörfler return NULL;
1427c22d69bfSAxel Dörfler
1428488f8888SAugustin Cavalier // We must unlock before invoking CreateDomainDatalinkIfNeeded, because
1429488f8888SAugustin Cavalier // otherwise we can hit lock ordering inversions with receive threads,
1430488f8888SAugustin Cavalier // usually in register_device_handler.
1431488f8888SAugustin Cavalier BReference<Interface> interfaceRef(interface);
1432488f8888SAugustin Cavalier locker.Unlock();
1433488f8888SAugustin Cavalier
143461729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
143561729d93SAxel Dörfler return NULL;
143661729d93SAxel Dörfler
1437488f8888SAugustin Cavalier return interfaceRef.Detach();
1438c22d69bfSAxel Dörfler }
1439c22d69bfSAxel Dörfler
144061729d93SAxel Dörfler
144161729d93SAxel Dörfler Interface*
get_interface(net_domain * domain,const char * name)144261729d93SAxel Dörfler get_interface(net_domain* domain, const char* name)
144361729d93SAxel Dörfler {
14448a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
144561729d93SAxel Dörfler
144661729d93SAxel Dörfler Interface* interface = find_interface(name);
1447ff8c8dfcSStefano Ceccherini if (interface == NULL || interface->IsBusy())
144861729d93SAxel Dörfler return NULL;
144961729d93SAxel Dörfler
1450488f8888SAugustin Cavalier // See comment in get_interface.
1451488f8888SAugustin Cavalier BReference<Interface> interfaceRef(interface);
1452488f8888SAugustin Cavalier locker.Unlock();
1453488f8888SAugustin Cavalier
145461729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
145561729d93SAxel Dörfler return NULL;
145661729d93SAxel Dörfler
1457488f8888SAugustin Cavalier return interfaceRef.Detach();
145861729d93SAxel Dörfler }
145961729d93SAxel Dörfler
146061729d93SAxel Dörfler
146161729d93SAxel Dörfler Interface*
get_interface_for_device(net_domain * domain,uint32 index)146261729d93SAxel Dörfler get_interface_for_device(net_domain* domain, uint32 index)
146361729d93SAxel Dörfler {
14648a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
146561729d93SAxel Dörfler
146661729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator();
146761729d93SAxel Dörfler while (Interface* interface = iterator.Next()) {
146861729d93SAxel Dörfler if (interface->device->index == index) {
1469ff8c8dfcSStefano Ceccherini if (interface->IsBusy())
1470ff8c8dfcSStefano Ceccherini return NULL;
1471488f8888SAugustin Cavalier
1472488f8888SAugustin Cavalier // See comment in get_interface.
1473488f8888SAugustin Cavalier BReference<Interface> interfaceRef(interface);
1474488f8888SAugustin Cavalier locker.Unlock();
1475488f8888SAugustin Cavalier
147661729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
147761729d93SAxel Dörfler return NULL;
147861729d93SAxel Dörfler
1479488f8888SAugustin Cavalier return interfaceRef.Detach();
148061729d93SAxel Dörfler }
148161729d93SAxel Dörfler }
148261729d93SAxel Dörfler
1483c22d69bfSAxel Dörfler return NULL;
1484c22d69bfSAxel Dörfler }
1485c22d69bfSAxel Dörfler
1486c22d69bfSAxel Dörfler
1487cd08b9f7SAxel Dörfler /*! Returns a reference to an Interface that matches the given \a linkAddress.
1488cd08b9f7SAxel Dörfler The link address is checked against its hardware address, or its interface
1489cd08b9f7SAxel Dörfler name, or finally the interface index.
1490cd08b9f7SAxel Dörfler */
1491cd08b9f7SAxel Dörfler Interface*
get_interface_for_link(net_domain * domain,const sockaddr * _linkAddress)1492cd08b9f7SAxel Dörfler get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress)
1493cd08b9f7SAxel Dörfler {
1494cd08b9f7SAxel Dörfler sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress;
1495cd08b9f7SAxel Dörfler
14968a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
1497cd08b9f7SAxel Dörfler
1498cd08b9f7SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator();
1499cd08b9f7SAxel Dörfler while (Interface* interface = iterator.Next()) {
1500ff8c8dfcSStefano Ceccherini if (interface->IsBusy())
1501ff8c8dfcSStefano Ceccherini continue;
1502cd08b9f7SAxel Dörfler // Test if the hardware address matches, or if the given interface
1503cd08b9f7SAxel Dörfler // matches, or if at least the index matches.
1504cd08b9f7SAxel Dörfler if ((linkAddress.sdl_alen == interface->device->address.length
1505cd08b9f7SAxel Dörfler && memcmp(LLADDR(&linkAddress), interface->device->address.data,
1506cd08b9f7SAxel Dörfler linkAddress.sdl_alen) == 0)
1507cd08b9f7SAxel Dörfler || (linkAddress.sdl_nlen > 0
1508cd08b9f7SAxel Dörfler && !strcmp(interface->name, (const char*)linkAddress.sdl_data))
1509cd08b9f7SAxel Dörfler || (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0
1510cd08b9f7SAxel Dörfler && linkAddress.sdl_index == interface->index)) {
1511ff8c8dfcSStefano Ceccherini if (interface->IsBusy())
1512ff8c8dfcSStefano Ceccherini return NULL;
1513488f8888SAugustin Cavalier
1514488f8888SAugustin Cavalier // See comment in get_interface.
1515488f8888SAugustin Cavalier BReference<Interface> interfaceRef(interface);
1516488f8888SAugustin Cavalier locker.Unlock();
1517488f8888SAugustin Cavalier
1518cd08b9f7SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
1519cd08b9f7SAxel Dörfler return NULL;
1520cd08b9f7SAxel Dörfler
1521488f8888SAugustin Cavalier return interfaceRef.Detach();
1522cd08b9f7SAxel Dörfler }
1523cd08b9f7SAxel Dörfler }
1524cd08b9f7SAxel Dörfler
1525cd08b9f7SAxel Dörfler return NULL;
1526cd08b9f7SAxel Dörfler }
1527cd08b9f7SAxel Dörfler
1528cd08b9f7SAxel Dörfler
152961729d93SAxel Dörfler InterfaceAddress*
get_interface_address(const sockaddr * local)153061729d93SAxel Dörfler get_interface_address(const sockaddr* local)
1531c22d69bfSAxel Dörfler {
153261729d93SAxel Dörfler if (local->sa_family == AF_UNSPEC)
153361729d93SAxel Dörfler return NULL;
1534c22d69bfSAxel Dörfler
153561729d93SAxel Dörfler MutexLocker locker(sHashLock);
1536c22d69bfSAxel Dörfler
153761729d93SAxel Dörfler InterfaceAddress* address = sAddressTable.Lookup(local);
153861729d93SAxel Dörfler if (address == NULL)
153961729d93SAxel Dörfler return NULL;
1540c22d69bfSAxel Dörfler
154161729d93SAxel Dörfler address->AcquireReference();
154261729d93SAxel Dörfler return address;
154361729d93SAxel Dörfler }
154461729d93SAxel Dörfler
154561729d93SAxel Dörfler
154661729d93SAxel Dörfler InterfaceAddress*
get_interface_address_for_destination(net_domain * domain,const sockaddr * destination)154761729d93SAxel Dörfler get_interface_address_for_destination(net_domain* domain,
1548cd08b9f7SAxel Dörfler const sockaddr* destination)
154961729d93SAxel Dörfler {
15508a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
155161729d93SAxel Dörfler
155261729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator();
155361729d93SAxel Dörfler while (Interface* interface = iterator.Next()) {
1554ff8c8dfcSStefano Ceccherini if (interface->IsBusy())
1555ff8c8dfcSStefano Ceccherini continue;
1556ff8c8dfcSStefano Ceccherini
155761729d93SAxel Dörfler InterfaceAddress* address
155861729d93SAxel Dörfler = interface->AddressForDestination(domain, destination);
155961729d93SAxel Dörfler if (address != NULL)
156061729d93SAxel Dörfler return address;
156161729d93SAxel Dörfler }
156261729d93SAxel Dörfler
156361729d93SAxel Dörfler return NULL;
156461729d93SAxel Dörfler }
156561729d93SAxel Dörfler
156661729d93SAxel Dörfler
1567cd08b9f7SAxel Dörfler /*! Returns a reference to an InterfaceAddress of the specified \a domain that
1568cd08b9f7SAxel Dörfler belongs to the interface identified via \a linkAddress. Only the hardware
1569cd08b9f7SAxel Dörfler address is matched.
1570cd08b9f7SAxel Dörfler
1571cd08b9f7SAxel Dörfler If \a unconfiguredOnly is set, the interface address must not yet be
1572cd08b9f7SAxel Dörfler configured, or must currently be in the process of being configured.
1573cd08b9f7SAxel Dörfler */
157461729d93SAxel Dörfler InterfaceAddress*
get_interface_address_for_link(net_domain * domain,const sockaddr * address,bool unconfiguredOnly)1575cd08b9f7SAxel Dörfler get_interface_address_for_link(net_domain* domain, const sockaddr* address,
1576cd08b9f7SAxel Dörfler bool unconfiguredOnly)
157761729d93SAxel Dörfler {
1578cd08b9f7SAxel Dörfler sockaddr_dl& linkAddress = *(sockaddr_dl*)address;
157961729d93SAxel Dörfler
15808a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
158161729d93SAxel Dörfler
158261729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator();
158361729d93SAxel Dörfler while (Interface* interface = iterator.Next()) {
1584ff8c8dfcSStefano Ceccherini if (interface->IsBusy())
1585ff8c8dfcSStefano Ceccherini continue;
1586cd08b9f7SAxel Dörfler // Test if the hardware address matches, or if the given interface
1587cd08b9f7SAxel Dörfler // matches, or if at least the index matches.
158861729d93SAxel Dörfler if (linkAddress.sdl_alen == interface->device->address.length
158961729d93SAxel Dörfler && memcmp(LLADDR(&linkAddress), interface->device->address.data,
159061729d93SAxel Dörfler linkAddress.sdl_alen) == 0) {
1591b0cf274aSAxel Dörfler TRACE(" %s matches\n", interface->name);
159261729d93SAxel Dörfler // link address matches
159361729d93SAxel Dörfler if (unconfiguredOnly)
159461729d93SAxel Dörfler return interface->FirstUnconfiguredForFamily(domain->family);
159561729d93SAxel Dörfler
159661729d93SAxel Dörfler return interface->FirstForFamily(domain->family);
159761729d93SAxel Dörfler }
159861729d93SAxel Dörfler }
159961729d93SAxel Dörfler
160061729d93SAxel Dörfler return NULL;
1601c22d69bfSAxel Dörfler }
1602c22d69bfSAxel Dörfler
1603c22d69bfSAxel Dörfler
1604c22d69bfSAxel Dörfler uint32
count_interfaces()160561729d93SAxel Dörfler count_interfaces()
1606c22d69bfSAxel Dörfler {
16078a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
1608c22d69bfSAxel Dörfler
160961729d93SAxel Dörfler return sInterfaces.Count();
1610c22d69bfSAxel Dörfler }
1611c22d69bfSAxel Dörfler
1612c22d69bfSAxel Dörfler
16133c13a5f5SAxel Dörfler /*! Dumps a list of all interfaces into the supplied userland buffer.
1614c22d69bfSAxel Dörfler If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
1615c22d69bfSAxel Dörfler returned.
1616c22d69bfSAxel Dörfler */
1617c22d69bfSAxel Dörfler status_t
list_interfaces(int family,void * _buffer,size_t * bufferSize)161861729d93SAxel Dörfler list_interfaces(int family, void* _buffer, size_t* bufferSize)
1619c22d69bfSAxel Dörfler {
16208a6337d0SStefano Ceccherini RecursiveLocker locker(sLock);
1621c22d69bfSAxel Dörfler
1622409b1fc0SHugo Santos UserBuffer buffer(_buffer, *bufferSize);
1623c22d69bfSAxel Dörfler
162461729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator();
162561729d93SAxel Dörfler while (Interface* interface = iterator.Next()) {
1626715fed44SAxel Dörfler // Copy name
1627715fed44SAxel Dörfler buffer.Push(interface->name, IF_NAMESIZE);
1628c22d69bfSAxel Dörfler
1629715fed44SAxel Dörfler // Copy address
163061729d93SAxel Dörfler InterfaceAddress* address = interface->FirstForFamily(family);
16311f9c8c45SAxel Dörfler size_t length = 0;
1632715fed44SAxel Dörfler
163361729d93SAxel Dörfler if (address != NULL && address->local != NULL) {
1634715fed44SAxel Dörfler // Actual address
16351f9c8c45SAxel Dörfler buffer.Push(address->local, length = address->local->sa_len);
163661729d93SAxel Dörfler } else {
1637715fed44SAxel Dörfler // Empty address
16381f9c8c45SAxel Dörfler sockaddr empty;
16391f9c8c45SAxel Dörfler empty.sa_len = 2;
16401f9c8c45SAxel Dörfler empty.sa_family = AF_UNSPEC;
16411f9c8c45SAxel Dörfler buffer.Push(&empty, length = empty.sa_len);
1642715fed44SAxel Dörfler }
1643715fed44SAxel Dörfler
164461729d93SAxel Dörfler if (address != NULL)
164561729d93SAxel Dörfler address->ReleaseReference();
164661729d93SAxel Dörfler
16471f9c8c45SAxel Dörfler if (IF_NAMESIZE + length < sizeof(ifreq)) {
16481f9c8c45SAxel Dörfler // Make sure at least sizeof(ifreq) bytes are written for each
16491f9c8c45SAxel Dörfler // interface for compatibility with other platforms
16501f9c8c45SAxel Dörfler buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length);
16511f9c8c45SAxel Dörfler }
16521f9c8c45SAxel Dörfler
16531f9c8c45SAxel Dörfler if (buffer.Status() != B_OK)
1654409b1fc0SHugo Santos return buffer.Status();
1655c22d69bfSAxel Dörfler }
1656c22d69bfSAxel Dörfler
1657715fed44SAxel Dörfler *bufferSize = buffer.BytesConsumed();
1658c22d69bfSAxel Dörfler return B_OK;
1659c22d69bfSAxel Dörfler }
1660c22d69bfSAxel Dörfler
1661c22d69bfSAxel Dörfler
1662c22d69bfSAxel Dörfler // #pragma mark -
1663c22d69bfSAxel Dörfler
1664c22d69bfSAxel Dörfler
1665c22d69bfSAxel Dörfler status_t
init_interfaces()1666c22d69bfSAxel Dörfler init_interfaces()
1667c22d69bfSAxel Dörfler {
16688a6337d0SStefano Ceccherini recursive_lock_init(&sLock, "net interfaces");
166961729d93SAxel Dörfler mutex_init(&sHashLock, "net local addresses");
1670c22d69bfSAxel Dörfler
167161729d93SAxel Dörfler new (&sInterfaces) InterfaceList;
167261729d93SAxel Dörfler new (&sAddressTable) AddressTable;
16739206bb37SAxel Dörfler // static C++ objects are not initialized in the module startup
1674a3ec278aSAxel Dörfler
1675a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1676a3ec278aSAxel Dörfler add_debugger_command("net_interface", &dump_interface,
1677a3ec278aSAxel Dörfler "Dump the given network interface");
167861729d93SAxel Dörfler add_debugger_command("net_interfaces", &dump_interfaces,
167961729d93SAxel Dörfler "Dump all network interfaces");
168061729d93SAxel Dörfler add_debugger_command("net_local", &dump_local,
168161729d93SAxel Dörfler "Dump all local interface addresses");
168261729d93SAxel Dörfler add_debugger_command("net_route", &dump_route,
168361729d93SAxel Dörfler "Dump the given network route");
1684a3ec278aSAxel Dörfler #endif
1685c22d69bfSAxel Dörfler return B_OK;
1686c22d69bfSAxel Dörfler }
1687c22d69bfSAxel Dörfler
1688c22d69bfSAxel Dörfler
1689c22d69bfSAxel Dörfler status_t
uninit_interfaces()1690c22d69bfSAxel Dörfler uninit_interfaces()
1691c22d69bfSAxel Dörfler {
1692a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS
1693a3ec278aSAxel Dörfler remove_debugger_command("net_interface", &dump_interface);
16943f2a0963SPhilippe Houdoin remove_debugger_command("net_interfaces", &dump_interfaces);
16953f2a0963SPhilippe Houdoin remove_debugger_command("net_local", &dump_local);
16963f2a0963SPhilippe Houdoin remove_debugger_command("net_route", &dump_route);
1697a3ec278aSAxel Dörfler #endif
1698a3ec278aSAxel Dörfler
16998a6337d0SStefano Ceccherini recursive_lock_destroy(&sLock);
170061729d93SAxel Dörfler mutex_destroy(&sHashLock);
1701c22d69bfSAxel Dörfler return B_OK;
1702c22d69bfSAxel Dörfler }
1703c22d69bfSAxel Dörfler
1704