1c22d69bfSAxel Dörfler /* 24ae58630SAxel Dörfler * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. 3c22d69bfSAxel Dörfler * Distributed under the terms of the MIT License. 4c22d69bfSAxel Dörfler * 5c22d69bfSAxel Dörfler * Authors: 6c22d69bfSAxel Dörfler * Axel Dörfler, axeld@pinc-software.de 7c22d69bfSAxel Dörfler */ 8c22d69bfSAxel Dörfler 9c22d69bfSAxel Dörfler 10c22d69bfSAxel Dörfler #include "interfaces.h" 11c22d69bfSAxel Dörfler 12c22d69bfSAxel Dörfler #include <net/if_dl.h> 13c22d69bfSAxel Dörfler #include <new> 14a1deb55eSHugo Santos #include <stdio.h> 15c22d69bfSAxel Dörfler #include <stdlib.h> 16c22d69bfSAxel Dörfler #include <string.h> 1761729d93SAxel Dörfler #include <sys/sockio.h> 1861729d93SAxel Dörfler 1961729d93SAxel Dörfler #include <KernelExport.h> 2061729d93SAxel Dörfler 2161729d93SAxel Dörfler #include <net_device.h> 22b0cf274aSAxel Dörfler #include <NetUtilities.h> 2361729d93SAxel Dörfler 2461729d93SAxel Dörfler #include "device_interfaces.h" 2561729d93SAxel Dörfler #include "domains.h" 2661729d93SAxel Dörfler #include "stack_private.h" 2761729d93SAxel Dörfler #include "utility.h" 28c22d69bfSAxel Dörfler 29c22d69bfSAxel Dörfler 3061729d93SAxel Dörfler //#define TRACE_INTERFACES 31c22d69bfSAxel Dörfler #ifdef TRACE_INTERFACES 3261729d93SAxel Dörfler # define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x) 33c22d69bfSAxel Dörfler #else 3461729d93SAxel Dörfler # define TRACE(x...) ; 35c22d69bfSAxel Dörfler #endif 36c22d69bfSAxel Dörfler 3761729d93SAxel Dörfler 3861729d93SAxel Dörfler struct AddressHashDefinition { 3961729d93SAxel Dörfler typedef const sockaddr* KeyType; 4061729d93SAxel Dörfler typedef InterfaceAddress ValueType; 4161729d93SAxel Dörfler 4261729d93SAxel Dörfler AddressHashDefinition() 4361729d93SAxel Dörfler { 4461729d93SAxel Dörfler } 4561729d93SAxel Dörfler 4661729d93SAxel Dörfler size_t HashKey(const KeyType& key) const 4761729d93SAxel Dörfler { 4861729d93SAxel Dörfler net_domain* domain = get_domain(key->sa_family); 4961729d93SAxel Dörfler if (domain == NULL) 5061729d93SAxel Dörfler return 0; 5161729d93SAxel Dörfler 5261729d93SAxel Dörfler return domain->address_module->hash_address(key, false); 5361729d93SAxel Dörfler } 5461729d93SAxel Dörfler 5561729d93SAxel Dörfler size_t Hash(InterfaceAddress* address) const 5661729d93SAxel Dörfler { 574ae58630SAxel Dörfler return address->domain->address_module->hash_address(address->local, 584ae58630SAxel Dörfler false); 5961729d93SAxel Dörfler } 6061729d93SAxel Dörfler 6161729d93SAxel Dörfler bool Compare(const KeyType& key, InterfaceAddress* address) const 6261729d93SAxel Dörfler { 6361729d93SAxel Dörfler if (address->local == NULL) 6461729d93SAxel Dörfler return key->sa_family == AF_UNSPEC; 6561729d93SAxel Dörfler 6661729d93SAxel Dörfler if (address->local->sa_family != key->sa_family) 6761729d93SAxel Dörfler return false; 6861729d93SAxel Dörfler 6961729d93SAxel Dörfler return address->domain->address_module->equal_addresses(key, 7061729d93SAxel Dörfler address->local); 7161729d93SAxel Dörfler } 7261729d93SAxel Dörfler 7361729d93SAxel Dörfler InterfaceAddress*& GetLink(InterfaceAddress* address) const 7461729d93SAxel Dörfler { 7561729d93SAxel Dörfler return address->HashTableLink(); 7661729d93SAxel Dörfler } 7761729d93SAxel Dörfler }; 7861729d93SAxel Dörfler 794ae58630SAxel Dörfler typedef BOpenHashTable<AddressHashDefinition, true, false> AddressTable; 80a3ec278aSAxel Dörfler 81c22d69bfSAxel Dörfler 8261729d93SAxel Dörfler static mutex 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 { 94ec4fb0f4SAxel Dörfler MutexLocker locker(sLock); 95ec4fb0f4SAxel Dörfler 96ec4fb0f4SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 97ec4fb0f4SAxel Dörfler while (Interface* interface = iterator.Next()) { 98ec4fb0f4SAxel Dörfler dprintf("%p: %s, %ld\n", interface, interface->name, 99ec4fb0f4SAxel Dörfler interface->CountReferences()); 100ec4fb0f4SAxel Dörfler } 101ec4fb0f4SAxel Dörfler } 102ec4fb0f4SAxel Dörfler #endif 103ec4fb0f4SAxel Dörfler 104ec4fb0f4SAxel Dörfler 105a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 106a3ec278aSAxel Dörfler 107a3ec278aSAxel Dörfler 108a3ec278aSAxel Dörfler static int 109a3ec278aSAxel Dörfler dump_interface(int argc, char** argv) 110a3ec278aSAxel Dörfler { 111a3ec278aSAxel Dörfler if (argc != 2) { 11211eccb54SAxel Dörfler kprintf("usage: %s [name|address]\n", argv[0]); 113a3ec278aSAxel Dörfler return 0; 114a3ec278aSAxel Dörfler } 115a3ec278aSAxel Dörfler 11611eccb54SAxel Dörfler Interface* interface = NULL; 11711eccb54SAxel Dörfler 11811eccb54SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 11911eccb54SAxel Dörfler while ((interface = iterator.Next()) != NULL) { 12011eccb54SAxel Dörfler if (!strcmp(argv[1], interface->name)) 12111eccb54SAxel Dörfler break; 12211eccb54SAxel Dörfler } 12311eccb54SAxel Dörfler 12411eccb54SAxel Dörfler if (interface == NULL) 12511eccb54SAxel Dörfler interface = (Interface*)parse_expression(argv[1]); 12611eccb54SAxel Dörfler 12761729d93SAxel Dörfler interface->Dump(); 128a3ec278aSAxel Dörfler 129a3ec278aSAxel Dörfler return 0; 130a3ec278aSAxel Dörfler } 131a3ec278aSAxel Dörfler 132a3ec278aSAxel Dörfler 133a3ec278aSAxel Dörfler static int 13461729d93SAxel Dörfler dump_interfaces(int argc, char** argv) 13561729d93SAxel Dörfler { 13661729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 13761729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 13861729d93SAxel Dörfler kprintf("%p %s\n", interface, interface->name); 13961729d93SAxel Dörfler } 14061729d93SAxel Dörfler return 0; 14161729d93SAxel Dörfler } 14261729d93SAxel Dörfler 14361729d93SAxel Dörfler 14461729d93SAxel Dörfler static int 14561729d93SAxel Dörfler dump_local(int argc, char** argv) 14661729d93SAxel Dörfler { 14761729d93SAxel Dörfler AddressTable::Iterator iterator = sAddressTable.GetIterator(); 14861729d93SAxel Dörfler size_t i = 0; 14961729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 15061729d93SAxel Dörfler address->Dump(++i); 15161729d93SAxel Dörfler dprintf(" hash: %lu\n", 15261729d93SAxel Dörfler address->domain->address_module->hash_address(address->local, 15361729d93SAxel Dörfler false)); 15461729d93SAxel Dörfler } 15561729d93SAxel Dörfler return 0; 15661729d93SAxel Dörfler } 15761729d93SAxel Dörfler 15861729d93SAxel Dörfler 15961729d93SAxel Dörfler static int 16061729d93SAxel Dörfler dump_route(int argc, char** argv) 161a3ec278aSAxel Dörfler { 162a3ec278aSAxel Dörfler if (argc != 2) { 163a3ec278aSAxel Dörfler kprintf("usage: %s [address]\n", argv[0]); 164a3ec278aSAxel Dörfler return 0; 165a3ec278aSAxel Dörfler } 166a3ec278aSAxel Dörfler 16761729d93SAxel Dörfler net_route* route = (net_route*)parse_expression(argv[1]); 16861729d93SAxel Dörfler kprintf("destination: %p\n", route->destination); 16961729d93SAxel Dörfler kprintf("mask: %p\n", route->mask); 17061729d93SAxel Dörfler kprintf("gateway: %p\n", route->gateway); 17161729d93SAxel Dörfler kprintf("flags: %" B_PRIx32 "\n", route->flags); 17261729d93SAxel Dörfler kprintf("mtu: %" B_PRIu32 "\n", route->mtu); 17361729d93SAxel Dörfler kprintf("interface address: %p\n", route->interface_address); 174a3ec278aSAxel Dörfler 17561729d93SAxel Dörfler if (route->interface_address != NULL) { 17661729d93SAxel Dörfler ((InterfaceAddress*)route->interface_address)->Dump(); 177a3ec278aSAxel Dörfler } 178a3ec278aSAxel Dörfler 179a3ec278aSAxel Dörfler return 0; 180a3ec278aSAxel Dörfler } 181a3ec278aSAxel Dörfler 182a3ec278aSAxel Dörfler 183a3ec278aSAxel Dörfler #endif // ENABLE_DEBUGGER_COMMANDS 184a3ec278aSAxel Dörfler 185a3ec278aSAxel Dörfler 18661729d93SAxel Dörfler InterfaceAddress::InterfaceAddress() 187c22d69bfSAxel Dörfler { 18861729d93SAxel Dörfler _Init(NULL, NULL); 18961729d93SAxel Dörfler } 190c22d69bfSAxel Dörfler 19161729d93SAxel Dörfler 19261729d93SAxel Dörfler InterfaceAddress::InterfaceAddress(net_interface* netInterface, 19361729d93SAxel Dörfler net_domain* netDomain) 19461729d93SAxel Dörfler { 19561729d93SAxel Dörfler _Init(netInterface, netDomain); 19661729d93SAxel Dörfler } 19761729d93SAxel Dörfler 19861729d93SAxel Dörfler 19961729d93SAxel Dörfler InterfaceAddress::~InterfaceAddress() 20061729d93SAxel Dörfler { 2012b1c0755SAxel Dörfler TRACE("InterfaceAddress %p: destructor\n", this); 2022b1c0755SAxel Dörfler 2032b1c0755SAxel Dörfler if (interface != NULL && (flags & IFAF_DIRECT_ADDRESS) == 0) 2042b1c0755SAxel Dörfler ((Interface*)interface)->ReleaseReference(); 20561729d93SAxel Dörfler } 20661729d93SAxel Dörfler 20761729d93SAxel Dörfler 20861729d93SAxel Dörfler status_t 20961729d93SAxel Dörfler InterfaceAddress::SetTo(const ifaliasreq& request) 21061729d93SAxel Dörfler { 21161729d93SAxel Dörfler status_t status = SetLocal((const sockaddr*)&request.ifra_addr); 21261729d93SAxel Dörfler if (status == B_OK) 21361729d93SAxel Dörfler status = SetDestination((const sockaddr*)&request.ifra_broadaddr); 21461729d93SAxel Dörfler if (status == B_OK) 21561729d93SAxel Dörfler status = SetMask((const sockaddr*)&request.ifra_mask); 21661729d93SAxel Dörfler 21761729d93SAxel Dörfler return status; 21861729d93SAxel Dörfler } 21961729d93SAxel Dörfler 22061729d93SAxel Dörfler 22161729d93SAxel Dörfler status_t 22261729d93SAxel Dörfler InterfaceAddress::SetLocal(const sockaddr* to) 22361729d93SAxel Dörfler { 22461729d93SAxel Dörfler return Set(&local, to); 22561729d93SAxel Dörfler } 22661729d93SAxel Dörfler 22761729d93SAxel Dörfler 22861729d93SAxel Dörfler status_t 22961729d93SAxel Dörfler InterfaceAddress::SetDestination(const sockaddr* to) 23061729d93SAxel Dörfler { 23161729d93SAxel Dörfler return Set(&destination, to); 23261729d93SAxel Dörfler } 23361729d93SAxel Dörfler 23461729d93SAxel Dörfler 23561729d93SAxel Dörfler status_t 23661729d93SAxel Dörfler InterfaceAddress::SetMask(const sockaddr* to) 23761729d93SAxel Dörfler { 23861729d93SAxel Dörfler return Set(&mask, to); 23961729d93SAxel Dörfler } 24061729d93SAxel Dörfler 24161729d93SAxel Dörfler 24261729d93SAxel Dörfler sockaddr** 24361729d93SAxel Dörfler InterfaceAddress::AddressFor(int32 option) 24461729d93SAxel Dörfler { 24561729d93SAxel Dörfler switch (option) { 24661729d93SAxel Dörfler case SIOCSIFADDR: 24761729d93SAxel Dörfler case SIOCGIFADDR: 2482b1c0755SAxel Dörfler case SIOCDIFADDR: 24961729d93SAxel Dörfler return &local; 25061729d93SAxel Dörfler 25161729d93SAxel Dörfler case SIOCSIFNETMASK: 25261729d93SAxel Dörfler case SIOCGIFNETMASK: 25361729d93SAxel Dörfler return &mask; 25461729d93SAxel Dörfler 25561729d93SAxel Dörfler case SIOCSIFBRDADDR: 25661729d93SAxel Dörfler case SIOCSIFDSTADDR: 25761729d93SAxel Dörfler case SIOCGIFBRDADDR: 25861729d93SAxel Dörfler case SIOCGIFDSTADDR: 25961729d93SAxel Dörfler return &destination; 26061729d93SAxel Dörfler 26161729d93SAxel Dörfler default: 26261729d93SAxel Dörfler return NULL; 26361729d93SAxel Dörfler } 26461729d93SAxel Dörfler } 26561729d93SAxel Dörfler 26661729d93SAxel Dörfler 2672b1c0755SAxel Dörfler /*! Adds the default routes that every interface address needs, ie. the local 2682b1c0755SAxel Dörfler host route, and one for the subnet (if set). 2692b1c0755SAxel Dörfler */ 2702b1c0755SAxel Dörfler void 2712b1c0755SAxel Dörfler InterfaceAddress::AddDefaultRoutes(int32 option) 2722b1c0755SAxel Dörfler { 2732b1c0755SAxel Dörfler net_route route; 2742b1c0755SAxel Dörfler route.destination = local; 2752b1c0755SAxel Dörfler route.gateway = NULL; 2762b1c0755SAxel Dörfler route.interface_address = this; 2772b1c0755SAxel Dörfler 2782b1c0755SAxel Dörfler if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) { 2792b1c0755SAxel Dörfler route.mask = mask; 2802b1c0755SAxel Dörfler route.flags = 0; 2812b1c0755SAxel Dörfler add_route(domain, &route); 2822b1c0755SAxel Dörfler } 2832b1c0755SAxel Dörfler 2842b1c0755SAxel Dörfler if (option == SIOCSIFADDR) { 2852b1c0755SAxel Dörfler route.mask = NULL; 2862b1c0755SAxel Dörfler route.flags = RTF_LOCAL | RTF_HOST; 2872b1c0755SAxel Dörfler add_route(domain, &route); 2882b1c0755SAxel Dörfler } 2892b1c0755SAxel Dörfler } 2902b1c0755SAxel Dörfler 2912b1c0755SAxel Dörfler 2922b1c0755SAxel Dörfler /*! Removes the default routes as set by AddDefaultRoutes() again. */ 2932b1c0755SAxel Dörfler void 2942b1c0755SAxel Dörfler InterfaceAddress::RemoveDefaultRoutes(int32 option) 2952b1c0755SAxel Dörfler { 2962b1c0755SAxel Dörfler net_route route; 2972b1c0755SAxel Dörfler route.destination = local; 2982b1c0755SAxel Dörfler route.gateway = NULL; 2992b1c0755SAxel Dörfler route.interface_address = this; 3002b1c0755SAxel Dörfler 3012b1c0755SAxel Dörfler if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) { 3022b1c0755SAxel Dörfler route.mask = mask; 3032b1c0755SAxel Dörfler route.flags = 0; 3042b1c0755SAxel Dörfler remove_route(domain, &route); 3052b1c0755SAxel Dörfler } 3062b1c0755SAxel Dörfler 3072b1c0755SAxel Dörfler if (option == SIOCSIFADDR) { 3082b1c0755SAxel Dörfler route.mask = NULL; 3092b1c0755SAxel Dörfler route.flags = RTF_LOCAL | RTF_HOST; 3102b1c0755SAxel Dörfler remove_route(domain, &route); 3112b1c0755SAxel Dörfler } 3122b1c0755SAxel Dörfler } 3132b1c0755SAxel Dörfler 3142b1c0755SAxel Dörfler 3154ae58630SAxel Dörfler bool 3164ae58630SAxel Dörfler InterfaceAddress::LocalIsDefined() const 3174ae58630SAxel Dörfler { 3184ae58630SAxel Dörfler return local != NULL && local->sa_family != AF_UNSPEC; 3194ae58630SAxel Dörfler } 3204ae58630SAxel Dörfler 3214ae58630SAxel Dörfler 32261729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 32361729d93SAxel Dörfler 32461729d93SAxel Dörfler 32561729d93SAxel Dörfler void 32661729d93SAxel Dörfler InterfaceAddress::Dump(size_t index, bool hideInterface) 32761729d93SAxel Dörfler { 32861729d93SAxel Dörfler if (index) 32961729d93SAxel Dörfler kprintf("%2zu. ", index); 33061729d93SAxel Dörfler else 33161729d93SAxel Dörfler kprintf(" "); 33261729d93SAxel Dörfler 33361729d93SAxel Dörfler if (!hideInterface) { 33461729d93SAxel Dörfler kprintf("interface: %p (%s)\n ", interface, 33561729d93SAxel Dörfler interface != NULL ? interface->name : "-"); 33661729d93SAxel Dörfler } 33761729d93SAxel Dörfler 33861729d93SAxel Dörfler kprintf("domain: %p (family %u)\n", domain, 33961729d93SAxel Dörfler domain != NULL ? domain->family : AF_UNSPEC); 34061729d93SAxel Dörfler 34161729d93SAxel Dörfler char buffer[64]; 34261729d93SAxel Dörfler if (local != NULL && domain != NULL) { 34361729d93SAxel Dörfler domain->address_module->print_address_buffer(local, buffer, 34461729d93SAxel Dörfler sizeof(buffer), false); 34561729d93SAxel Dörfler } else 34661729d93SAxel Dörfler strcpy(buffer, "-"); 34761729d93SAxel Dörfler kprintf(" local: %s\n", buffer); 34861729d93SAxel Dörfler 34961729d93SAxel Dörfler if (mask != NULL && domain != NULL) { 35061729d93SAxel Dörfler domain->address_module->print_address_buffer(mask, buffer, 35161729d93SAxel Dörfler sizeof(buffer), false); 35261729d93SAxel Dörfler } else 35361729d93SAxel Dörfler strcpy(buffer, "-"); 35461729d93SAxel Dörfler kprintf(" mask: %s\n", buffer); 35561729d93SAxel Dörfler 35661729d93SAxel Dörfler if (destination != NULL && domain != NULL) { 35761729d93SAxel Dörfler domain->address_module->print_address_buffer(destination, buffer, 35861729d93SAxel Dörfler sizeof(buffer), false); 35961729d93SAxel Dörfler } else 36061729d93SAxel Dörfler strcpy(buffer, "-"); 36161729d93SAxel Dörfler kprintf(" destination: %s\n", buffer); 3624af124a1SAxel Dörfler 3634af124a1SAxel Dörfler kprintf(" ref count: %" B_PRId32 "\n", CountReferences()); 36461729d93SAxel Dörfler } 36561729d93SAxel Dörfler 36661729d93SAxel Dörfler 36761729d93SAxel Dörfler #endif // ENABLE_DEBUGGER_COMMANDS 36861729d93SAxel Dörfler 36961729d93SAxel Dörfler 37061729d93SAxel Dörfler /*static*/ status_t 37161729d93SAxel Dörfler InterfaceAddress::Set(sockaddr** _address, const sockaddr* to) 37261729d93SAxel Dörfler { 37361729d93SAxel Dörfler sockaddr* address = *_address; 37461729d93SAxel Dörfler 37561729d93SAxel Dörfler if (to == NULL || to->sa_family == AF_UNSPEC) { 37661729d93SAxel Dörfler // Clear address 37761729d93SAxel Dörfler free(address); 37861729d93SAxel Dörfler *_address = NULL; 37961729d93SAxel Dörfler return B_OK; 38061729d93SAxel Dörfler } 38161729d93SAxel Dörfler 38261729d93SAxel Dörfler // Set address 38361729d93SAxel Dörfler 38461729d93SAxel Dörfler size_t size = max_c(to->sa_len, sizeof(sockaddr)); 38561729d93SAxel Dörfler if (size > sizeof(sockaddr_storage)) 38661729d93SAxel Dörfler size = sizeof(sockaddr_storage); 38761729d93SAxel Dörfler 38861729d93SAxel Dörfler address = Prepare(_address, size); 38961729d93SAxel Dörfler if (address == NULL) 39061729d93SAxel Dörfler return B_NO_MEMORY; 39161729d93SAxel Dörfler 39261729d93SAxel Dörfler memcpy(address, to, size); 39361729d93SAxel Dörfler address->sa_len = size; 39461729d93SAxel Dörfler 39561729d93SAxel Dörfler return B_OK; 39661729d93SAxel Dörfler } 39761729d93SAxel Dörfler 39861729d93SAxel Dörfler 3995ebd9548SAxel Dörfler /*! Makes sure that the sockaddr object pointed to by \a _address is large 4005ebd9548SAxel Dörfler enough to hold \a size bytes. 4015ebd9548SAxel Dörfler \a _address may point to NULL when calling this method. 4025ebd9548SAxel Dörfler */ 40361729d93SAxel Dörfler /*static*/ sockaddr* 40461729d93SAxel Dörfler InterfaceAddress::Prepare(sockaddr** _address, size_t size) 40561729d93SAxel Dörfler { 40661729d93SAxel Dörfler size = max_c(size, sizeof(sockaddr)); 40761729d93SAxel Dörfler if (size > sizeof(sockaddr_storage)) 40861729d93SAxel Dörfler size = sizeof(sockaddr_storage); 40961729d93SAxel Dörfler 41061729d93SAxel Dörfler sockaddr* address = *_address; 41161729d93SAxel Dörfler 41261729d93SAxel Dörfler if (address == NULL || size > address->sa_len) { 41361729d93SAxel Dörfler address = (sockaddr*)realloc(address, size); 41461729d93SAxel Dörfler if (address == NULL) 41561729d93SAxel Dörfler return NULL; 41661729d93SAxel Dörfler } 41761729d93SAxel Dörfler 41861729d93SAxel Dörfler address->sa_len = size; 41961729d93SAxel Dörfler 42061729d93SAxel Dörfler *_address = address; 42161729d93SAxel Dörfler return address; 42261729d93SAxel Dörfler } 42361729d93SAxel Dörfler 42461729d93SAxel Dörfler 42561729d93SAxel Dörfler void 42661729d93SAxel Dörfler InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain) 42761729d93SAxel Dörfler { 4282b1c0755SAxel Dörfler TRACE("InterfaceAddress %p: init interface %p, domain %p\n", this, 4292b1c0755SAxel Dörfler netInterface, netDomain); 4302b1c0755SAxel Dörfler 43161729d93SAxel Dörfler interface = netInterface; 43261729d93SAxel Dörfler domain = netDomain; 43361729d93SAxel Dörfler local = NULL; 43461729d93SAxel Dörfler destination = NULL; 43561729d93SAxel Dörfler mask = NULL; 4362b1c0755SAxel Dörfler flags = 0; 4372b1c0755SAxel Dörfler 4382b1c0755SAxel Dörfler if (interface != NULL) 4392b1c0755SAxel Dörfler ((Interface*)interface)->AcquireReference(); 44061729d93SAxel Dörfler } 44161729d93SAxel Dörfler 44261729d93SAxel Dörfler 44361729d93SAxel Dörfler // #pragma mark - 44461729d93SAxel Dörfler 44561729d93SAxel Dörfler 44661729d93SAxel Dörfler Interface::Interface(const char* interfaceName, 44761729d93SAxel Dörfler net_device_interface* deviceInterface) 44861729d93SAxel Dörfler { 44961729d93SAxel Dörfler TRACE("Interface %p: new \"%s\", device interface %p\n", this, 45061729d93SAxel Dörfler interfaceName, deviceInterface); 45161729d93SAxel Dörfler 452b0cf274aSAxel Dörfler int written = strlcpy(name, interfaceName, IF_NAMESIZE); 453b0cf274aSAxel Dörfler memset(name + written, 0, IF_NAMESIZE - written); 454b0cf274aSAxel Dörfler // Clear remaining space 455b0cf274aSAxel Dörfler 45661729d93SAxel Dörfler device = deviceInterface->device; 45761729d93SAxel Dörfler 45861729d93SAxel Dörfler index = ++sInterfaceIndex; 45961729d93SAxel Dörfler flags = 0; 46061729d93SAxel Dörfler type = 0; 46161729d93SAxel Dörfler mtu = deviceInterface->device->mtu; 46261729d93SAxel Dörfler metric = 0; 46361729d93SAxel Dörfler 46461729d93SAxel Dörfler fDeviceInterface = acquire_device_interface(deviceInterface); 46561729d93SAxel Dörfler 46661729d93SAxel Dörfler recursive_lock_init(&fLock, name); 46761729d93SAxel Dörfler 46861729d93SAxel Dörfler // Grab a reference to the networking stack, to make sure it won't be 46961729d93SAxel Dörfler // unloaded as long as an interface exists 47061729d93SAxel Dörfler module_info* module; 47161729d93SAxel Dörfler get_module(gNetStackInterfaceModule.info.name, &module); 47261729d93SAxel Dörfler } 47361729d93SAxel Dörfler 47461729d93SAxel Dörfler 47561729d93SAxel Dörfler Interface::~Interface() 47661729d93SAxel Dörfler { 4772b1c0755SAxel Dörfler TRACE("Interface %p: destructor\n", this); 4782b1c0755SAxel Dörfler 4792b1c0755SAxel Dörfler put_device_interface(fDeviceInterface); 4802b1c0755SAxel Dörfler 4812b1c0755SAxel Dörfler // Uninitialize the domain datalink protocols 4822b1c0755SAxel Dörfler 4832b1c0755SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 4842b1c0755SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) { 4852b1c0755SAxel Dörfler put_domain_datalink_protocols(this, datalink->domain); 4862b1c0755SAxel Dörfler } 4872b1c0755SAxel Dörfler 4882b1c0755SAxel Dörfler // Free domain datalink objects 4892b1c0755SAxel Dörfler 4902b1c0755SAxel Dörfler domain_datalink* next = fDatalinkTable.Clear(true); 4912b1c0755SAxel Dörfler while (next != NULL) { 4922b1c0755SAxel Dörfler domain_datalink* datalink = next; 4932b1c0755SAxel Dörfler next = next->hash_link; 4942b1c0755SAxel Dörfler 4952b1c0755SAxel Dörfler delete datalink; 4962b1c0755SAxel Dörfler } 4972b1c0755SAxel Dörfler 49861729d93SAxel Dörfler recursive_lock_destroy(&fLock); 49961729d93SAxel Dörfler 50061729d93SAxel Dörfler // Release reference of the stack - at this point, our stack may be unloaded 50161729d93SAxel Dörfler // if no other interfaces or sockets are left 50261729d93SAxel Dörfler put_module(gNetStackInterfaceModule.info.name); 50361729d93SAxel Dörfler } 50461729d93SAxel Dörfler 50561729d93SAxel Dörfler 50661729d93SAxel Dörfler /*! Returns a reference to the first InterfaceAddress that is from the same 50761729d93SAxel Dörfler as the specified \a family. 50861729d93SAxel Dörfler */ 50961729d93SAxel Dörfler InterfaceAddress* 51061729d93SAxel Dörfler Interface::FirstForFamily(int family) 51161729d93SAxel Dörfler { 51261729d93SAxel Dörfler RecursiveLocker locker(fLock); 51361729d93SAxel Dörfler 51461729d93SAxel Dörfler InterfaceAddress* address = _FirstForFamily(family); 51561729d93SAxel Dörfler if (address != NULL) { 51661729d93SAxel Dörfler address->AcquireReference(); 51761729d93SAxel Dörfler return address; 51861729d93SAxel Dörfler } 51961729d93SAxel Dörfler 52061729d93SAxel Dörfler return NULL; 52161729d93SAxel Dörfler } 52261729d93SAxel Dörfler 52361729d93SAxel Dörfler 52461729d93SAxel Dörfler /*! Returns a reference to the first unconfigured address of this interface 52561729d93SAxel Dörfler for the specified \a family. 52661729d93SAxel Dörfler */ 52761729d93SAxel Dörfler InterfaceAddress* 52861729d93SAxel Dörfler Interface::FirstUnconfiguredForFamily(int family) 52961729d93SAxel Dörfler { 53061729d93SAxel Dörfler RecursiveLocker locker(fLock); 53161729d93SAxel Dörfler 53261729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 53361729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 53461729d93SAxel Dörfler if (address->domain->family == family 53561729d93SAxel Dörfler && (address->local == NULL 53661729d93SAxel Dörfler // TODO: this has to be solved differently!! 53761729d93SAxel Dörfler || (flags & IFF_CONFIGURING) != 0)) { 53861729d93SAxel Dörfler address->AcquireReference(); 53961729d93SAxel Dörfler return address; 54061729d93SAxel Dörfler } 54161729d93SAxel Dörfler } 54261729d93SAxel Dörfler 54361729d93SAxel Dörfler return NULL; 54461729d93SAxel Dörfler } 54561729d93SAxel Dörfler 54661729d93SAxel Dörfler 54761729d93SAxel Dörfler /*! Returns a reference to the InterfaceAddress that has the specified 54861729d93SAxel Dörfler \a destination address. 54961729d93SAxel Dörfler */ 55061729d93SAxel Dörfler InterfaceAddress* 55161729d93SAxel Dörfler Interface::AddressForDestination(net_domain* domain, 55261729d93SAxel Dörfler const sockaddr* destination) 55361729d93SAxel Dörfler { 55461729d93SAxel Dörfler RecursiveLocker locker(fLock); 55561729d93SAxel Dörfler 55661729d93SAxel Dörfler if ((device->flags & IFF_BROADCAST) == 0) { 55761729d93SAxel Dörfler // The device does not support broadcasting 55861729d93SAxel Dörfler return NULL; 55961729d93SAxel Dörfler } 56061729d93SAxel Dörfler 56161729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 56261729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 56361729d93SAxel Dörfler if (address->domain == domain 56461729d93SAxel Dörfler && address->destination != NULL 56561729d93SAxel Dörfler && domain->address_module->equal_addresses(address->destination, 56661729d93SAxel Dörfler destination)) { 56761729d93SAxel Dörfler address->AcquireReference(); 56861729d93SAxel Dörfler return address; 56961729d93SAxel Dörfler } 57061729d93SAxel Dörfler } 57161729d93SAxel Dörfler 57261729d93SAxel Dörfler return NULL; 57361729d93SAxel Dörfler } 57461729d93SAxel Dörfler 57561729d93SAxel Dörfler 576910ffb32SAxel Dörfler /*! Returns a reference to the InterfaceAddress that has the specified 577910ffb32SAxel Dörfler \a local address. 578910ffb32SAxel Dörfler */ 579910ffb32SAxel Dörfler InterfaceAddress* 580910ffb32SAxel Dörfler Interface::AddressForLocal(net_domain* domain, const sockaddr* local) 581910ffb32SAxel Dörfler { 582910ffb32SAxel Dörfler RecursiveLocker locker(fLock); 583910ffb32SAxel Dörfler 584910ffb32SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 585910ffb32SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 586910ffb32SAxel Dörfler if (address->domain == domain 587910ffb32SAxel Dörfler && address->local != NULL 588910ffb32SAxel Dörfler && domain->address_module->equal_addresses(address->local, local)) { 589910ffb32SAxel Dörfler address->AcquireReference(); 590910ffb32SAxel Dörfler return address; 591910ffb32SAxel Dörfler } 592910ffb32SAxel Dörfler } 593910ffb32SAxel Dörfler 594910ffb32SAxel Dörfler return NULL; 595910ffb32SAxel Dörfler } 596910ffb32SAxel Dörfler 597910ffb32SAxel Dörfler 59861729d93SAxel Dörfler status_t 59961729d93SAxel Dörfler Interface::AddAddress(InterfaceAddress* address) 60061729d93SAxel Dörfler { 60161729d93SAxel Dörfler net_domain* domain = address->domain; 60261729d93SAxel Dörfler if (domain == NULL) 60361729d93SAxel Dörfler return B_BAD_VALUE; 60461729d93SAxel Dörfler 60561729d93SAxel Dörfler RecursiveLocker locker(fLock); 60661729d93SAxel Dörfler fAddresses.Add(address); 60761729d93SAxel Dörfler locker.Unlock(); 60861729d93SAxel Dörfler 6094ae58630SAxel Dörfler if (address->LocalIsDefined()) { 61061729d93SAxel Dörfler MutexLocker hashLocker(sHashLock); 61161729d93SAxel Dörfler sAddressTable.Insert(address); 6124ae58630SAxel Dörfler } 61361729d93SAxel Dörfler return B_OK; 61461729d93SAxel Dörfler } 61561729d93SAxel Dörfler 61661729d93SAxel Dörfler 61761729d93SAxel Dörfler void 61861729d93SAxel Dörfler Interface::RemoveAddress(InterfaceAddress* address) 61961729d93SAxel Dörfler { 62061729d93SAxel Dörfler net_domain* domain = address->domain; 62161729d93SAxel Dörfler if (domain == NULL) 62261729d93SAxel Dörfler return; 62361729d93SAxel Dörfler 62461729d93SAxel Dörfler RecursiveLocker locker(fLock); 62561729d93SAxel Dörfler 62661729d93SAxel Dörfler fAddresses.Remove(address); 62761729d93SAxel Dörfler address->GetDoublyLinkedListLink()->next = NULL; 62861729d93SAxel Dörfler 62961729d93SAxel Dörfler locker.Unlock(); 63061729d93SAxel Dörfler 6314ae58630SAxel Dörfler if (address->LocalIsDefined()) { 63261729d93SAxel Dörfler MutexLocker hashLocker(sHashLock); 63361729d93SAxel Dörfler sAddressTable.Remove(address); 63461729d93SAxel Dörfler } 6354ae58630SAxel Dörfler } 63661729d93SAxel Dörfler 63761729d93SAxel Dörfler 63861729d93SAxel Dörfler bool 63961729d93SAxel Dörfler Interface::GetNextAddress(InterfaceAddress** _address) 64061729d93SAxel Dörfler { 64161729d93SAxel Dörfler RecursiveLocker locker(fLock); 64261729d93SAxel Dörfler 64361729d93SAxel Dörfler InterfaceAddress* address = *_address; 64461729d93SAxel Dörfler if (address == NULL) { 64561729d93SAxel Dörfler // get first address 64661729d93SAxel Dörfler address = fAddresses.First(); 64761729d93SAxel Dörfler } else { 64861729d93SAxel Dörfler // get next, if possible 64961729d93SAxel Dörfler InterfaceAddress* next = fAddresses.GetNext(address); 65061729d93SAxel Dörfler address->ReleaseReference(); 65161729d93SAxel Dörfler address = next; 65261729d93SAxel Dörfler } 65361729d93SAxel Dörfler 65461729d93SAxel Dörfler *_address = address; 65561729d93SAxel Dörfler 65661729d93SAxel Dörfler if (address == NULL) 65761729d93SAxel Dörfler return false; 65861729d93SAxel Dörfler 65961729d93SAxel Dörfler address->AcquireReference(); 66061729d93SAxel Dörfler return true; 66161729d93SAxel Dörfler } 66261729d93SAxel Dörfler 66361729d93SAxel Dörfler 6649d771afbSAxel Dörfler InterfaceAddress* 6659d771afbSAxel Dörfler Interface::AddressAt(size_t index) 6669d771afbSAxel Dörfler { 6679d771afbSAxel Dörfler RecursiveLocker locker(fLock); 6689d771afbSAxel Dörfler 6699d771afbSAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 6709d771afbSAxel Dörfler size_t i = 0; 6719d771afbSAxel Dörfler 6729d771afbSAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 6739d771afbSAxel Dörfler if (i++ == index) { 6749d771afbSAxel Dörfler address->AcquireReference(); 6759d771afbSAxel Dörfler return address; 6769d771afbSAxel Dörfler } 6779d771afbSAxel Dörfler } 6789d771afbSAxel Dörfler 6799d771afbSAxel Dörfler return NULL; 6809d771afbSAxel Dörfler } 6819d771afbSAxel Dörfler 6829d771afbSAxel Dörfler 6832c12b8a3SAxel Dörfler int32 6842c12b8a3SAxel Dörfler Interface::IndexOfAddress(InterfaceAddress* address) 6852c12b8a3SAxel Dörfler { 686b0766602SAxel Dörfler if (address == NULL) 687b0766602SAxel Dörfler return -1; 688b0766602SAxel Dörfler 6892c12b8a3SAxel Dörfler RecursiveLocker locker(fLock); 6902c12b8a3SAxel Dörfler 6912c12b8a3SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 6922c12b8a3SAxel Dörfler int32 index = 0; 6932c12b8a3SAxel Dörfler 6942c12b8a3SAxel Dörfler while (iterator.HasNext()) { 6952c12b8a3SAxel Dörfler if (address == iterator.Next()) 6962c12b8a3SAxel Dörfler return index; 6972c12b8a3SAxel Dörfler 6982c12b8a3SAxel Dörfler index++; 6992c12b8a3SAxel Dörfler } 7002c12b8a3SAxel Dörfler 7012c12b8a3SAxel Dörfler return -1; 7022c12b8a3SAxel Dörfler } 7032c12b8a3SAxel Dörfler 7042c12b8a3SAxel Dörfler 7059d771afbSAxel Dörfler size_t 7069d771afbSAxel Dörfler Interface::CountAddresses() 7079d771afbSAxel Dörfler { 7089d771afbSAxel Dörfler RecursiveLocker locker(fLock); 7099d771afbSAxel Dörfler return fAddresses.Count(); 7109d771afbSAxel Dörfler } 7119d771afbSAxel Dörfler 7129d771afbSAxel Dörfler 7132b1c0755SAxel Dörfler void 7142b1c0755SAxel Dörfler Interface::RemoveAddresses() 7152b1c0755SAxel Dörfler { 7162b1c0755SAxel Dörfler RecursiveLocker locker(fLock); 7172b1c0755SAxel Dörfler 7182b1c0755SAxel Dörfler while (InterfaceAddress* address = fAddresses.RemoveHead()) { 719b0766602SAxel Dörfler locker.Unlock(); 720b0766602SAxel Dörfler 721b0766602SAxel Dörfler if (address->LocalIsDefined()) { 722b0766602SAxel Dörfler MutexLocker hashLocker(sHashLock); 723b0766602SAxel Dörfler sAddressTable.Remove(address); 724b0766602SAxel Dörfler } 7255ebd9548SAxel Dörfler address->ReleaseReference(); 726b0766602SAxel Dörfler 727b0766602SAxel Dörfler locker.Lock(); 7282b1c0755SAxel Dörfler } 7292b1c0755SAxel Dörfler } 7302b1c0755SAxel Dörfler 7312b1c0755SAxel Dörfler 7329d771afbSAxel Dörfler /*! This is called in order to call the correct methods of the datalink 7339d771afbSAxel Dörfler protocols, ie. it will translate address changes to 7349d771afbSAxel Dörfler net_datalink_protocol::change_address(), and IFF_UP changes to 7359d771afbSAxel Dörfler net_datalink_protocol::interface_up(), and interface_down(). 7369d771afbSAxel Dörfler 7379d771afbSAxel Dörfler Everything else is passed unchanged to net_datalink_protocol::control(). 7389d771afbSAxel Dörfler */ 73961729d93SAxel Dörfler status_t 74061729d93SAxel Dörfler Interface::Control(net_domain* domain, int32 option, ifreq& request, 74161729d93SAxel Dörfler ifreq* userRequest, size_t length) 74261729d93SAxel Dörfler { 74361729d93SAxel Dörfler switch (option) { 74461729d93SAxel Dörfler case SIOCSIFFLAGS: 74561729d93SAxel Dörfler { 746e8802e49SAxel Dörfler if (length != sizeof(ifreq)) 747e8802e49SAxel Dörfler return B_BAD_VALUE; 748e8802e49SAxel Dörfler 74961729d93SAxel Dörfler uint32 requestFlags = request.ifr_flags; 75061729d93SAxel Dörfler uint32 oldFlags = flags; 75161729d93SAxel Dörfler status_t status = B_OK; 75261729d93SAxel Dörfler 75361729d93SAxel Dörfler request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST); 75461729d93SAxel Dörfler 75561729d93SAxel Dörfler if ((requestFlags & IFF_UP) != (flags & IFF_UP)) { 75661729d93SAxel Dörfler if ((requestFlags & IFF_UP) != 0) 75761729d93SAxel Dörfler status = _SetUp(); 75861729d93SAxel Dörfler else 7592b1c0755SAxel Dörfler SetDown(); 76061729d93SAxel Dörfler } 76161729d93SAxel Dörfler 76261729d93SAxel Dörfler if (status == B_OK) { 76361729d93SAxel Dörfler // TODO: maybe allow deleting IFF_BROADCAST on the interface 76461729d93SAxel Dörfler // level? 76561729d93SAxel Dörfler flags &= IFF_UP | IFF_LINK | IFF_BROADCAST; 76661729d93SAxel Dörfler flags |= request.ifr_flags; 76761729d93SAxel Dörfler } 76861729d93SAxel Dörfler 769e78fea43SAxel Dörfler if (oldFlags != flags) { 770e78fea43SAxel Dörfler TRACE("Interface %p: flags changed from %" B_PRIx32 " to %" 771e78fea43SAxel Dörfler B_PRIx32 "\n", this, oldFlags, flags); 77261729d93SAxel Dörfler notify_interface_changed(this, oldFlags, flags); 773e78fea43SAxel Dörfler } 77461729d93SAxel Dörfler 77561729d93SAxel Dörfler return status; 77661729d93SAxel Dörfler } 77761729d93SAxel Dörfler 7782b1c0755SAxel Dörfler case B_SOCKET_SET_ALIAS: 7799d771afbSAxel Dörfler { 780e8802e49SAxel Dörfler if (length != sizeof(ifaliasreq)) 781e8802e49SAxel Dörfler return B_BAD_VALUE; 782e8802e49SAxel Dörfler 7839d771afbSAxel Dörfler RecursiveLocker locker(fLock); 7849d771afbSAxel Dörfler 7859d771afbSAxel Dörfler ifaliasreq aliasRequest; 7869d771afbSAxel Dörfler if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq)) 7879d771afbSAxel Dörfler != B_OK) 7889d771afbSAxel Dörfler return B_BAD_ADDRESS; 7899d771afbSAxel Dörfler 790910ffb32SAxel Dörfler InterfaceAddress* address = NULL; 791910ffb32SAxel Dörfler if (aliasRequest.ifra_index < 0) { 792910ffb32SAxel Dörfler if (!domain->address_module->is_empty_address( 793910ffb32SAxel Dörfler (const sockaddr*)&aliasRequest.ifra_addr, false)) { 794910ffb32SAxel Dörfler // Find first address that matches the local address 795910ffb32SAxel Dörfler address = AddressForLocal(domain, 796910ffb32SAxel Dörfler (const sockaddr*)&aliasRequest.ifra_addr); 797910ffb32SAxel Dörfler } 798910ffb32SAxel Dörfler if (address == NULL) { 799910ffb32SAxel Dörfler // Find first address for family 800910ffb32SAxel Dörfler address = FirstForFamily(domain->family); 801910ffb32SAxel Dörfler } 802a271028eSAxel Dörfler if (address == NULL) { 803a271028eSAxel Dörfler // Create new on the fly 804a271028eSAxel Dörfler address = new(std::nothrow) InterfaceAddress(this, domain); 805a271028eSAxel Dörfler if (address == NULL) 806a271028eSAxel Dörfler return B_NO_MEMORY; 807a271028eSAxel Dörfler 808a271028eSAxel Dörfler status_t status = AddAddress(address); 809095f97a6SAxel Dörfler if (status != B_OK) { 810095f97a6SAxel Dörfler delete address; 811a271028eSAxel Dörfler return status; 812095f97a6SAxel Dörfler } 813a271028eSAxel Dörfler 814a271028eSAxel Dörfler // Note, even if setting the address failed, the empty 815a271028eSAxel Dörfler // address added here will still be added to the interface. 8168dcde8b1SAxel Dörfler address->AcquireReference(); 817a271028eSAxel Dörfler } 818910ffb32SAxel Dörfler } else 819910ffb32SAxel Dörfler address = AddressAt(aliasRequest.ifra_index); 820910ffb32SAxel Dörfler 8219d771afbSAxel Dörfler if (address == NULL) 8229d771afbSAxel Dörfler return B_BAD_VALUE; 8239d771afbSAxel Dörfler 8249d771afbSAxel Dörfler status_t status = B_OK; 8259d771afbSAxel Dörfler 8269d771afbSAxel Dörfler if (!domain->address_module->equal_addresses( 8279d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_addr, address->local)) { 8289d771afbSAxel Dörfler status = _ChangeAddress(locker, address, SIOCSIFADDR, 8299d771afbSAxel Dörfler address->local, (sockaddr*)&aliasRequest.ifra_addr); 8309d771afbSAxel Dörfler } 8319d771afbSAxel Dörfler 8329d771afbSAxel Dörfler if (status == B_OK && !domain->address_module->equal_addresses( 833910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_mask, address->mask) 834910ffb32SAxel Dörfler && !domain->address_module->is_empty_address( 835910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_mask, false)) { 8369d771afbSAxel Dörfler status = _ChangeAddress(locker, address, SIOCSIFNETMASK, 8379d771afbSAxel Dörfler address->mask, (sockaddr*)&aliasRequest.ifra_mask); 8389d771afbSAxel Dörfler } 8399d771afbSAxel Dörfler 8409d771afbSAxel Dörfler if (status == B_OK && !domain->address_module->equal_addresses( 8419d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination, 842910ffb32SAxel Dörfler address->destination) 843910ffb32SAxel Dörfler && !domain->address_module->is_empty_address( 844910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination, false)) { 8459d771afbSAxel Dörfler status = _ChangeAddress(locker, address, 8469d771afbSAxel Dörfler (domain->address_module->flags 8479d771afbSAxel Dörfler & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0 8489d771afbSAxel Dörfler ? SIOCSIFBRDADDR : SIOCSIFDSTADDR, 8499d771afbSAxel Dörfler address->destination, 8509d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination); 8519d771afbSAxel Dörfler } 8529d771afbSAxel Dörfler 8539d771afbSAxel Dörfler address->ReleaseReference(); 8549d771afbSAxel Dörfler return status; 8559d771afbSAxel Dörfler } 8569d771afbSAxel Dörfler 85761729d93SAxel Dörfler case SIOCSIFADDR: 85861729d93SAxel Dörfler case SIOCSIFNETMASK: 85961729d93SAxel Dörfler case SIOCSIFBRDADDR: 86061729d93SAxel Dörfler case SIOCSIFDSTADDR: 86161729d93SAxel Dörfler case SIOCDIFADDR: 86261729d93SAxel Dörfler { 863e8802e49SAxel Dörfler if (length != sizeof(ifreq)) 864e8802e49SAxel Dörfler return B_BAD_VALUE; 865e8802e49SAxel Dörfler 86661729d93SAxel Dörfler RecursiveLocker locker(fLock); 86761729d93SAxel Dörfler 86861729d93SAxel Dörfler InterfaceAddress* address = NULL; 86961729d93SAxel Dörfler sockaddr_storage newAddress; 87061729d93SAxel Dörfler 87161729d93SAxel Dörfler size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr)); 87261729d93SAxel Dörfler if (size > sizeof(sockaddr_storage)) 87361729d93SAxel Dörfler size = sizeof(sockaddr_storage); 87461729d93SAxel Dörfler 87561729d93SAxel Dörfler if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK) 87661729d93SAxel Dörfler return B_BAD_ADDRESS; 87761729d93SAxel Dörfler 87861729d93SAxel Dörfler if (option == SIOCDIFADDR) { 87961729d93SAxel Dörfler // Find referring address - we can't use the hash, as another 88061729d93SAxel Dörfler // interface might use the same address. 88161729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 88261729d93SAxel Dörfler while ((address = iterator.Next()) != NULL) { 88361729d93SAxel Dörfler if (address->domain == domain 88461729d93SAxel Dörfler && domain->address_module->equal_addresses( 88561729d93SAxel Dörfler address->local, (sockaddr*)&newAddress)) 88661729d93SAxel Dörfler break; 88761729d93SAxel Dörfler } 88861729d93SAxel Dörfler 88961729d93SAxel Dörfler if (address == NULL) 89061729d93SAxel Dörfler return B_BAD_VALUE; 89178abd727SAxel Dörfler } else { 89278abd727SAxel Dörfler // Just use the first address for this family 89378abd727SAxel Dörfler address = _FirstForFamily(domain->family); 89478abd727SAxel Dörfler if (address == NULL) { 89578abd727SAxel Dörfler // Create new on the fly 89678abd727SAxel Dörfler address = new(std::nothrow) InterfaceAddress(this, domain); 89778abd727SAxel Dörfler if (address == NULL) 89878abd727SAxel Dörfler return B_NO_MEMORY; 89978abd727SAxel Dörfler 90078abd727SAxel Dörfler status_t status = AddAddress(address); 901095f97a6SAxel Dörfler if (status != B_OK) { 902095f97a6SAxel Dörfler delete address; 90378abd727SAxel Dörfler return status; 904095f97a6SAxel Dörfler } 90578abd727SAxel Dörfler 90678abd727SAxel Dörfler // Note, even if setting the address failed, the empty 90778abd727SAxel Dörfler // address added here will still be added to the interface. 90878abd727SAxel Dörfler } 90978abd727SAxel Dörfler } 91061729d93SAxel Dörfler 9119d771afbSAxel Dörfler return _ChangeAddress(locker, address, option, 9129d771afbSAxel Dörfler *address->AddressFor(option), 91361729d93SAxel Dörfler option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL); 91461729d93SAxel Dörfler } 91561729d93SAxel Dörfler 91661729d93SAxel Dörfler default: 91761729d93SAxel Dörfler // pass the request into the datalink protocol stack 91861729d93SAxel Dörfler domain_datalink* datalink = DomainDatalink(domain->family); 91961729d93SAxel Dörfler if (datalink->first_info != NULL) { 92061729d93SAxel Dörfler return datalink->first_info->control( 92161729d93SAxel Dörfler datalink->first_protocol, option, userRequest, length); 92261729d93SAxel Dörfler } 92361729d93SAxel Dörfler break; 92461729d93SAxel Dörfler } 92561729d93SAxel Dörfler 92661729d93SAxel Dörfler return B_BAD_VALUE; 92761729d93SAxel Dörfler } 92861729d93SAxel Dörfler 92961729d93SAxel Dörfler 9302b1c0755SAxel Dörfler void 9312b1c0755SAxel Dörfler Interface::SetDown() 9322b1c0755SAxel Dörfler { 9332b1c0755SAxel Dörfler if ((flags & IFF_UP) == 0) 9342b1c0755SAxel Dörfler return; 9352b1c0755SAxel Dörfler 9362b1c0755SAxel Dörfler RecursiveLocker locker(fLock); 9372b1c0755SAxel Dörfler 9382b1c0755SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 9392b1c0755SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) { 9402b1c0755SAxel Dörfler datalink->first_info->interface_down(datalink->first_protocol); 9412b1c0755SAxel Dörfler } 9422b1c0755SAxel Dörfler 9432b1c0755SAxel Dörfler flags &= ~IFF_UP; 9442b1c0755SAxel Dörfler } 9452b1c0755SAxel Dörfler 9462b1c0755SAxel Dörfler 9472b1c0755SAxel Dörfler /*! Called when a device lost its IFF_UP status. We will invalidate all 9482b1c0755SAxel Dörfler interface routes here. 9492b1c0755SAxel Dörfler */ 9502b1c0755SAxel Dörfler void 9512b1c0755SAxel Dörfler Interface::WentDown() 9522b1c0755SAxel Dörfler { 953ed18d7cfSAxel Dörfler TRACE("Interface %p: went down\n", this); 954ed18d7cfSAxel Dörfler 9552b1c0755SAxel Dörfler RecursiveLocker locker(fLock); 9562b1c0755SAxel Dörfler 9572b1c0755SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 9582b1c0755SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 9592b1c0755SAxel Dörfler if (address->domain != NULL) 9602b1c0755SAxel Dörfler invalidate_routes(address->domain, this); 9612b1c0755SAxel Dörfler } 9622b1c0755SAxel Dörfler } 9632b1c0755SAxel Dörfler 9642b1c0755SAxel Dörfler 96561729d93SAxel Dörfler status_t 96661729d93SAxel Dörfler Interface::CreateDomainDatalinkIfNeeded(net_domain* domain) 96761729d93SAxel Dörfler { 96861729d93SAxel Dörfler RecursiveLocker locker(fLock); 96961729d93SAxel Dörfler 97061729d93SAxel Dörfler if (fDatalinkTable.Lookup(domain->family) != NULL) 97161729d93SAxel Dörfler return B_OK; 97261729d93SAxel Dörfler 97361729d93SAxel Dörfler TRACE("Interface %p: create domain datalink for domain %p\n", this, domain); 97461729d93SAxel Dörfler 97561729d93SAxel Dörfler domain_datalink* datalink = new(std::nothrow) domain_datalink; 97661729d93SAxel Dörfler if (datalink == NULL) 97761729d93SAxel Dörfler return B_NO_MEMORY; 97861729d93SAxel Dörfler 979ed18d7cfSAxel Dörfler datalink->first_protocol = NULL; 980ed18d7cfSAxel Dörfler datalink->first_info = NULL; 98161729d93SAxel Dörfler datalink->domain = domain; 98261729d93SAxel Dörfler 98361729d93SAxel Dörfler // setup direct route for bound devices 98461729d93SAxel Dörfler datalink->direct_route.destination = NULL; 98561729d93SAxel Dörfler datalink->direct_route.mask = NULL; 98661729d93SAxel Dörfler datalink->direct_route.gateway = NULL; 98761729d93SAxel Dörfler datalink->direct_route.flags = 0; 98861729d93SAxel Dörfler datalink->direct_route.mtu = 0; 98961729d93SAxel Dörfler datalink->direct_route.interface_address = &datalink->direct_address; 99061729d93SAxel Dörfler datalink->direct_route.ref_count = 1; 99161729d93SAxel Dörfler // make sure this doesn't get deleted accidently 99261729d93SAxel Dörfler 99361729d93SAxel Dörfler // provide its link back to the interface 99461729d93SAxel Dörfler datalink->direct_address.local = NULL; 99561729d93SAxel Dörfler datalink->direct_address.destination = NULL; 99661729d93SAxel Dörfler datalink->direct_address.mask = NULL; 99761729d93SAxel Dörfler datalink->direct_address.domain = domain; 99861729d93SAxel Dörfler datalink->direct_address.interface = this; 9992b1c0755SAxel Dörfler datalink->direct_address.flags = IFAF_DIRECT_ADDRESS; 100061729d93SAxel Dörfler 100161729d93SAxel Dörfler fDatalinkTable.Insert(datalink); 100261729d93SAxel Dörfler 100361729d93SAxel Dörfler status_t status = get_domain_datalink_protocols(this, domain); 100461729d93SAxel Dörfler if (status == B_OK) 100561729d93SAxel Dörfler return B_OK; 100661729d93SAxel Dörfler 100761729d93SAxel Dörfler fDatalinkTable.Remove(datalink); 100861729d93SAxel Dörfler delete datalink; 100961729d93SAxel Dörfler 101061729d93SAxel Dörfler return status; 101161729d93SAxel Dörfler } 101261729d93SAxel Dörfler 101361729d93SAxel Dörfler 101461729d93SAxel Dörfler domain_datalink* 101561729d93SAxel Dörfler Interface::DomainDatalink(uint8 family) 101661729d93SAxel Dörfler { 101761729d93SAxel Dörfler // Note: domain datalinks cannot be removed while the interface is alive, 101861729d93SAxel Dörfler // since this would require us either to hold the lock while calling this 101961729d93SAxel Dörfler // function, or introduce reference counting for the domain_datalink 102061729d93SAxel Dörfler // structure. 102161729d93SAxel Dörfler RecursiveLocker locker(fLock); 102261729d93SAxel Dörfler return fDatalinkTable.Lookup(family); 102361729d93SAxel Dörfler } 102461729d93SAxel Dörfler 102561729d93SAxel Dörfler 102661729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 102761729d93SAxel Dörfler 102861729d93SAxel Dörfler 102961729d93SAxel Dörfler void 103061729d93SAxel Dörfler Interface::Dump() const 103161729d93SAxel Dörfler { 103261729d93SAxel Dörfler kprintf("name: %s\n", name); 103361729d93SAxel Dörfler kprintf("device: %p\n", device); 103461729d93SAxel Dörfler kprintf("device_interface: %p\n", fDeviceInterface); 103561729d93SAxel Dörfler kprintf("index: %" B_PRIu32 "\n", index); 103661729d93SAxel Dörfler kprintf("flags: %#" B_PRIx32 "\n", flags); 103761729d93SAxel Dörfler kprintf("type: %u\n", type); 103861729d93SAxel Dörfler kprintf("mtu: %" B_PRIu32 "\n", mtu); 103961729d93SAxel Dörfler kprintf("metric: %" B_PRIu32 "\n", metric); 1040ed18d7cfSAxel Dörfler kprintf("ref count: %" B_PRId32 "\n", CountReferences()); 104161729d93SAxel Dörfler 104261729d93SAxel Dörfler kprintf("datalink protocols:\n"); 104361729d93SAxel Dörfler 104461729d93SAxel Dörfler DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator(); 104561729d93SAxel Dörfler size_t i = 0; 104661729d93SAxel Dörfler while (domain_datalink* datalink = datalinkIterator.Next()) { 104761729d93SAxel Dörfler kprintf("%2zu. domain: %p\n", ++i, datalink->domain); 104861729d93SAxel Dörfler kprintf(" first_protocol: %p\n", datalink->first_protocol); 104961729d93SAxel Dörfler kprintf(" first_info: %p\n", datalink->first_info); 105061729d93SAxel Dörfler kprintf(" direct_route: %p\n", &datalink->direct_route); 105161729d93SAxel Dörfler } 105261729d93SAxel Dörfler 105361729d93SAxel Dörfler kprintf("addresses:\n"); 105461729d93SAxel Dörfler 105561729d93SAxel Dörfler AddressList::ConstIterator iterator = fAddresses.GetIterator(); 105661729d93SAxel Dörfler i = 0; 105761729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 105861729d93SAxel Dörfler address->Dump(++i, true); 105961729d93SAxel Dörfler } 106061729d93SAxel Dörfler } 106161729d93SAxel Dörfler 106261729d93SAxel Dörfler 106361729d93SAxel Dörfler #endif // ENABLE_DEBUGGER_COMMANDS 106461729d93SAxel Dörfler 106561729d93SAxel Dörfler 106661729d93SAxel Dörfler status_t 106761729d93SAxel Dörfler Interface::_SetUp() 106861729d93SAxel Dörfler { 106961729d93SAxel Dörfler status_t status = up_device_interface(fDeviceInterface); 107061729d93SAxel Dörfler if (status != B_OK) 107161729d93SAxel Dörfler return status; 107261729d93SAxel Dörfler 10732b1c0755SAxel Dörfler // Propagate flag to all datalink protocols 107461729d93SAxel Dörfler 107561729d93SAxel Dörfler RecursiveLocker locker(fLock); 107661729d93SAxel Dörfler 107761729d93SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 107861729d93SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) { 107961729d93SAxel Dörfler status = datalink->first_info->interface_up(datalink->first_protocol); 108061729d93SAxel Dörfler if (status != B_OK) { 108161729d93SAxel Dörfler // Revert "up" status 108261729d93SAxel Dörfler DatalinkTable::Iterator secondIterator 108361729d93SAxel Dörfler = fDatalinkTable.GetIterator(); 108461729d93SAxel Dörfler while (secondIterator.HasNext()) { 108561729d93SAxel Dörfler domain_datalink* secondDatalink = secondIterator.Next(); 108661729d93SAxel Dörfler if (secondDatalink == NULL || secondDatalink == datalink) 1087c22d69bfSAxel Dörfler break; 1088c22d69bfSAxel Dörfler 108961729d93SAxel Dörfler secondDatalink->first_info->interface_down( 109061729d93SAxel Dörfler secondDatalink->first_protocol); 109161729d93SAxel Dörfler } 109261729d93SAxel Dörfler 109361729d93SAxel Dörfler down_device_interface(fDeviceInterface); 109461729d93SAxel Dörfler return status; 109561729d93SAxel Dörfler } 109661729d93SAxel Dörfler } 109761729d93SAxel Dörfler 10982b1c0755SAxel Dörfler // Add default routes for the existing addresses 10992b1c0755SAxel Dörfler 11002b1c0755SAxel Dörfler AddressList::Iterator addressIterator = fAddresses.GetIterator(); 11012b1c0755SAxel Dörfler while (InterfaceAddress* address = addressIterator.Next()) { 11022b1c0755SAxel Dörfler address->AddDefaultRoutes(SIOCSIFADDR); 11032b1c0755SAxel Dörfler } 11042b1c0755SAxel Dörfler 110561729d93SAxel Dörfler flags |= IFF_UP; 110661729d93SAxel Dörfler return B_OK; 110761729d93SAxel Dörfler } 110861729d93SAxel Dörfler 110961729d93SAxel Dörfler 111061729d93SAxel Dörfler InterfaceAddress* 111161729d93SAxel Dörfler Interface::_FirstForFamily(int family) 111261729d93SAxel Dörfler { 111361729d93SAxel Dörfler ASSERT_LOCKED_RECURSIVE(&fLock); 111461729d93SAxel Dörfler 111561729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 111661729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 111761729d93SAxel Dörfler if (address->domain != NULL && address->domain->family == family) 111861729d93SAxel Dörfler return address; 111961729d93SAxel Dörfler } 112061729d93SAxel Dörfler 112161729d93SAxel Dörfler return NULL; 112261729d93SAxel Dörfler } 112361729d93SAxel Dörfler 112461729d93SAxel Dörfler 11259d771afbSAxel Dörfler status_t 11269d771afbSAxel Dörfler Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address, 1127b0cf274aSAxel Dörfler int32 option, const sockaddr* originalAddress, 1128b0cf274aSAxel Dörfler const sockaddr* requestedAddress) 11299d771afbSAxel Dörfler { 1130b0cf274aSAxel Dörfler // Copy old address 11319d771afbSAxel Dörfler sockaddr_storage oldAddress; 11329d771afbSAxel Dörfler if (address->domain->address_module->set_to((sockaddr*)&oldAddress, 11339d771afbSAxel Dörfler originalAddress) != B_OK) 11349d771afbSAxel Dörfler oldAddress.ss_family = AF_UNSPEC; 11359d771afbSAxel Dörfler 1136b0cf274aSAxel Dörfler // Copy new address (this also makes sure that sockaddr::sa_len is set 1137b0cf274aSAxel Dörfler // correctly) 1138b0cf274aSAxel Dörfler sockaddr_storage newAddress; 1139b0cf274aSAxel Dörfler if (address->domain->address_module->set_to((sockaddr*)&newAddress, 1140b0cf274aSAxel Dörfler requestedAddress) != B_OK) 1141b0cf274aSAxel Dörfler newAddress.ss_family = AF_UNSPEC; 1142b0cf274aSAxel Dörfler 11436b1e1488SAxel Dörfler // Test if anything changed for real 1144b0cf274aSAxel Dörfler if (address->domain->address_module->equal_addresses( 1145b0cf274aSAxel Dörfler (sockaddr*)&oldAddress, (sockaddr*)&newAddress)) { 11466b1e1488SAxel Dörfler // Nothing to do 1147b0cf274aSAxel Dörfler TRACE(" option %" B_PRId32 " addresses are equal!\n", option); 11486b1e1488SAxel Dörfler return B_OK; 11496b1e1488SAxel Dörfler } 11506b1e1488SAxel Dörfler 11519d771afbSAxel Dörfler // TODO: mark this address busy or call while holding the lock! 11529d771afbSAxel Dörfler address->AcquireReference(); 11539d771afbSAxel Dörfler locker.Unlock(); 11549d771afbSAxel Dörfler 11559d771afbSAxel Dörfler domain_datalink* datalink = DomainDatalink(address->domain); 11569d771afbSAxel Dörfler status_t status = datalink->first_protocol->module->change_address( 11579d771afbSAxel Dörfler datalink->first_protocol, address, option, 11589d771afbSAxel Dörfler oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL, 1159b0cf274aSAxel Dörfler newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL); 11609d771afbSAxel Dörfler 11619d771afbSAxel Dörfler locker.Lock(); 11629d771afbSAxel Dörfler address->ReleaseReference(); 11639d771afbSAxel Dörfler return status; 11649d771afbSAxel Dörfler } 11659d771afbSAxel Dörfler 11669d771afbSAxel Dörfler 116761729d93SAxel Dörfler // #pragma mark - 116861729d93SAxel Dörfler 116961729d93SAxel Dörfler 117061729d93SAxel Dörfler /*! Searches for a specific interface by name. 117161729d93SAxel Dörfler You need to have the interface list's lock hold when calling this function. 117261729d93SAxel Dörfler */ 117361729d93SAxel Dörfler static struct Interface* 117461729d93SAxel Dörfler find_interface(const char* name) 117561729d93SAxel Dörfler { 117661729d93SAxel Dörfler ASSERT_LOCKED_MUTEX(&sLock); 117761729d93SAxel Dörfler 117861729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 117961729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1180c22d69bfSAxel Dörfler if (!strcmp(interface->name, name)) 1181c22d69bfSAxel Dörfler return interface; 1182c22d69bfSAxel Dörfler } 1183c22d69bfSAxel Dörfler 1184c22d69bfSAxel Dörfler return NULL; 1185c22d69bfSAxel Dörfler } 1186c22d69bfSAxel Dörfler 1187c22d69bfSAxel Dörfler 118861729d93SAxel Dörfler /*! Searches for a specific interface by index. 118961729d93SAxel Dörfler You need to have the interface list's lock hold when calling this function. 1190c22d69bfSAxel Dörfler */ 119161729d93SAxel Dörfler static struct Interface* 119261729d93SAxel Dörfler find_interface(uint32 index) 1193c22d69bfSAxel Dörfler { 119461729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 119561729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1196c22d69bfSAxel Dörfler if (interface->index == index) 1197c22d69bfSAxel Dörfler return interface; 1198c22d69bfSAxel Dörfler } 1199c22d69bfSAxel Dörfler 1200c22d69bfSAxel Dörfler return NULL; 1201c22d69bfSAxel Dörfler } 1202c22d69bfSAxel Dörfler 1203c22d69bfSAxel Dörfler 120461729d93SAxel Dörfler // #pragma mark - 120561729d93SAxel Dörfler 120661729d93SAxel Dörfler 120761729d93SAxel Dörfler status_t 120861729d93SAxel Dörfler add_interface(const char* name, net_domain_private* domain, 120961729d93SAxel Dörfler const ifaliasreq& request, net_device_interface* deviceInterface) 121061729d93SAxel Dörfler { 121161729d93SAxel Dörfler MutexLocker locker(sLock); 121261729d93SAxel Dörfler 121361729d93SAxel Dörfler if (find_interface(name) != NULL) 121461729d93SAxel Dörfler return B_NAME_IN_USE; 121561729d93SAxel Dörfler 121661729d93SAxel Dörfler Interface* interface 121761729d93SAxel Dörfler = new(std::nothrow) Interface(name, deviceInterface); 1218c22d69bfSAxel Dörfler if (interface == NULL) 1219c22d69bfSAxel Dörfler return B_NO_MEMORY; 1220c22d69bfSAxel Dörfler 122161729d93SAxel Dörfler sInterfaces.Add(interface); 122261729d93SAxel Dörfler interface->AcquireReference(); 122361729d93SAxel Dörfler // We need another reference to be able to use the interface without 122461729d93SAxel Dörfler // holding sLock. 1225c22d69bfSAxel Dörfler 122661729d93SAxel Dörfler locker.Unlock(); 1227c22d69bfSAxel Dörfler 12284ae58630SAxel Dörfler status_t status = add_interface_address(interface, domain, request); 12294ae58630SAxel Dörfler if (status == B_OK) 123061729d93SAxel Dörfler notify_interface_added(interface); 12314ae58630SAxel Dörfler else { 12324ae58630SAxel Dörfler locker.Lock(); 12334ae58630SAxel Dörfler sInterfaces.Remove(interface); 12344ae58630SAxel Dörfler locker.Unlock(); 12354ae58630SAxel Dörfler interface->ReleaseReference(); 12364ae58630SAxel Dörfler } 1237c22d69bfSAxel Dörfler 123861729d93SAxel Dörfler interface->ReleaseReference(); 123927e0dea9SAxel Dörfler 12404ae58630SAxel Dörfler return status; 1241c22d69bfSAxel Dörfler } 1242c22d69bfSAxel Dörfler 1243c22d69bfSAxel Dörfler 124461729d93SAxel Dörfler /*! Removes the interface from the list, and puts the stack's reference to it. 124561729d93SAxel Dörfler */ 12467aa2819cSAxel Dörfler void 124761729d93SAxel Dörfler remove_interface(Interface* interface) 1248c64feccaSHugo Santos { 12492b1c0755SAxel Dörfler interface->SetDown(); 12502b1c0755SAxel Dörfler interface->RemoveAddresses(); 1251c64feccaSHugo Santos 12522b1c0755SAxel Dörfler MutexLocker locker(sLock); 12532b1c0755SAxel Dörfler sInterfaces.Remove(interface); 12542b1c0755SAxel Dörfler locker.Unlock(); 1255f6d219a1SAxel Dörfler 125661729d93SAxel Dörfler notify_interface_removed(interface); 1257c22d69bfSAxel Dörfler 12582b1c0755SAxel Dörfler interface->ReleaseReference(); 12597aa2819cSAxel Dörfler } 12607aa2819cSAxel Dörfler 12617aa2819cSAxel Dörfler 12627aa2819cSAxel Dörfler /*! This is called whenever a device interface is being removed. We will get 12637aa2819cSAxel Dörfler the corresponding Interface, and remove it. 12647aa2819cSAxel Dörfler */ 12657aa2819cSAxel Dörfler void 12667aa2819cSAxel Dörfler interface_removed_device_interface(net_device_interface* deviceInterface) 12677aa2819cSAxel Dörfler { 12687aa2819cSAxel Dörfler MutexLocker locker(sLock); 12697aa2819cSAxel Dörfler 12707aa2819cSAxel Dörfler Interface* interface = find_interface(deviceInterface->device->name); 12717aa2819cSAxel Dörfler if (interface != NULL) 12727aa2819cSAxel Dörfler remove_interface(interface); 1273c22d69bfSAxel Dörfler } 1274c22d69bfSAxel Dörfler 1275c22d69bfSAxel Dörfler 127661729d93SAxel Dörfler status_t 127761729d93SAxel Dörfler add_interface_address(Interface* interface, net_domain_private* domain, 127861729d93SAxel Dörfler const ifaliasreq& request) 1279c22d69bfSAxel Dörfler { 128061729d93SAxel Dörfler // Make sure the family of the provided addresses is valid 128161729d93SAxel Dörfler if ((request.ifra_addr.ss_family != domain->family 128261729d93SAxel Dörfler && request.ifra_addr.ss_family != AF_UNSPEC) 128361729d93SAxel Dörfler || (request.ifra_mask.ss_family != domain->family 128461729d93SAxel Dörfler && request.ifra_mask.ss_family != AF_UNSPEC) 128561729d93SAxel Dörfler || (request.ifra_broadaddr.ss_family != domain->family 128661729d93SAxel Dörfler && request.ifra_broadaddr.ss_family != AF_UNSPEC)) 128761729d93SAxel Dörfler return B_BAD_VALUE; 1288c22d69bfSAxel Dörfler 128961729d93SAxel Dörfler RecursiveLocker locker(interface->Lock()); 129061729d93SAxel Dörfler 129161729d93SAxel Dörfler InterfaceAddress* address 129261729d93SAxel Dörfler = new(std::nothrow) InterfaceAddress(interface, domain); 129361729d93SAxel Dörfler if (address == NULL) 129461729d93SAxel Dörfler return B_NO_MEMORY; 129561729d93SAxel Dörfler 129661729d93SAxel Dörfler status_t status = address->SetTo(request); 129761729d93SAxel Dörfler if (status == B_OK) 129861729d93SAxel Dörfler status = interface->CreateDomainDatalinkIfNeeded(domain); 129961729d93SAxel Dörfler if (status == B_OK) 130061729d93SAxel Dörfler status = interface->AddAddress(address); 130161729d93SAxel Dörfler 130261729d93SAxel Dörfler if (status == B_OK && address->local != NULL) { 130361729d93SAxel Dörfler // update the datalink protocols 130461729d93SAxel Dörfler domain_datalink* datalink = interface->DomainDatalink(domain->family); 130561729d93SAxel Dörfler 130661729d93SAxel Dörfler status = datalink->first_protocol->module->change_address( 130761729d93SAxel Dörfler datalink->first_protocol, address, SIOCAIFADDR, NULL, 130861729d93SAxel Dörfler address->local); 130961729d93SAxel Dörfler if (status != B_OK) 131061729d93SAxel Dörfler interface->RemoveAddress(address); 131161729d93SAxel Dörfler } 131261729d93SAxel Dörfler if (status == B_OK) 131361729d93SAxel Dörfler notify_interface_changed(interface); 131461729d93SAxel Dörfler else 131561729d93SAxel Dörfler delete address; 131661729d93SAxel Dörfler 131761729d93SAxel Dörfler return status; 131861729d93SAxel Dörfler } 131961729d93SAxel Dörfler 132061729d93SAxel Dörfler 132161729d93SAxel Dörfler status_t 132261729d93SAxel Dörfler update_interface_address(InterfaceAddress* interfaceAddress, int32 option, 132361729d93SAxel Dörfler const sockaddr* oldAddress, const sockaddr* newAddress) 132461729d93SAxel Dörfler { 1325b0cf274aSAxel Dörfler TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress " 1326b0cf274aSAxel Dörfler "%s)\n", __FUNCTION__, interfaceAddress, option, 1327b0cf274aSAxel Dörfler AddressString(interfaceAddress->domain, oldAddress).Data(), 1328b0cf274aSAxel Dörfler AddressString(interfaceAddress->domain, newAddress).Data()); 1329b0cf274aSAxel Dörfler 133061729d93SAxel Dörfler MutexLocker locker(sHashLock); 133161729d93SAxel Dörfler 133261729d93SAxel Dörfler // set logical interface address 133361729d93SAxel Dörfler sockaddr** _address = interfaceAddress->AddressFor(option); 133461729d93SAxel Dörfler if (_address == NULL) 133561729d93SAxel Dörfler return B_BAD_VALUE; 133661729d93SAxel Dörfler 13372b1c0755SAxel Dörfler Interface* interface = (Interface*)interfaceAddress->interface; 13382b1c0755SAxel Dörfler 13392b1c0755SAxel Dörfler interfaceAddress->RemoveDefaultRoutes(option); 13402b1c0755SAxel Dörfler 13412b1c0755SAxel Dörfler if (option == SIOCDIFADDR) { 13422b1c0755SAxel Dörfler // Remove address, and release its reference (causing our caller to 13432b1c0755SAxel Dörfler // delete it) 13442b1c0755SAxel Dörfler locker.Unlock(); 13452b1c0755SAxel Dörfler 13462b1c0755SAxel Dörfler invalidate_routes(interfaceAddress); 13472b1c0755SAxel Dörfler 13482b1c0755SAxel Dörfler interface->RemoveAddress(interfaceAddress); 13492b1c0755SAxel Dörfler interfaceAddress->ReleaseReference(); 13502b1c0755SAxel Dörfler return B_OK; 13512b1c0755SAxel Dörfler } 13522b1c0755SAxel Dörfler 13534ae58630SAxel Dörfler if (interfaceAddress->LocalIsDefined()) 135461729d93SAxel Dörfler sAddressTable.Remove(interfaceAddress); 135561729d93SAxel Dörfler 135661729d93SAxel Dörfler // Copy new address over 135761729d93SAxel Dörfler status_t status = InterfaceAddress::Set(_address, newAddress); 135861729d93SAxel Dörfler if (status == B_OK) { 135961729d93SAxel Dörfler sockaddr* address = *_address; 136061729d93SAxel Dörfler 13615ebd9548SAxel Dörfler if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) { 136261729d93SAxel Dörfler // Reset netmask and broadcast addresses to defaults 136361729d93SAxel Dörfler net_domain* domain = interfaceAddress->domain; 13645ebd9548SAxel Dörfler sockaddr* defaultNetmask = NULL; 13655ebd9548SAxel Dörfler const sockaddr* netmask = NULL; 136661729d93SAxel Dörfler if (option == SIOCSIFADDR) { 13675ebd9548SAxel Dörfler defaultNetmask = InterfaceAddress::Prepare( 136861729d93SAxel Dörfler &interfaceAddress->mask, address->sa_len); 13695ebd9548SAxel Dörfler } else 13705ebd9548SAxel Dörfler netmask = newAddress; 137161729d93SAxel Dörfler 137261729d93SAxel Dörfler // Reset the broadcast address if the address family has 137361729d93SAxel Dörfler // such 13745ebd9548SAxel Dörfler sockaddr* defaultBroadcast = NULL; 137561729d93SAxel Dörfler if ((domain->address_module->flags 137661729d93SAxel Dörfler & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) { 13775ebd9548SAxel Dörfler defaultBroadcast = InterfaceAddress::Prepare( 137861729d93SAxel Dörfler &interfaceAddress->destination, address->sa_len); 137961729d93SAxel Dörfler } else 138061729d93SAxel Dörfler InterfaceAddress::Set(&interfaceAddress->destination, NULL); 138161729d93SAxel Dörfler 13825ebd9548SAxel Dörfler domain->address_module->set_to_defaults(defaultNetmask, 13835ebd9548SAxel Dörfler defaultBroadcast, interfaceAddress->local, netmask); 138461729d93SAxel Dörfler } 138561729d93SAxel Dörfler 13862b1c0755SAxel Dörfler interfaceAddress->AddDefaultRoutes(option); 13872b1c0755SAxel Dörfler notify_interface_changed(interface); 138861729d93SAxel Dörfler } 138961729d93SAxel Dörfler 13904ae58630SAxel Dörfler if (interfaceAddress->LocalIsDefined()) 139161729d93SAxel Dörfler sAddressTable.Insert(interfaceAddress); 139261729d93SAxel Dörfler return status; 139361729d93SAxel Dörfler } 139461729d93SAxel Dörfler 139561729d93SAxel Dörfler 139661729d93SAxel Dörfler Interface* 139761729d93SAxel Dörfler get_interface(net_domain* domain, uint32 index) 139861729d93SAxel Dörfler { 139961729d93SAxel Dörfler MutexLocker locker(sLock); 140061729d93SAxel Dörfler 1401ec4fb0f4SAxel Dörfler Interface* interface; 140261729d93SAxel Dörfler if (index == 0) 1403ec4fb0f4SAxel Dörfler interface = sInterfaces.First(); 1404ec4fb0f4SAxel Dörfler else 1405ec4fb0f4SAxel Dörfler interface = find_interface(index); 1406c22d69bfSAxel Dörfler if (interface == NULL) 140761729d93SAxel Dörfler return NULL; 1408c22d69bfSAxel Dörfler 140961729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 141061729d93SAxel Dörfler return NULL; 141161729d93SAxel Dörfler 141261729d93SAxel Dörfler interface->AcquireReference(); 1413c22d69bfSAxel Dörfler return interface; 1414c22d69bfSAxel Dörfler } 1415c22d69bfSAxel Dörfler 141661729d93SAxel Dörfler 141761729d93SAxel Dörfler Interface* 141861729d93SAxel Dörfler get_interface(net_domain* domain, const char* name) 141961729d93SAxel Dörfler { 142061729d93SAxel Dörfler MutexLocker locker(sLock); 142161729d93SAxel Dörfler 142261729d93SAxel Dörfler Interface* interface = find_interface(name); 142361729d93SAxel Dörfler if (interface == NULL) 142461729d93SAxel Dörfler return NULL; 142561729d93SAxel Dörfler 142661729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 142761729d93SAxel Dörfler return NULL; 142861729d93SAxel Dörfler 142961729d93SAxel Dörfler interface->AcquireReference(); 143061729d93SAxel Dörfler return interface; 143161729d93SAxel Dörfler } 143261729d93SAxel Dörfler 143361729d93SAxel Dörfler 143461729d93SAxel Dörfler Interface* 143561729d93SAxel Dörfler get_interface_for_device(net_domain* domain, uint32 index) 143661729d93SAxel Dörfler { 143761729d93SAxel Dörfler MutexLocker locker(sLock); 143861729d93SAxel Dörfler 143961729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 144061729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 144161729d93SAxel Dörfler if (interface->device->index == index) { 144261729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 144361729d93SAxel Dörfler return NULL; 144461729d93SAxel Dörfler 144561729d93SAxel Dörfler interface->AcquireReference(); 144661729d93SAxel Dörfler return interface; 144761729d93SAxel Dörfler } 144861729d93SAxel Dörfler } 144961729d93SAxel Dörfler 1450c22d69bfSAxel Dörfler return NULL; 1451c22d69bfSAxel Dörfler } 1452c22d69bfSAxel Dörfler 1453c22d69bfSAxel Dörfler 1454cd08b9f7SAxel Dörfler /*! Returns a reference to an Interface that matches the given \a linkAddress. 1455cd08b9f7SAxel Dörfler The link address is checked against its hardware address, or its interface 1456cd08b9f7SAxel Dörfler name, or finally the interface index. 1457cd08b9f7SAxel Dörfler */ 1458cd08b9f7SAxel Dörfler Interface* 1459cd08b9f7SAxel Dörfler get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) 1460cd08b9f7SAxel Dörfler { 1461cd08b9f7SAxel Dörfler sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress; 1462cd08b9f7SAxel Dörfler 1463cd08b9f7SAxel Dörfler MutexLocker locker(sLock); 1464cd08b9f7SAxel Dörfler 1465cd08b9f7SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1466cd08b9f7SAxel Dörfler while (Interface* interface = iterator.Next()) { 1467cd08b9f7SAxel Dörfler // Test if the hardware address matches, or if the given interface 1468cd08b9f7SAxel Dörfler // matches, or if at least the index matches. 1469cd08b9f7SAxel Dörfler if ((linkAddress.sdl_alen == interface->device->address.length 1470cd08b9f7SAxel Dörfler && memcmp(LLADDR(&linkAddress), interface->device->address.data, 1471cd08b9f7SAxel Dörfler linkAddress.sdl_alen) == 0) 1472cd08b9f7SAxel Dörfler || (linkAddress.sdl_nlen > 0 1473cd08b9f7SAxel Dörfler && !strcmp(interface->name, (const char*)linkAddress.sdl_data)) 1474cd08b9f7SAxel Dörfler || (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0 1475cd08b9f7SAxel Dörfler && linkAddress.sdl_index == interface->index)) { 1476cd08b9f7SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1477cd08b9f7SAxel Dörfler return NULL; 1478cd08b9f7SAxel Dörfler 1479cd08b9f7SAxel Dörfler interface->AcquireReference(); 1480cd08b9f7SAxel Dörfler return interface; 1481cd08b9f7SAxel Dörfler } 1482cd08b9f7SAxel Dörfler } 1483cd08b9f7SAxel Dörfler 1484cd08b9f7SAxel Dörfler return NULL; 1485cd08b9f7SAxel Dörfler } 1486cd08b9f7SAxel Dörfler 1487cd08b9f7SAxel Dörfler 148861729d93SAxel Dörfler InterfaceAddress* 148961729d93SAxel Dörfler get_interface_address(const sockaddr* local) 1490c22d69bfSAxel Dörfler { 149161729d93SAxel Dörfler if (local->sa_family == AF_UNSPEC) 149261729d93SAxel Dörfler return NULL; 1493c22d69bfSAxel Dörfler 149461729d93SAxel Dörfler MutexLocker locker(sHashLock); 1495c22d69bfSAxel Dörfler 149661729d93SAxel Dörfler InterfaceAddress* address = sAddressTable.Lookup(local); 149761729d93SAxel Dörfler if (address == NULL) 149861729d93SAxel Dörfler return NULL; 1499c22d69bfSAxel Dörfler 150061729d93SAxel Dörfler address->AcquireReference(); 150161729d93SAxel Dörfler return address; 150261729d93SAxel Dörfler } 150361729d93SAxel Dörfler 150461729d93SAxel Dörfler 150561729d93SAxel Dörfler InterfaceAddress* 150661729d93SAxel Dörfler get_interface_address_for_destination(net_domain* domain, 1507cd08b9f7SAxel Dörfler const sockaddr* destination) 150861729d93SAxel Dörfler { 150961729d93SAxel Dörfler MutexLocker locker(sLock); 151061729d93SAxel Dörfler 151161729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 151261729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 151361729d93SAxel Dörfler InterfaceAddress* address 151461729d93SAxel Dörfler = interface->AddressForDestination(domain, destination); 151561729d93SAxel Dörfler if (address != NULL) 151661729d93SAxel Dörfler return address; 151761729d93SAxel Dörfler } 151861729d93SAxel Dörfler 151961729d93SAxel Dörfler return NULL; 152061729d93SAxel Dörfler } 152161729d93SAxel Dörfler 152261729d93SAxel Dörfler 1523cd08b9f7SAxel Dörfler /*! Returns a reference to an InterfaceAddress of the specified \a domain that 1524cd08b9f7SAxel Dörfler belongs to the interface identified via \a linkAddress. Only the hardware 1525cd08b9f7SAxel Dörfler address is matched. 1526cd08b9f7SAxel Dörfler 1527cd08b9f7SAxel Dörfler If \a unconfiguredOnly is set, the interface address must not yet be 1528cd08b9f7SAxel Dörfler configured, or must currently be in the process of being configured. 1529cd08b9f7SAxel Dörfler */ 153061729d93SAxel Dörfler InterfaceAddress* 1531cd08b9f7SAxel Dörfler get_interface_address_for_link(net_domain* domain, const sockaddr* address, 1532cd08b9f7SAxel Dörfler bool unconfiguredOnly) 153361729d93SAxel Dörfler { 1534cd08b9f7SAxel Dörfler sockaddr_dl& linkAddress = *(sockaddr_dl*)address; 153561729d93SAxel Dörfler 153661729d93SAxel Dörfler MutexLocker locker(sLock); 153761729d93SAxel Dörfler 153861729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 153961729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1540cd08b9f7SAxel Dörfler // Test if the hardware address matches, or if the given interface 1541cd08b9f7SAxel Dörfler // matches, or if at least the index matches. 154261729d93SAxel Dörfler if (linkAddress.sdl_alen == interface->device->address.length 154361729d93SAxel Dörfler && memcmp(LLADDR(&linkAddress), interface->device->address.data, 154461729d93SAxel Dörfler linkAddress.sdl_alen) == 0) { 1545b0cf274aSAxel Dörfler TRACE(" %s matches\n", interface->name); 154661729d93SAxel Dörfler // link address matches 154761729d93SAxel Dörfler if (unconfiguredOnly) 154861729d93SAxel Dörfler return interface->FirstUnconfiguredForFamily(domain->family); 154961729d93SAxel Dörfler 155061729d93SAxel Dörfler return interface->FirstForFamily(domain->family); 155161729d93SAxel Dörfler } 155261729d93SAxel Dörfler } 155361729d93SAxel Dörfler 155461729d93SAxel Dörfler return NULL; 1555c22d69bfSAxel Dörfler } 1556c22d69bfSAxel Dörfler 1557c22d69bfSAxel Dörfler 1558c22d69bfSAxel Dörfler uint32 155961729d93SAxel Dörfler count_interfaces() 1560c22d69bfSAxel Dörfler { 156161729d93SAxel Dörfler MutexLocker locker(sLock); 1562c22d69bfSAxel Dörfler 156361729d93SAxel Dörfler return sInterfaces.Count(); 1564c22d69bfSAxel Dörfler } 1565c22d69bfSAxel Dörfler 1566c22d69bfSAxel Dörfler 15673c13a5f5SAxel Dörfler /*! Dumps a list of all interfaces into the supplied userland buffer. 1568c22d69bfSAxel Dörfler If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is 1569c22d69bfSAxel Dörfler returned. 1570c22d69bfSAxel Dörfler */ 1571c22d69bfSAxel Dörfler status_t 157261729d93SAxel Dörfler list_interfaces(int family, void* _buffer, size_t* bufferSize) 1573c22d69bfSAxel Dörfler { 157461729d93SAxel Dörfler MutexLocker locker(sLock); 1575c22d69bfSAxel Dörfler 1576409b1fc0SHugo Santos UserBuffer buffer(_buffer, *bufferSize); 1577c22d69bfSAxel Dörfler 157861729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 157961729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1580715fed44SAxel Dörfler // Copy name 1581715fed44SAxel Dörfler buffer.Push(interface->name, IF_NAMESIZE); 1582c22d69bfSAxel Dörfler 1583715fed44SAxel Dörfler // Copy address 158461729d93SAxel Dörfler InterfaceAddress* address = interface->FirstForFamily(family); 15851f9c8c45SAxel Dörfler size_t length = 0; 1586715fed44SAxel Dörfler 158761729d93SAxel Dörfler if (address != NULL && address->local != NULL) { 1588715fed44SAxel Dörfler // Actual address 15891f9c8c45SAxel Dörfler buffer.Push(address->local, length = address->local->sa_len); 159061729d93SAxel Dörfler } else { 1591715fed44SAxel Dörfler // Empty address 15921f9c8c45SAxel Dörfler sockaddr empty; 15931f9c8c45SAxel Dörfler empty.sa_len = 2; 15941f9c8c45SAxel Dörfler empty.sa_family = AF_UNSPEC; 15951f9c8c45SAxel Dörfler buffer.Push(&empty, length = empty.sa_len); 1596715fed44SAxel Dörfler } 1597715fed44SAxel Dörfler 159861729d93SAxel Dörfler if (address != NULL) 159961729d93SAxel Dörfler address->ReleaseReference(); 160061729d93SAxel Dörfler 16011f9c8c45SAxel Dörfler if (IF_NAMESIZE + length < sizeof(ifreq)) { 16021f9c8c45SAxel Dörfler // Make sure at least sizeof(ifreq) bytes are written for each 16031f9c8c45SAxel Dörfler // interface for compatibility with other platforms 16041f9c8c45SAxel Dörfler buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length); 16051f9c8c45SAxel Dörfler } 16061f9c8c45SAxel Dörfler 16071f9c8c45SAxel Dörfler if (buffer.Status() != B_OK) 1608409b1fc0SHugo Santos return buffer.Status(); 1609c22d69bfSAxel Dörfler } 1610c22d69bfSAxel Dörfler 1611715fed44SAxel Dörfler *bufferSize = buffer.BytesConsumed(); 1612c22d69bfSAxel Dörfler return B_OK; 1613c22d69bfSAxel Dörfler } 1614c22d69bfSAxel Dörfler 1615c22d69bfSAxel Dörfler 1616c22d69bfSAxel Dörfler // #pragma mark - 1617c22d69bfSAxel Dörfler 1618c22d69bfSAxel Dörfler 1619c22d69bfSAxel Dörfler status_t 1620c22d69bfSAxel Dörfler init_interfaces() 1621c22d69bfSAxel Dörfler { 162261729d93SAxel Dörfler mutex_init(&sLock, "net interfaces"); 162361729d93SAxel Dörfler mutex_init(&sHashLock, "net local addresses"); 1624c22d69bfSAxel Dörfler 162561729d93SAxel Dörfler new (&sInterfaces) InterfaceList; 162661729d93SAxel Dörfler new (&sAddressTable) AddressTable; 16279206bb37SAxel Dörfler // static C++ objects are not initialized in the module startup 1628a3ec278aSAxel Dörfler 1629a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 1630a3ec278aSAxel Dörfler add_debugger_command("net_interface", &dump_interface, 1631a3ec278aSAxel Dörfler "Dump the given network interface"); 163261729d93SAxel Dörfler add_debugger_command("net_interfaces", &dump_interfaces, 163361729d93SAxel Dörfler "Dump all network interfaces"); 163461729d93SAxel Dörfler add_debugger_command("net_local", &dump_local, 163561729d93SAxel Dörfler "Dump all local interface addresses"); 163661729d93SAxel Dörfler add_debugger_command("net_route", &dump_route, 163761729d93SAxel Dörfler "Dump the given network route"); 1638a3ec278aSAxel Dörfler #endif 1639c22d69bfSAxel Dörfler return B_OK; 1640c22d69bfSAxel Dörfler } 1641c22d69bfSAxel Dörfler 1642c22d69bfSAxel Dörfler 1643c22d69bfSAxel Dörfler status_t 1644c22d69bfSAxel Dörfler uninit_interfaces() 1645c22d69bfSAxel Dörfler { 1646a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 1647a3ec278aSAxel Dörfler remove_debugger_command("net_interface", &dump_interface); 1648*3f2a0963SPhilippe Houdoin remove_debugger_command("net_interfaces", &dump_interfaces); 1649*3f2a0963SPhilippe Houdoin remove_debugger_command("net_local", &dump_local); 1650*3f2a0963SPhilippe Houdoin remove_debugger_command("net_route", &dump_route); 1651a3ec278aSAxel Dörfler #endif 1652a3ec278aSAxel Dörfler 165361729d93SAxel Dörfler mutex_destroy(&sLock); 165461729d93SAxel Dörfler mutex_destroy(&sHashLock); 1655c22d69bfSAxel Dörfler return B_OK; 1656c22d69bfSAxel Dörfler } 1657c22d69bfSAxel Dörfler 1658