1c22d69bfSAxel Dörfler /* 261729d93SAxel Dörfler * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. 3c22d69bfSAxel Dörfler * Distributed under the terms of the MIT License. 4c22d69bfSAxel Dörfler * 5c22d69bfSAxel Dörfler * Authors: 6c22d69bfSAxel Dörfler * Axel Dörfler, axeld@pinc-software.de 7c22d69bfSAxel Dörfler */ 8c22d69bfSAxel Dörfler 9c22d69bfSAxel Dörfler 10c22d69bfSAxel Dörfler #include "interfaces.h" 11c22d69bfSAxel Dörfler 12c22d69bfSAxel Dörfler #include <net/if_dl.h> 13c22d69bfSAxel Dörfler #include <new> 14a1deb55eSHugo Santos #include <stdio.h> 15c22d69bfSAxel Dörfler #include <stdlib.h> 16c22d69bfSAxel Dörfler #include <string.h> 1761729d93SAxel Dörfler #include <sys/sockio.h> 1861729d93SAxel Dörfler 1961729d93SAxel Dörfler #include <KernelExport.h> 2061729d93SAxel Dörfler 2161729d93SAxel Dörfler #include <net_device.h> 22b0cf274aSAxel Dörfler #include <NetUtilities.h> 2361729d93SAxel Dörfler 2461729d93SAxel Dörfler #include "device_interfaces.h" 2561729d93SAxel Dörfler #include "domains.h" 2661729d93SAxel Dörfler #include "stack_private.h" 2761729d93SAxel Dörfler #include "utility.h" 28c22d69bfSAxel Dörfler 29c22d69bfSAxel Dörfler 3061729d93SAxel Dörfler //#define TRACE_INTERFACES 31c22d69bfSAxel Dörfler #ifdef TRACE_INTERFACES 3261729d93SAxel Dörfler # define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x) 33c22d69bfSAxel Dörfler #else 3461729d93SAxel Dörfler # define TRACE(x...) ; 35c22d69bfSAxel Dörfler #endif 36c22d69bfSAxel Dörfler 3761729d93SAxel Dörfler 3861729d93SAxel Dörfler struct AddressHashDefinition { 3961729d93SAxel Dörfler typedef const sockaddr* KeyType; 4061729d93SAxel Dörfler typedef InterfaceAddress ValueType; 4161729d93SAxel Dörfler 4261729d93SAxel Dörfler AddressHashDefinition() 4361729d93SAxel Dörfler { 4461729d93SAxel Dörfler } 4561729d93SAxel Dörfler 4661729d93SAxel Dörfler size_t HashKey(const KeyType& key) const 4761729d93SAxel Dörfler { 4861729d93SAxel Dörfler net_domain* domain = get_domain(key->sa_family); 4961729d93SAxel Dörfler if (domain == NULL) 5061729d93SAxel Dörfler return 0; 5161729d93SAxel Dörfler 5261729d93SAxel Dörfler return domain->address_module->hash_address(key, false); 5361729d93SAxel Dörfler } 5461729d93SAxel Dörfler 5561729d93SAxel Dörfler size_t Hash(InterfaceAddress* address) const 5661729d93SAxel Dörfler { 5761729d93SAxel Dörfler return address->domain->address_module->hash_address(address->local, false); 5861729d93SAxel Dörfler } 5961729d93SAxel Dörfler 6061729d93SAxel Dörfler bool Compare(const KeyType& key, InterfaceAddress* address) const 6161729d93SAxel Dörfler { 6261729d93SAxel Dörfler if (address->local == NULL) 6361729d93SAxel Dörfler return key->sa_family == AF_UNSPEC; 6461729d93SAxel Dörfler 6561729d93SAxel Dörfler if (address->local->sa_family != key->sa_family) 6661729d93SAxel Dörfler return false; 6761729d93SAxel Dörfler 6861729d93SAxel Dörfler return address->domain->address_module->equal_addresses(key, 6961729d93SAxel Dörfler address->local); 7061729d93SAxel Dörfler } 7161729d93SAxel Dörfler 7261729d93SAxel Dörfler InterfaceAddress*& GetLink(InterfaceAddress* address) const 7361729d93SAxel Dörfler { 7461729d93SAxel Dörfler return address->HashTableLink(); 7561729d93SAxel Dörfler } 7661729d93SAxel Dörfler }; 7761729d93SAxel Dörfler 7861729d93SAxel Dörfler typedef BOpenHashTable<AddressHashDefinition, true, true> AddressTable; 79a3ec278aSAxel Dörfler 80c22d69bfSAxel Dörfler 8161729d93SAxel Dörfler static mutex sLock; 8261729d93SAxel Dörfler static InterfaceList sInterfaces; 8361729d93SAxel Dörfler static mutex sHashLock; 8461729d93SAxel Dörfler static AddressTable sAddressTable; 85c22d69bfSAxel Dörfler static uint32 sInterfaceIndex; 869261b129SHugo Santos 879261b129SHugo Santos 88a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 89a3ec278aSAxel Dörfler 90a3ec278aSAxel Dörfler 91a3ec278aSAxel Dörfler static int 92a3ec278aSAxel Dörfler dump_interface(int argc, char** argv) 93a3ec278aSAxel Dörfler { 94a3ec278aSAxel Dörfler if (argc != 2) { 95a3ec278aSAxel Dörfler kprintf("usage: %s [address]\n", argv[0]); 96a3ec278aSAxel Dörfler return 0; 97a3ec278aSAxel Dörfler } 98a3ec278aSAxel Dörfler 9961729d93SAxel Dörfler Interface* interface = (Interface*)parse_expression(argv[1]); 10061729d93SAxel Dörfler interface->Dump(); 101a3ec278aSAxel Dörfler 102a3ec278aSAxel Dörfler return 0; 103a3ec278aSAxel Dörfler } 104a3ec278aSAxel Dörfler 105a3ec278aSAxel Dörfler 106a3ec278aSAxel Dörfler static int 10761729d93SAxel Dörfler dump_interfaces(int argc, char** argv) 10861729d93SAxel Dörfler { 10961729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 11061729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 11161729d93SAxel Dörfler kprintf("%p %s\n", interface, interface->name); 11261729d93SAxel Dörfler } 11361729d93SAxel Dörfler return 0; 11461729d93SAxel Dörfler } 11561729d93SAxel Dörfler 11661729d93SAxel Dörfler 11761729d93SAxel Dörfler static int 11861729d93SAxel Dörfler dump_local(int argc, char** argv) 11961729d93SAxel Dörfler { 12061729d93SAxel Dörfler AddressTable::Iterator iterator = sAddressTable.GetIterator(); 12161729d93SAxel Dörfler size_t i = 0; 12261729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 12361729d93SAxel Dörfler address->Dump(++i); 12461729d93SAxel Dörfler dprintf(" hash: %lu\n", 12561729d93SAxel Dörfler address->domain->address_module->hash_address(address->local, 12661729d93SAxel Dörfler false)); 12761729d93SAxel Dörfler } 12861729d93SAxel Dörfler return 0; 12961729d93SAxel Dörfler } 13061729d93SAxel Dörfler 13161729d93SAxel Dörfler 13261729d93SAxel Dörfler static int 13361729d93SAxel Dörfler dump_route(int argc, char** argv) 134a3ec278aSAxel Dörfler { 135a3ec278aSAxel Dörfler if (argc != 2) { 136a3ec278aSAxel Dörfler kprintf("usage: %s [address]\n", argv[0]); 137a3ec278aSAxel Dörfler return 0; 138a3ec278aSAxel Dörfler } 139a3ec278aSAxel Dörfler 14061729d93SAxel Dörfler net_route* route = (net_route*)parse_expression(argv[1]); 14161729d93SAxel Dörfler kprintf("destination: %p\n", route->destination); 14261729d93SAxel Dörfler kprintf("mask: %p\n", route->mask); 14361729d93SAxel Dörfler kprintf("gateway: %p\n", route->gateway); 14461729d93SAxel Dörfler kprintf("flags: %" B_PRIx32 "\n", route->flags); 14561729d93SAxel Dörfler kprintf("mtu: %" B_PRIu32 "\n", route->mtu); 14661729d93SAxel Dörfler kprintf("interface address: %p\n", route->interface_address); 147a3ec278aSAxel Dörfler 14861729d93SAxel Dörfler if (route->interface_address != NULL) { 14961729d93SAxel Dörfler ((InterfaceAddress*)route->interface_address)->Dump(); 150a3ec278aSAxel Dörfler } 151a3ec278aSAxel Dörfler 152a3ec278aSAxel Dörfler return 0; 153a3ec278aSAxel Dörfler } 154a3ec278aSAxel Dörfler 155a3ec278aSAxel Dörfler 156a3ec278aSAxel Dörfler #endif // ENABLE_DEBUGGER_COMMANDS 157a3ec278aSAxel Dörfler 158a3ec278aSAxel Dörfler 15961729d93SAxel Dörfler InterfaceAddress::InterfaceAddress() 160c22d69bfSAxel Dörfler { 16161729d93SAxel Dörfler _Init(NULL, NULL); 16261729d93SAxel Dörfler } 163c22d69bfSAxel Dörfler 16461729d93SAxel Dörfler 16561729d93SAxel Dörfler InterfaceAddress::InterfaceAddress(net_interface* netInterface, 16661729d93SAxel Dörfler net_domain* netDomain) 16761729d93SAxel Dörfler { 16861729d93SAxel Dörfler _Init(netInterface, netDomain); 16961729d93SAxel Dörfler } 17061729d93SAxel Dörfler 17161729d93SAxel Dörfler 17261729d93SAxel Dörfler InterfaceAddress::~InterfaceAddress() 17361729d93SAxel Dörfler { 1742b1c0755SAxel Dörfler TRACE("InterfaceAddress %p: destructor\n", this); 1752b1c0755SAxel Dörfler 1762b1c0755SAxel Dörfler if (interface != NULL && (flags & IFAF_DIRECT_ADDRESS) == 0) 1772b1c0755SAxel Dörfler ((Interface*)interface)->ReleaseReference(); 17861729d93SAxel Dörfler } 17961729d93SAxel Dörfler 18061729d93SAxel Dörfler 18161729d93SAxel Dörfler status_t 18261729d93SAxel Dörfler InterfaceAddress::SetTo(const ifaliasreq& request) 18361729d93SAxel Dörfler { 18461729d93SAxel Dörfler status_t status = SetLocal((const sockaddr*)&request.ifra_addr); 18561729d93SAxel Dörfler if (status == B_OK) 18661729d93SAxel Dörfler status = SetDestination((const sockaddr*)&request.ifra_broadaddr); 18761729d93SAxel Dörfler if (status == B_OK) 18861729d93SAxel Dörfler status = SetMask((const sockaddr*)&request.ifra_mask); 18961729d93SAxel Dörfler 19061729d93SAxel Dörfler return status; 19161729d93SAxel Dörfler } 19261729d93SAxel Dörfler 19361729d93SAxel Dörfler 19461729d93SAxel Dörfler status_t 19561729d93SAxel Dörfler InterfaceAddress::SetLocal(const sockaddr* to) 19661729d93SAxel Dörfler { 19761729d93SAxel Dörfler return Set(&local, to); 19861729d93SAxel Dörfler } 19961729d93SAxel Dörfler 20061729d93SAxel Dörfler 20161729d93SAxel Dörfler status_t 20261729d93SAxel Dörfler InterfaceAddress::SetDestination(const sockaddr* to) 20361729d93SAxel Dörfler { 20461729d93SAxel Dörfler return Set(&destination, to); 20561729d93SAxel Dörfler } 20661729d93SAxel Dörfler 20761729d93SAxel Dörfler 20861729d93SAxel Dörfler status_t 20961729d93SAxel Dörfler InterfaceAddress::SetMask(const sockaddr* to) 21061729d93SAxel Dörfler { 21161729d93SAxel Dörfler return Set(&mask, to); 21261729d93SAxel Dörfler } 21361729d93SAxel Dörfler 21461729d93SAxel Dörfler 21561729d93SAxel Dörfler sockaddr** 21661729d93SAxel Dörfler InterfaceAddress::AddressFor(int32 option) 21761729d93SAxel Dörfler { 21861729d93SAxel Dörfler switch (option) { 21961729d93SAxel Dörfler case SIOCSIFADDR: 22061729d93SAxel Dörfler case SIOCGIFADDR: 2212b1c0755SAxel Dörfler case SIOCDIFADDR: 22261729d93SAxel Dörfler return &local; 22361729d93SAxel Dörfler 22461729d93SAxel Dörfler case SIOCSIFNETMASK: 22561729d93SAxel Dörfler case SIOCGIFNETMASK: 22661729d93SAxel Dörfler return &mask; 22761729d93SAxel Dörfler 22861729d93SAxel Dörfler case SIOCSIFBRDADDR: 22961729d93SAxel Dörfler case SIOCSIFDSTADDR: 23061729d93SAxel Dörfler case SIOCGIFBRDADDR: 23161729d93SAxel Dörfler case SIOCGIFDSTADDR: 23261729d93SAxel Dörfler return &destination; 23361729d93SAxel Dörfler 23461729d93SAxel Dörfler default: 23561729d93SAxel Dörfler return NULL; 23661729d93SAxel Dörfler } 23761729d93SAxel Dörfler } 23861729d93SAxel Dörfler 23961729d93SAxel Dörfler 2402b1c0755SAxel Dörfler /*! Adds the default routes that every interface address needs, ie. the local 2412b1c0755SAxel Dörfler host route, and one for the subnet (if set). 2422b1c0755SAxel Dörfler */ 2432b1c0755SAxel Dörfler void 2442b1c0755SAxel Dörfler InterfaceAddress::AddDefaultRoutes(int32 option) 2452b1c0755SAxel Dörfler { 2462b1c0755SAxel Dörfler net_route route; 2472b1c0755SAxel Dörfler route.destination = local; 2482b1c0755SAxel Dörfler route.gateway = NULL; 2492b1c0755SAxel Dörfler route.interface_address = this; 2502b1c0755SAxel Dörfler 2512b1c0755SAxel Dörfler if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) { 2522b1c0755SAxel Dörfler route.mask = mask; 2532b1c0755SAxel Dörfler route.flags = 0; 2542b1c0755SAxel Dörfler add_route(domain, &route); 2552b1c0755SAxel Dörfler } 2562b1c0755SAxel Dörfler 2572b1c0755SAxel Dörfler if (option == SIOCSIFADDR) { 2582b1c0755SAxel Dörfler route.mask = NULL; 2592b1c0755SAxel Dörfler route.flags = RTF_LOCAL | RTF_HOST; 2602b1c0755SAxel Dörfler add_route(domain, &route); 2612b1c0755SAxel Dörfler } 2622b1c0755SAxel Dörfler } 2632b1c0755SAxel Dörfler 2642b1c0755SAxel Dörfler 2652b1c0755SAxel Dörfler /*! Removes the default routes as set by AddDefaultRoutes() again. */ 2662b1c0755SAxel Dörfler void 2672b1c0755SAxel Dörfler InterfaceAddress::RemoveDefaultRoutes(int32 option) 2682b1c0755SAxel Dörfler { 2692b1c0755SAxel Dörfler net_route route; 2702b1c0755SAxel Dörfler route.destination = local; 2712b1c0755SAxel Dörfler route.gateway = NULL; 2722b1c0755SAxel Dörfler route.interface_address = this; 2732b1c0755SAxel Dörfler 2742b1c0755SAxel Dörfler if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) { 2752b1c0755SAxel Dörfler route.mask = mask; 2762b1c0755SAxel Dörfler route.flags = 0; 2772b1c0755SAxel Dörfler remove_route(domain, &route); 2782b1c0755SAxel Dörfler } 2792b1c0755SAxel Dörfler 2802b1c0755SAxel Dörfler if (option == SIOCSIFADDR) { 2812b1c0755SAxel Dörfler route.mask = NULL; 2822b1c0755SAxel Dörfler route.flags = RTF_LOCAL | RTF_HOST; 2832b1c0755SAxel Dörfler remove_route(domain, &route); 2842b1c0755SAxel Dörfler } 2852b1c0755SAxel Dörfler } 2862b1c0755SAxel Dörfler 2872b1c0755SAxel Dörfler 28861729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 28961729d93SAxel Dörfler 29061729d93SAxel Dörfler 29161729d93SAxel Dörfler void 29261729d93SAxel Dörfler InterfaceAddress::Dump(size_t index, bool hideInterface) 29361729d93SAxel Dörfler { 29461729d93SAxel Dörfler if (index) 29561729d93SAxel Dörfler kprintf("%2zu. ", index); 29661729d93SAxel Dörfler else 29761729d93SAxel Dörfler kprintf(" "); 29861729d93SAxel Dörfler 29961729d93SAxel Dörfler if (!hideInterface) { 30061729d93SAxel Dörfler kprintf("interface: %p (%s)\n ", interface, 30161729d93SAxel Dörfler interface != NULL ? interface->name : "-"); 30261729d93SAxel Dörfler } 30361729d93SAxel Dörfler 30461729d93SAxel Dörfler kprintf("domain: %p (family %u)\n", domain, 30561729d93SAxel Dörfler domain != NULL ? domain->family : AF_UNSPEC); 30661729d93SAxel Dörfler 30761729d93SAxel Dörfler char buffer[64]; 30861729d93SAxel Dörfler if (local != NULL && domain != NULL) { 30961729d93SAxel Dörfler domain->address_module->print_address_buffer(local, buffer, 31061729d93SAxel Dörfler sizeof(buffer), false); 31161729d93SAxel Dörfler } else 31261729d93SAxel Dörfler strcpy(buffer, "-"); 31361729d93SAxel Dörfler kprintf(" local: %s\n", buffer); 31461729d93SAxel Dörfler 31561729d93SAxel Dörfler if (mask != NULL && domain != NULL) { 31661729d93SAxel Dörfler domain->address_module->print_address_buffer(mask, buffer, 31761729d93SAxel Dörfler sizeof(buffer), false); 31861729d93SAxel Dörfler } else 31961729d93SAxel Dörfler strcpy(buffer, "-"); 32061729d93SAxel Dörfler kprintf(" mask: %s\n", buffer); 32161729d93SAxel Dörfler 32261729d93SAxel Dörfler if (destination != NULL && domain != NULL) { 32361729d93SAxel Dörfler domain->address_module->print_address_buffer(destination, buffer, 32461729d93SAxel Dörfler sizeof(buffer), false); 32561729d93SAxel Dörfler } else 32661729d93SAxel Dörfler strcpy(buffer, "-"); 32761729d93SAxel Dörfler kprintf(" destination: %s\n", buffer); 3284af124a1SAxel Dörfler 3294af124a1SAxel Dörfler kprintf(" ref count: %" B_PRId32 "\n", CountReferences()); 33061729d93SAxel Dörfler } 33161729d93SAxel Dörfler 33261729d93SAxel Dörfler 33361729d93SAxel Dörfler #endif // ENABLE_DEBUGGER_COMMANDS 33461729d93SAxel Dörfler 33561729d93SAxel Dörfler 33661729d93SAxel Dörfler /*static*/ status_t 33761729d93SAxel Dörfler InterfaceAddress::Set(sockaddr** _address, const sockaddr* to) 33861729d93SAxel Dörfler { 33961729d93SAxel Dörfler sockaddr* address = *_address; 34061729d93SAxel Dörfler 34161729d93SAxel Dörfler if (to == NULL || to->sa_family == AF_UNSPEC) { 34261729d93SAxel Dörfler // Clear address 34361729d93SAxel Dörfler free(address); 34461729d93SAxel Dörfler *_address = NULL; 34561729d93SAxel Dörfler return B_OK; 34661729d93SAxel Dörfler } 34761729d93SAxel Dörfler 34861729d93SAxel Dörfler // Set address 34961729d93SAxel Dörfler 35061729d93SAxel Dörfler size_t size = max_c(to->sa_len, sizeof(sockaddr)); 35161729d93SAxel Dörfler if (size > sizeof(sockaddr_storage)) 35261729d93SAxel Dörfler size = sizeof(sockaddr_storage); 35361729d93SAxel Dörfler 35461729d93SAxel Dörfler address = Prepare(_address, size); 35561729d93SAxel Dörfler if (address == NULL) 35661729d93SAxel Dörfler return B_NO_MEMORY; 35761729d93SAxel Dörfler 35861729d93SAxel Dörfler memcpy(address, to, size); 35961729d93SAxel Dörfler address->sa_len = size; 36061729d93SAxel Dörfler 36161729d93SAxel Dörfler return B_OK; 36261729d93SAxel Dörfler } 36361729d93SAxel Dörfler 36461729d93SAxel Dörfler 36561729d93SAxel Dörfler /*static*/ sockaddr* 36661729d93SAxel Dörfler InterfaceAddress::Prepare(sockaddr** _address, size_t size) 36761729d93SAxel Dörfler { 36861729d93SAxel Dörfler size = max_c(size, sizeof(sockaddr)); 36961729d93SAxel Dörfler if (size > sizeof(sockaddr_storage)) 37061729d93SAxel Dörfler size = sizeof(sockaddr_storage); 37161729d93SAxel Dörfler 37261729d93SAxel Dörfler sockaddr* address = *_address; 37361729d93SAxel Dörfler 37461729d93SAxel Dörfler if (address == NULL || size > address->sa_len) { 37561729d93SAxel Dörfler address = (sockaddr*)realloc(address, size); 37661729d93SAxel Dörfler if (address == NULL) 37761729d93SAxel Dörfler return NULL; 37861729d93SAxel Dörfler } 37961729d93SAxel Dörfler 38061729d93SAxel Dörfler address->sa_len = size; 38161729d93SAxel Dörfler 38261729d93SAxel Dörfler *_address = address; 38361729d93SAxel Dörfler return address; 38461729d93SAxel Dörfler } 38561729d93SAxel Dörfler 38661729d93SAxel Dörfler 38761729d93SAxel Dörfler void 38861729d93SAxel Dörfler InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain) 38961729d93SAxel Dörfler { 3902b1c0755SAxel Dörfler TRACE("InterfaceAddress %p: init interface %p, domain %p\n", this, 3912b1c0755SAxel Dörfler netInterface, netDomain); 3922b1c0755SAxel Dörfler 39361729d93SAxel Dörfler interface = netInterface; 39461729d93SAxel Dörfler domain = netDomain; 39561729d93SAxel Dörfler local = NULL; 39661729d93SAxel Dörfler destination = NULL; 39761729d93SAxel Dörfler mask = NULL; 3982b1c0755SAxel Dörfler flags = 0; 3992b1c0755SAxel Dörfler 4002b1c0755SAxel Dörfler if (interface != NULL) 4012b1c0755SAxel Dörfler ((Interface*)interface)->AcquireReference(); 40261729d93SAxel Dörfler } 40361729d93SAxel Dörfler 40461729d93SAxel Dörfler 40561729d93SAxel Dörfler // #pragma mark - 40661729d93SAxel Dörfler 40761729d93SAxel Dörfler 40861729d93SAxel Dörfler Interface::Interface(const char* interfaceName, 40961729d93SAxel Dörfler net_device_interface* deviceInterface) 41061729d93SAxel Dörfler { 41161729d93SAxel Dörfler TRACE("Interface %p: new \"%s\", device interface %p\n", this, 41261729d93SAxel Dörfler interfaceName, deviceInterface); 41361729d93SAxel Dörfler 414b0cf274aSAxel Dörfler int written = strlcpy(name, interfaceName, IF_NAMESIZE); 415b0cf274aSAxel Dörfler memset(name + written, 0, IF_NAMESIZE - written); 416b0cf274aSAxel Dörfler // Clear remaining space 417b0cf274aSAxel Dörfler 41861729d93SAxel Dörfler device = deviceInterface->device; 41961729d93SAxel Dörfler 42061729d93SAxel Dörfler index = ++sInterfaceIndex; 42161729d93SAxel Dörfler flags = 0; 42261729d93SAxel Dörfler type = 0; 42361729d93SAxel Dörfler mtu = deviceInterface->device->mtu; 42461729d93SAxel Dörfler metric = 0; 42561729d93SAxel Dörfler 42661729d93SAxel Dörfler fDeviceInterface = acquire_device_interface(deviceInterface); 42761729d93SAxel Dörfler 42861729d93SAxel Dörfler recursive_lock_init(&fLock, name); 42961729d93SAxel Dörfler 43061729d93SAxel Dörfler // Grab a reference to the networking stack, to make sure it won't be 43161729d93SAxel Dörfler // unloaded as long as an interface exists 43261729d93SAxel Dörfler module_info* module; 43361729d93SAxel Dörfler get_module(gNetStackInterfaceModule.info.name, &module); 43461729d93SAxel Dörfler } 43561729d93SAxel Dörfler 43661729d93SAxel Dörfler 43761729d93SAxel Dörfler Interface::~Interface() 43861729d93SAxel Dörfler { 4392b1c0755SAxel Dörfler TRACE("Interface %p: destructor\n", this); 4402b1c0755SAxel Dörfler 4412b1c0755SAxel Dörfler put_device_interface(fDeviceInterface); 4422b1c0755SAxel Dörfler 4432b1c0755SAxel Dörfler // Uninitialize the domain datalink protocols 4442b1c0755SAxel Dörfler 4452b1c0755SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 4462b1c0755SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) { 4472b1c0755SAxel Dörfler put_domain_datalink_protocols(this, datalink->domain); 4482b1c0755SAxel Dörfler } 4492b1c0755SAxel Dörfler 4502b1c0755SAxel Dörfler // Free domain datalink objects 4512b1c0755SAxel Dörfler 4522b1c0755SAxel Dörfler domain_datalink* next = fDatalinkTable.Clear(true); 4532b1c0755SAxel Dörfler while (next != NULL) { 4542b1c0755SAxel Dörfler domain_datalink* datalink = next; 4552b1c0755SAxel Dörfler next = next->hash_link; 4562b1c0755SAxel Dörfler 4572b1c0755SAxel Dörfler delete datalink; 4582b1c0755SAxel Dörfler } 4592b1c0755SAxel Dörfler 46061729d93SAxel Dörfler recursive_lock_destroy(&fLock); 46161729d93SAxel Dörfler 46261729d93SAxel Dörfler // Release reference of the stack - at this point, our stack may be unloaded 46361729d93SAxel Dörfler // if no other interfaces or sockets are left 46461729d93SAxel Dörfler put_module(gNetStackInterfaceModule.info.name); 46561729d93SAxel Dörfler } 46661729d93SAxel Dörfler 46761729d93SAxel Dörfler 46861729d93SAxel Dörfler /*! Returns a reference to the first InterfaceAddress that is from the same 46961729d93SAxel Dörfler as the specified \a family. 47061729d93SAxel Dörfler */ 47161729d93SAxel Dörfler InterfaceAddress* 47261729d93SAxel Dörfler Interface::FirstForFamily(int family) 47361729d93SAxel Dörfler { 47461729d93SAxel Dörfler RecursiveLocker locker(fLock); 47561729d93SAxel Dörfler 47661729d93SAxel Dörfler InterfaceAddress* address = _FirstForFamily(family); 47761729d93SAxel Dörfler if (address != NULL) { 47861729d93SAxel Dörfler address->AcquireReference(); 47961729d93SAxel Dörfler return address; 48061729d93SAxel Dörfler } 48161729d93SAxel Dörfler 48261729d93SAxel Dörfler return NULL; 48361729d93SAxel Dörfler } 48461729d93SAxel Dörfler 48561729d93SAxel Dörfler 48661729d93SAxel Dörfler /*! Returns a reference to the first unconfigured address of this interface 48761729d93SAxel Dörfler for the specified \a family. 48861729d93SAxel Dörfler */ 48961729d93SAxel Dörfler InterfaceAddress* 49061729d93SAxel Dörfler Interface::FirstUnconfiguredForFamily(int family) 49161729d93SAxel Dörfler { 49261729d93SAxel Dörfler RecursiveLocker locker(fLock); 49361729d93SAxel Dörfler 49461729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 49561729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 49661729d93SAxel Dörfler if (address->domain->family == family 49761729d93SAxel Dörfler && (address->local == NULL 49861729d93SAxel Dörfler // TODO: this has to be solved differently!! 49961729d93SAxel Dörfler || (flags & IFF_CONFIGURING) != 0)) { 50061729d93SAxel Dörfler address->AcquireReference(); 50161729d93SAxel Dörfler return address; 50261729d93SAxel Dörfler } 50361729d93SAxel Dörfler } 50461729d93SAxel Dörfler 50561729d93SAxel Dörfler return NULL; 50661729d93SAxel Dörfler } 50761729d93SAxel Dörfler 50861729d93SAxel Dörfler 50961729d93SAxel Dörfler /*! Returns a reference to the InterfaceAddress that has the specified 51061729d93SAxel Dörfler \a destination address. 51161729d93SAxel Dörfler */ 51261729d93SAxel Dörfler InterfaceAddress* 51361729d93SAxel Dörfler Interface::AddressForDestination(net_domain* domain, 51461729d93SAxel Dörfler const sockaddr* destination) 51561729d93SAxel Dörfler { 51661729d93SAxel Dörfler RecursiveLocker locker(fLock); 51761729d93SAxel Dörfler 51861729d93SAxel Dörfler if ((device->flags & IFF_BROADCAST) == 0) { 51961729d93SAxel Dörfler // The device does not support broadcasting 52061729d93SAxel Dörfler return NULL; 52161729d93SAxel Dörfler } 52261729d93SAxel Dörfler 52361729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 52461729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 52561729d93SAxel Dörfler if (address->domain == domain 52661729d93SAxel Dörfler && address->destination != NULL 52761729d93SAxel Dörfler && domain->address_module->equal_addresses(address->destination, 52861729d93SAxel Dörfler destination)) { 52961729d93SAxel Dörfler address->AcquireReference(); 53061729d93SAxel Dörfler return address; 53161729d93SAxel Dörfler } 53261729d93SAxel Dörfler } 53361729d93SAxel Dörfler 53461729d93SAxel Dörfler return NULL; 53561729d93SAxel Dörfler } 53661729d93SAxel Dörfler 53761729d93SAxel Dörfler 538910ffb32SAxel Dörfler /*! Returns a reference to the InterfaceAddress that has the specified 539910ffb32SAxel Dörfler \a local address. 540910ffb32SAxel Dörfler */ 541910ffb32SAxel Dörfler InterfaceAddress* 542910ffb32SAxel Dörfler Interface::AddressForLocal(net_domain* domain, const sockaddr* local) 543910ffb32SAxel Dörfler { 544910ffb32SAxel Dörfler RecursiveLocker locker(fLock); 545910ffb32SAxel Dörfler 546910ffb32SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 547910ffb32SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 548910ffb32SAxel Dörfler if (address->domain == domain 549910ffb32SAxel Dörfler && address->local != NULL 550910ffb32SAxel Dörfler && domain->address_module->equal_addresses(address->local, local)) { 551910ffb32SAxel Dörfler address->AcquireReference(); 552910ffb32SAxel Dörfler return address; 553910ffb32SAxel Dörfler } 554910ffb32SAxel Dörfler } 555910ffb32SAxel Dörfler 556910ffb32SAxel Dörfler return NULL; 557910ffb32SAxel Dörfler } 558910ffb32SAxel Dörfler 559910ffb32SAxel Dörfler 56061729d93SAxel Dörfler status_t 56161729d93SAxel Dörfler Interface::AddAddress(InterfaceAddress* address) 56261729d93SAxel Dörfler { 56361729d93SAxel Dörfler net_domain* domain = address->domain; 56461729d93SAxel Dörfler if (domain == NULL) 56561729d93SAxel Dörfler return B_BAD_VALUE; 56661729d93SAxel Dörfler 56761729d93SAxel Dörfler RecursiveLocker locker(fLock); 56861729d93SAxel Dörfler fAddresses.Add(address); 56961729d93SAxel Dörfler locker.Unlock(); 57061729d93SAxel Dörfler 57161729d93SAxel Dörfler MutexLocker hashLocker(sHashLock); 57261729d93SAxel Dörfler sAddressTable.Insert(address); 57361729d93SAxel Dörfler return B_OK; 57461729d93SAxel Dörfler } 57561729d93SAxel Dörfler 57661729d93SAxel Dörfler 57761729d93SAxel Dörfler void 57861729d93SAxel Dörfler Interface::RemoveAddress(InterfaceAddress* address) 57961729d93SAxel Dörfler { 58061729d93SAxel Dörfler net_domain* domain = address->domain; 58161729d93SAxel Dörfler if (domain == NULL) 58261729d93SAxel Dörfler return; 58361729d93SAxel Dörfler 58461729d93SAxel Dörfler RecursiveLocker locker(fLock); 58561729d93SAxel Dörfler 58661729d93SAxel Dörfler fAddresses.Remove(address); 58761729d93SAxel Dörfler address->GetDoublyLinkedListLink()->next = NULL; 58861729d93SAxel Dörfler 58961729d93SAxel Dörfler locker.Unlock(); 59061729d93SAxel Dörfler 59161729d93SAxel Dörfler MutexLocker hashLocker(sHashLock); 59261729d93SAxel Dörfler sAddressTable.Remove(address); 59361729d93SAxel Dörfler } 59461729d93SAxel Dörfler 59561729d93SAxel Dörfler 59661729d93SAxel Dörfler bool 59761729d93SAxel Dörfler Interface::GetNextAddress(InterfaceAddress** _address) 59861729d93SAxel Dörfler { 59961729d93SAxel Dörfler RecursiveLocker locker(fLock); 60061729d93SAxel Dörfler 60161729d93SAxel Dörfler InterfaceAddress* address = *_address; 60261729d93SAxel Dörfler if (address == NULL) { 60361729d93SAxel Dörfler // get first address 60461729d93SAxel Dörfler address = fAddresses.First(); 60561729d93SAxel Dörfler } else { 60661729d93SAxel Dörfler // get next, if possible 60761729d93SAxel Dörfler InterfaceAddress* next = fAddresses.GetNext(address); 60861729d93SAxel Dörfler address->ReleaseReference(); 60961729d93SAxel Dörfler address = next; 61061729d93SAxel Dörfler } 61161729d93SAxel Dörfler 61261729d93SAxel Dörfler *_address = address; 61361729d93SAxel Dörfler 61461729d93SAxel Dörfler if (address == NULL) 61561729d93SAxel Dörfler return false; 61661729d93SAxel Dörfler 61761729d93SAxel Dörfler address->AcquireReference(); 61861729d93SAxel Dörfler return true; 61961729d93SAxel Dörfler } 62061729d93SAxel Dörfler 62161729d93SAxel Dörfler 6229d771afbSAxel Dörfler InterfaceAddress* 6239d771afbSAxel Dörfler Interface::AddressAt(size_t index) 6249d771afbSAxel Dörfler { 6259d771afbSAxel Dörfler RecursiveLocker locker(fLock); 6269d771afbSAxel Dörfler 6279d771afbSAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 6289d771afbSAxel Dörfler size_t i = 0; 6299d771afbSAxel Dörfler 6309d771afbSAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 6319d771afbSAxel Dörfler if (i++ == index) { 6329d771afbSAxel Dörfler address->AcquireReference(); 6339d771afbSAxel Dörfler return address; 6349d771afbSAxel Dörfler } 6359d771afbSAxel Dörfler } 6369d771afbSAxel Dörfler 6379d771afbSAxel Dörfler return NULL; 6389d771afbSAxel Dörfler } 6399d771afbSAxel Dörfler 6409d771afbSAxel Dörfler 6412c12b8a3SAxel Dörfler int32 6422c12b8a3SAxel Dörfler Interface::IndexOfAddress(InterfaceAddress* address) 6432c12b8a3SAxel Dörfler { 6442c12b8a3SAxel Dörfler RecursiveLocker locker(fLock); 6452c12b8a3SAxel Dörfler 6462c12b8a3SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 6472c12b8a3SAxel Dörfler int32 index = 0; 6482c12b8a3SAxel Dörfler 6492c12b8a3SAxel Dörfler while (iterator.HasNext()) { 6502c12b8a3SAxel Dörfler if (address == iterator.Next()) 6512c12b8a3SAxel Dörfler return index; 6522c12b8a3SAxel Dörfler 6532c12b8a3SAxel Dörfler index++; 6542c12b8a3SAxel Dörfler } 6552c12b8a3SAxel Dörfler 6562c12b8a3SAxel Dörfler return -1; 6572c12b8a3SAxel Dörfler } 6582c12b8a3SAxel Dörfler 6592c12b8a3SAxel Dörfler 6609d771afbSAxel Dörfler size_t 6619d771afbSAxel Dörfler Interface::CountAddresses() 6629d771afbSAxel Dörfler { 6639d771afbSAxel Dörfler RecursiveLocker locker(fLock); 6649d771afbSAxel Dörfler return fAddresses.Count(); 6659d771afbSAxel Dörfler } 6669d771afbSAxel Dörfler 6679d771afbSAxel Dörfler 6682b1c0755SAxel Dörfler void 6692b1c0755SAxel Dörfler Interface::RemoveAddresses() 6702b1c0755SAxel Dörfler { 6712b1c0755SAxel Dörfler RecursiveLocker locker(fLock); 6722b1c0755SAxel Dörfler 6732b1c0755SAxel Dörfler while (InterfaceAddress* address = fAddresses.RemoveHead()) { 6742b1c0755SAxel Dörfler address->ReleaseReference(); 6752b1c0755SAxel Dörfler } 6762b1c0755SAxel Dörfler } 6772b1c0755SAxel Dörfler 6782b1c0755SAxel Dörfler 6799d771afbSAxel Dörfler /*! This is called in order to call the correct methods of the datalink 6809d771afbSAxel Dörfler protocols, ie. it will translate address changes to 6819d771afbSAxel Dörfler net_datalink_protocol::change_address(), and IFF_UP changes to 6829d771afbSAxel Dörfler net_datalink_protocol::interface_up(), and interface_down(). 6839d771afbSAxel Dörfler 6849d771afbSAxel Dörfler Everything else is passed unchanged to net_datalink_protocol::control(). 6859d771afbSAxel Dörfler */ 68661729d93SAxel Dörfler status_t 68761729d93SAxel Dörfler Interface::Control(net_domain* domain, int32 option, ifreq& request, 68861729d93SAxel Dörfler ifreq* userRequest, size_t length) 68961729d93SAxel Dörfler { 69061729d93SAxel Dörfler switch (option) { 69161729d93SAxel Dörfler case SIOCSIFFLAGS: 69261729d93SAxel Dörfler { 693e8802e49SAxel Dörfler if (length != sizeof(ifreq)) 694e8802e49SAxel Dörfler return B_BAD_VALUE; 695e8802e49SAxel Dörfler 69661729d93SAxel Dörfler uint32 requestFlags = request.ifr_flags; 69761729d93SAxel Dörfler uint32 oldFlags = flags; 69861729d93SAxel Dörfler status_t status = B_OK; 69961729d93SAxel Dörfler 70061729d93SAxel Dörfler request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST); 70161729d93SAxel Dörfler 70261729d93SAxel Dörfler if ((requestFlags & IFF_UP) != (flags & IFF_UP)) { 70361729d93SAxel Dörfler if ((requestFlags & IFF_UP) != 0) 70461729d93SAxel Dörfler status = _SetUp(); 70561729d93SAxel Dörfler else 7062b1c0755SAxel Dörfler SetDown(); 70761729d93SAxel Dörfler } 70861729d93SAxel Dörfler 70961729d93SAxel Dörfler if (status == B_OK) { 71061729d93SAxel Dörfler // TODO: maybe allow deleting IFF_BROADCAST on the interface 71161729d93SAxel Dörfler // level? 71261729d93SAxel Dörfler flags &= IFF_UP | IFF_LINK | IFF_BROADCAST; 71361729d93SAxel Dörfler flags |= request.ifr_flags; 71461729d93SAxel Dörfler } 71561729d93SAxel Dörfler 71661729d93SAxel Dörfler if (oldFlags != flags) 71761729d93SAxel Dörfler notify_interface_changed(this, oldFlags, flags); 71861729d93SAxel Dörfler 71961729d93SAxel Dörfler return status; 72061729d93SAxel Dörfler } 72161729d93SAxel Dörfler 7222b1c0755SAxel Dörfler case B_SOCKET_SET_ALIAS: 7239d771afbSAxel Dörfler { 724e8802e49SAxel Dörfler if (length != sizeof(ifaliasreq)) 725e8802e49SAxel Dörfler return B_BAD_VALUE; 726e8802e49SAxel Dörfler 7279d771afbSAxel Dörfler RecursiveLocker locker(fLock); 7289d771afbSAxel Dörfler 7299d771afbSAxel Dörfler ifaliasreq aliasRequest; 7309d771afbSAxel Dörfler if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq)) 7319d771afbSAxel Dörfler != B_OK) 7329d771afbSAxel Dörfler return B_BAD_ADDRESS; 7339d771afbSAxel Dörfler 734910ffb32SAxel Dörfler InterfaceAddress* address = NULL; 735910ffb32SAxel Dörfler if (aliasRequest.ifra_index < 0) { 736910ffb32SAxel Dörfler if (!domain->address_module->is_empty_address( 737910ffb32SAxel Dörfler (const sockaddr*)&aliasRequest.ifra_addr, false)) { 738910ffb32SAxel Dörfler // Find first address that matches the local address 739910ffb32SAxel Dörfler address = AddressForLocal(domain, 740910ffb32SAxel Dörfler (const sockaddr*)&aliasRequest.ifra_addr); 741910ffb32SAxel Dörfler } 742910ffb32SAxel Dörfler if (address == NULL) { 743910ffb32SAxel Dörfler // Find first address for family 744910ffb32SAxel Dörfler address = FirstForFamily(domain->family); 745910ffb32SAxel Dörfler } 746a271028eSAxel Dörfler if (address == NULL) { 747a271028eSAxel Dörfler // Create new on the fly 748a271028eSAxel Dörfler address = new(std::nothrow) InterfaceAddress(this, domain); 749a271028eSAxel Dörfler if (address == NULL) 750a271028eSAxel Dörfler return B_NO_MEMORY; 751a271028eSAxel Dörfler 752a271028eSAxel Dörfler status_t status = AddAddress(address); 753095f97a6SAxel Dörfler if (status != B_OK) { 754095f97a6SAxel Dörfler delete address; 755a271028eSAxel Dörfler return status; 756095f97a6SAxel Dörfler } 757a271028eSAxel Dörfler 758a271028eSAxel Dörfler // Note, even if setting the address failed, the empty 759a271028eSAxel Dörfler // address added here will still be added to the interface. 760*8dcde8b1SAxel Dörfler address->AcquireReference(); 761a271028eSAxel Dörfler } 762910ffb32SAxel Dörfler } else 763910ffb32SAxel Dörfler address = AddressAt(aliasRequest.ifra_index); 764910ffb32SAxel Dörfler 7659d771afbSAxel Dörfler if (address == NULL) 7669d771afbSAxel Dörfler return B_BAD_VALUE; 7679d771afbSAxel Dörfler 7689d771afbSAxel Dörfler status_t status = B_OK; 7699d771afbSAxel Dörfler 7709d771afbSAxel Dörfler if (!domain->address_module->equal_addresses( 7719d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_addr, address->local)) { 7729d771afbSAxel Dörfler status = _ChangeAddress(locker, address, SIOCSIFADDR, 7739d771afbSAxel Dörfler address->local, (sockaddr*)&aliasRequest.ifra_addr); 7749d771afbSAxel Dörfler } 7759d771afbSAxel Dörfler 7769d771afbSAxel Dörfler if (status == B_OK && !domain->address_module->equal_addresses( 777910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_mask, address->mask) 778910ffb32SAxel Dörfler && !domain->address_module->is_empty_address( 779910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_mask, false)) { 7809d771afbSAxel Dörfler status = _ChangeAddress(locker, address, SIOCSIFNETMASK, 7819d771afbSAxel Dörfler address->mask, (sockaddr*)&aliasRequest.ifra_mask); 7829d771afbSAxel Dörfler } 7839d771afbSAxel Dörfler 7849d771afbSAxel Dörfler if (status == B_OK && !domain->address_module->equal_addresses( 7859d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination, 786910ffb32SAxel Dörfler address->destination) 787910ffb32SAxel Dörfler && !domain->address_module->is_empty_address( 788910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination, false)) { 7899d771afbSAxel Dörfler status = _ChangeAddress(locker, address, 7909d771afbSAxel Dörfler (domain->address_module->flags 7919d771afbSAxel Dörfler & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0 7929d771afbSAxel Dörfler ? SIOCSIFBRDADDR : SIOCSIFDSTADDR, 7939d771afbSAxel Dörfler address->destination, 7949d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination); 7959d771afbSAxel Dörfler } 7969d771afbSAxel Dörfler 7979d771afbSAxel Dörfler address->ReleaseReference(); 7989d771afbSAxel Dörfler return status; 7999d771afbSAxel Dörfler } 8009d771afbSAxel Dörfler 80161729d93SAxel Dörfler case SIOCSIFADDR: 80261729d93SAxel Dörfler case SIOCSIFNETMASK: 80361729d93SAxel Dörfler case SIOCSIFBRDADDR: 80461729d93SAxel Dörfler case SIOCSIFDSTADDR: 80561729d93SAxel Dörfler case SIOCDIFADDR: 80661729d93SAxel Dörfler { 807e8802e49SAxel Dörfler if (length != sizeof(ifreq)) 808e8802e49SAxel Dörfler return B_BAD_VALUE; 809e8802e49SAxel Dörfler 81061729d93SAxel Dörfler RecursiveLocker locker(fLock); 81161729d93SAxel Dörfler 81261729d93SAxel Dörfler InterfaceAddress* address = NULL; 81361729d93SAxel Dörfler sockaddr_storage newAddress; 81461729d93SAxel Dörfler 81561729d93SAxel Dörfler size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr)); 81661729d93SAxel Dörfler if (size > sizeof(sockaddr_storage)) 81761729d93SAxel Dörfler size = sizeof(sockaddr_storage); 81861729d93SAxel Dörfler 81961729d93SAxel Dörfler if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK) 82061729d93SAxel Dörfler return B_BAD_ADDRESS; 82161729d93SAxel Dörfler 82261729d93SAxel Dörfler if (option == SIOCDIFADDR) { 82361729d93SAxel Dörfler // Find referring address - we can't use the hash, as another 82461729d93SAxel Dörfler // interface might use the same address. 82561729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 82661729d93SAxel Dörfler while ((address = iterator.Next()) != NULL) { 82761729d93SAxel Dörfler if (address->domain == domain 82861729d93SAxel Dörfler && domain->address_module->equal_addresses( 82961729d93SAxel Dörfler address->local, (sockaddr*)&newAddress)) 83061729d93SAxel Dörfler break; 83161729d93SAxel Dörfler } 83261729d93SAxel Dörfler 83361729d93SAxel Dörfler if (address == NULL) 83461729d93SAxel Dörfler return B_BAD_VALUE; 83578abd727SAxel Dörfler } else { 83678abd727SAxel Dörfler // Just use the first address for this family 83778abd727SAxel Dörfler address = _FirstForFamily(domain->family); 83878abd727SAxel Dörfler if (address == NULL) { 83978abd727SAxel Dörfler // Create new on the fly 84078abd727SAxel Dörfler address = new(std::nothrow) InterfaceAddress(this, domain); 84178abd727SAxel Dörfler if (address == NULL) 84278abd727SAxel Dörfler return B_NO_MEMORY; 84378abd727SAxel Dörfler 84478abd727SAxel Dörfler status_t status = AddAddress(address); 845095f97a6SAxel Dörfler if (status != B_OK) { 846095f97a6SAxel Dörfler delete address; 84778abd727SAxel Dörfler return status; 848095f97a6SAxel Dörfler } 84978abd727SAxel Dörfler 85078abd727SAxel Dörfler // Note, even if setting the address failed, the empty 85178abd727SAxel Dörfler // address added here will still be added to the interface. 85278abd727SAxel Dörfler } 85378abd727SAxel Dörfler } 85461729d93SAxel Dörfler 8559d771afbSAxel Dörfler return _ChangeAddress(locker, address, option, 8569d771afbSAxel Dörfler *address->AddressFor(option), 85761729d93SAxel Dörfler option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL); 85861729d93SAxel Dörfler } 85961729d93SAxel Dörfler 86061729d93SAxel Dörfler default: 86161729d93SAxel Dörfler // pass the request into the datalink protocol stack 86261729d93SAxel Dörfler domain_datalink* datalink = DomainDatalink(domain->family); 86361729d93SAxel Dörfler if (datalink->first_info != NULL) { 86461729d93SAxel Dörfler return datalink->first_info->control( 86561729d93SAxel Dörfler datalink->first_protocol, option, userRequest, length); 86661729d93SAxel Dörfler } 86761729d93SAxel Dörfler break; 86861729d93SAxel Dörfler } 86961729d93SAxel Dörfler 87061729d93SAxel Dörfler return B_BAD_VALUE; 87161729d93SAxel Dörfler } 87261729d93SAxel Dörfler 87361729d93SAxel Dörfler 8742b1c0755SAxel Dörfler void 8752b1c0755SAxel Dörfler Interface::SetDown() 8762b1c0755SAxel Dörfler { 8772b1c0755SAxel Dörfler if ((flags & IFF_UP) == 0) 8782b1c0755SAxel Dörfler return; 8792b1c0755SAxel Dörfler 8802b1c0755SAxel Dörfler RecursiveLocker locker(fLock); 8812b1c0755SAxel Dörfler 8822b1c0755SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 8832b1c0755SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) { 8842b1c0755SAxel Dörfler datalink->first_info->interface_down(datalink->first_protocol); 8852b1c0755SAxel Dörfler } 8862b1c0755SAxel Dörfler 8872b1c0755SAxel Dörfler flags &= ~IFF_UP; 8882b1c0755SAxel Dörfler } 8892b1c0755SAxel Dörfler 8902b1c0755SAxel Dörfler 8912b1c0755SAxel Dörfler /*! Called when a device lost its IFF_UP status. We will invalidate all 8922b1c0755SAxel Dörfler interface routes here. 8932b1c0755SAxel Dörfler */ 8942b1c0755SAxel Dörfler void 8952b1c0755SAxel Dörfler Interface::WentDown() 8962b1c0755SAxel Dörfler { 8972b1c0755SAxel Dörfler RecursiveLocker locker(fLock); 8982b1c0755SAxel Dörfler 8992b1c0755SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 9002b1c0755SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 9012b1c0755SAxel Dörfler if (address->domain != NULL) 9022b1c0755SAxel Dörfler invalidate_routes(address->domain, this); 9032b1c0755SAxel Dörfler } 9042b1c0755SAxel Dörfler } 9052b1c0755SAxel Dörfler 9062b1c0755SAxel Dörfler 90761729d93SAxel Dörfler status_t 90861729d93SAxel Dörfler Interface::CreateDomainDatalinkIfNeeded(net_domain* domain) 90961729d93SAxel Dörfler { 91061729d93SAxel Dörfler RecursiveLocker locker(fLock); 91161729d93SAxel Dörfler 91261729d93SAxel Dörfler if (fDatalinkTable.Lookup(domain->family) != NULL) 91361729d93SAxel Dörfler return B_OK; 91461729d93SAxel Dörfler 91561729d93SAxel Dörfler TRACE("Interface %p: create domain datalink for domain %p\n", this, domain); 91661729d93SAxel Dörfler 91761729d93SAxel Dörfler domain_datalink* datalink = new(std::nothrow) domain_datalink; 91861729d93SAxel Dörfler if (datalink == NULL) 91961729d93SAxel Dörfler return B_NO_MEMORY; 92061729d93SAxel Dörfler 92161729d93SAxel Dörfler datalink->domain = domain; 92261729d93SAxel Dörfler 92361729d93SAxel Dörfler // setup direct route for bound devices 92461729d93SAxel Dörfler datalink->direct_route.destination = NULL; 92561729d93SAxel Dörfler datalink->direct_route.mask = NULL; 92661729d93SAxel Dörfler datalink->direct_route.gateway = NULL; 92761729d93SAxel Dörfler datalink->direct_route.flags = 0; 92861729d93SAxel Dörfler datalink->direct_route.mtu = 0; 92961729d93SAxel Dörfler datalink->direct_route.interface_address = &datalink->direct_address; 93061729d93SAxel Dörfler datalink->direct_route.ref_count = 1; 93161729d93SAxel Dörfler // make sure this doesn't get deleted accidently 93261729d93SAxel Dörfler 93361729d93SAxel Dörfler // provide its link back to the interface 93461729d93SAxel Dörfler datalink->direct_address.local = NULL; 93561729d93SAxel Dörfler datalink->direct_address.destination = NULL; 93661729d93SAxel Dörfler datalink->direct_address.mask = NULL; 93761729d93SAxel Dörfler datalink->direct_address.domain = domain; 93861729d93SAxel Dörfler datalink->direct_address.interface = this; 9392b1c0755SAxel Dörfler datalink->direct_address.flags = IFAF_DIRECT_ADDRESS; 94061729d93SAxel Dörfler 94161729d93SAxel Dörfler fDatalinkTable.Insert(datalink); 94261729d93SAxel Dörfler 94361729d93SAxel Dörfler status_t status = get_domain_datalink_protocols(this, domain); 94461729d93SAxel Dörfler if (status == B_OK) 94561729d93SAxel Dörfler return B_OK; 94661729d93SAxel Dörfler 94761729d93SAxel Dörfler fDatalinkTable.Remove(datalink); 94861729d93SAxel Dörfler delete datalink; 94961729d93SAxel Dörfler 95061729d93SAxel Dörfler return status; 95161729d93SAxel Dörfler } 95261729d93SAxel Dörfler 95361729d93SAxel Dörfler 95461729d93SAxel Dörfler domain_datalink* 95561729d93SAxel Dörfler Interface::DomainDatalink(uint8 family) 95661729d93SAxel Dörfler { 95761729d93SAxel Dörfler // Note: domain datalinks cannot be removed while the interface is alive, 95861729d93SAxel Dörfler // since this would require us either to hold the lock while calling this 95961729d93SAxel Dörfler // function, or introduce reference counting for the domain_datalink 96061729d93SAxel Dörfler // structure. 96161729d93SAxel Dörfler RecursiveLocker locker(fLock); 96261729d93SAxel Dörfler return fDatalinkTable.Lookup(family); 96361729d93SAxel Dörfler } 96461729d93SAxel Dörfler 96561729d93SAxel Dörfler 96661729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 96761729d93SAxel Dörfler 96861729d93SAxel Dörfler 96961729d93SAxel Dörfler void 97061729d93SAxel Dörfler Interface::Dump() const 97161729d93SAxel Dörfler { 97261729d93SAxel Dörfler kprintf("name: %s\n", name); 97361729d93SAxel Dörfler kprintf("device: %p\n", device); 97461729d93SAxel Dörfler kprintf("device_interface: %p\n", fDeviceInterface); 97561729d93SAxel Dörfler kprintf("index: %" B_PRIu32 "\n", index); 97661729d93SAxel Dörfler kprintf("flags: %#" B_PRIx32 "\n", flags); 97761729d93SAxel Dörfler kprintf("type: %u\n", type); 97861729d93SAxel Dörfler kprintf("mtu: %" B_PRIu32 "\n", mtu); 97961729d93SAxel Dörfler kprintf("metric: %" B_PRIu32 "\n", metric); 98061729d93SAxel Dörfler 98161729d93SAxel Dörfler kprintf("datalink protocols:\n"); 98261729d93SAxel Dörfler 98361729d93SAxel Dörfler DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator(); 98461729d93SAxel Dörfler size_t i = 0; 98561729d93SAxel Dörfler while (domain_datalink* datalink = datalinkIterator.Next()) { 98661729d93SAxel Dörfler kprintf("%2zu. domain: %p\n", ++i, datalink->domain); 98761729d93SAxel Dörfler kprintf(" first_protocol: %p\n", datalink->first_protocol); 98861729d93SAxel Dörfler kprintf(" first_info: %p\n", datalink->first_info); 98961729d93SAxel Dörfler kprintf(" direct_route: %p\n", &datalink->direct_route); 99061729d93SAxel Dörfler } 99161729d93SAxel Dörfler 99261729d93SAxel Dörfler kprintf("addresses:\n"); 99361729d93SAxel Dörfler 99461729d93SAxel Dörfler AddressList::ConstIterator iterator = fAddresses.GetIterator(); 99561729d93SAxel Dörfler i = 0; 99661729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 99761729d93SAxel Dörfler address->Dump(++i, true); 99861729d93SAxel Dörfler } 99961729d93SAxel Dörfler } 100061729d93SAxel Dörfler 100161729d93SAxel Dörfler 100261729d93SAxel Dörfler #endif // ENABLE_DEBUGGER_COMMANDS 100361729d93SAxel Dörfler 100461729d93SAxel Dörfler 100561729d93SAxel Dörfler status_t 100661729d93SAxel Dörfler Interface::_SetUp() 100761729d93SAxel Dörfler { 100861729d93SAxel Dörfler status_t status = up_device_interface(fDeviceInterface); 100961729d93SAxel Dörfler if (status != B_OK) 101061729d93SAxel Dörfler return status; 101161729d93SAxel Dörfler 10122b1c0755SAxel Dörfler // Propagate flag to all datalink protocols 101361729d93SAxel Dörfler 101461729d93SAxel Dörfler RecursiveLocker locker(fLock); 101561729d93SAxel Dörfler 101661729d93SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 101761729d93SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) { 101861729d93SAxel Dörfler status = datalink->first_info->interface_up(datalink->first_protocol); 101961729d93SAxel Dörfler if (status != B_OK) { 102061729d93SAxel Dörfler // Revert "up" status 102161729d93SAxel Dörfler DatalinkTable::Iterator secondIterator 102261729d93SAxel Dörfler = fDatalinkTable.GetIterator(); 102361729d93SAxel Dörfler while (secondIterator.HasNext()) { 102461729d93SAxel Dörfler domain_datalink* secondDatalink = secondIterator.Next(); 102561729d93SAxel Dörfler if (secondDatalink == NULL || secondDatalink == datalink) 1026c22d69bfSAxel Dörfler break; 1027c22d69bfSAxel Dörfler 102861729d93SAxel Dörfler secondDatalink->first_info->interface_down( 102961729d93SAxel Dörfler secondDatalink->first_protocol); 103061729d93SAxel Dörfler } 103161729d93SAxel Dörfler 103261729d93SAxel Dörfler down_device_interface(fDeviceInterface); 103361729d93SAxel Dörfler return status; 103461729d93SAxel Dörfler } 103561729d93SAxel Dörfler } 103661729d93SAxel Dörfler 10372b1c0755SAxel Dörfler // Add default routes for the existing addresses 10382b1c0755SAxel Dörfler 10392b1c0755SAxel Dörfler AddressList::Iterator addressIterator = fAddresses.GetIterator(); 10402b1c0755SAxel Dörfler while (InterfaceAddress* address = addressIterator.Next()) { 10412b1c0755SAxel Dörfler address->AddDefaultRoutes(SIOCSIFADDR); 10422b1c0755SAxel Dörfler } 10432b1c0755SAxel Dörfler 104461729d93SAxel Dörfler flags |= IFF_UP; 104561729d93SAxel Dörfler return B_OK; 104661729d93SAxel Dörfler } 104761729d93SAxel Dörfler 104861729d93SAxel Dörfler 104961729d93SAxel Dörfler InterfaceAddress* 105061729d93SAxel Dörfler Interface::_FirstForFamily(int family) 105161729d93SAxel Dörfler { 105261729d93SAxel Dörfler ASSERT_LOCKED_RECURSIVE(&fLock); 105361729d93SAxel Dörfler 105461729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 105561729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 105661729d93SAxel Dörfler if (address->domain != NULL && address->domain->family == family) 105761729d93SAxel Dörfler return address; 105861729d93SAxel Dörfler } 105961729d93SAxel Dörfler 106061729d93SAxel Dörfler return NULL; 106161729d93SAxel Dörfler } 106261729d93SAxel Dörfler 106361729d93SAxel Dörfler 10649d771afbSAxel Dörfler status_t 10659d771afbSAxel Dörfler Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address, 1066b0cf274aSAxel Dörfler int32 option, const sockaddr* originalAddress, 1067b0cf274aSAxel Dörfler const sockaddr* requestedAddress) 10689d771afbSAxel Dörfler { 1069b0cf274aSAxel Dörfler // Copy old address 10709d771afbSAxel Dörfler sockaddr_storage oldAddress; 10719d771afbSAxel Dörfler if (address->domain->address_module->set_to((sockaddr*)&oldAddress, 10729d771afbSAxel Dörfler originalAddress) != B_OK) 10739d771afbSAxel Dörfler oldAddress.ss_family = AF_UNSPEC; 10749d771afbSAxel Dörfler 1075b0cf274aSAxel Dörfler // Copy new address (this also makes sure that sockaddr::sa_len is set 1076b0cf274aSAxel Dörfler // correctly) 1077b0cf274aSAxel Dörfler sockaddr_storage newAddress; 1078b0cf274aSAxel Dörfler if (address->domain->address_module->set_to((sockaddr*)&newAddress, 1079b0cf274aSAxel Dörfler requestedAddress) != B_OK) 1080b0cf274aSAxel Dörfler newAddress.ss_family = AF_UNSPEC; 1081b0cf274aSAxel Dörfler 10826b1e1488SAxel Dörfler // Test if anything changed for real 1083b0cf274aSAxel Dörfler if (address->domain->address_module->equal_addresses( 1084b0cf274aSAxel Dörfler (sockaddr*)&oldAddress, (sockaddr*)&newAddress)) { 10856b1e1488SAxel Dörfler // Nothing to do 1086b0cf274aSAxel Dörfler TRACE(" option %" B_PRId32 " addresses are equal!\n", option); 10876b1e1488SAxel Dörfler return B_OK; 10886b1e1488SAxel Dörfler } 10896b1e1488SAxel Dörfler 10909d771afbSAxel Dörfler // TODO: mark this address busy or call while holding the lock! 10919d771afbSAxel Dörfler address->AcquireReference(); 10929d771afbSAxel Dörfler locker.Unlock(); 10939d771afbSAxel Dörfler 10949d771afbSAxel Dörfler domain_datalink* datalink = DomainDatalink(address->domain); 10959d771afbSAxel Dörfler status_t status = datalink->first_protocol->module->change_address( 10969d771afbSAxel Dörfler datalink->first_protocol, address, option, 10979d771afbSAxel Dörfler oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL, 1098b0cf274aSAxel Dörfler newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL); 10999d771afbSAxel Dörfler 11009d771afbSAxel Dörfler locker.Lock(); 11019d771afbSAxel Dörfler address->ReleaseReference(); 11029d771afbSAxel Dörfler return status; 11039d771afbSAxel Dörfler } 11049d771afbSAxel Dörfler 11059d771afbSAxel Dörfler 110661729d93SAxel Dörfler // #pragma mark - 110761729d93SAxel Dörfler 110861729d93SAxel Dörfler 110961729d93SAxel Dörfler /*! Searches for a specific interface by name. 111061729d93SAxel Dörfler You need to have the interface list's lock hold when calling this function. 111161729d93SAxel Dörfler */ 111261729d93SAxel Dörfler static struct Interface* 111361729d93SAxel Dörfler find_interface(const char* name) 111461729d93SAxel Dörfler { 111561729d93SAxel Dörfler ASSERT_LOCKED_MUTEX(&sLock); 111661729d93SAxel Dörfler 111761729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 111861729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1119c22d69bfSAxel Dörfler if (!strcmp(interface->name, name)) 1120c22d69bfSAxel Dörfler return interface; 1121c22d69bfSAxel Dörfler } 1122c22d69bfSAxel Dörfler 1123c22d69bfSAxel Dörfler return NULL; 1124c22d69bfSAxel Dörfler } 1125c22d69bfSAxel Dörfler 1126c22d69bfSAxel Dörfler 112761729d93SAxel Dörfler /*! Searches for a specific interface by index. 112861729d93SAxel Dörfler You need to have the interface list's lock hold when calling this function. 1129c22d69bfSAxel Dörfler */ 113061729d93SAxel Dörfler static struct Interface* 113161729d93SAxel Dörfler find_interface(uint32 index) 1132c22d69bfSAxel Dörfler { 113361729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 113461729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1135c22d69bfSAxel Dörfler if (interface->index == index) 1136c22d69bfSAxel Dörfler return interface; 1137c22d69bfSAxel Dörfler } 1138c22d69bfSAxel Dörfler 1139c22d69bfSAxel Dörfler return NULL; 1140c22d69bfSAxel Dörfler } 1141c22d69bfSAxel Dörfler 1142c22d69bfSAxel Dörfler 114361729d93SAxel Dörfler // #pragma mark - 114461729d93SAxel Dörfler 114561729d93SAxel Dörfler 114661729d93SAxel Dörfler status_t 114761729d93SAxel Dörfler add_interface(const char* name, net_domain_private* domain, 114861729d93SAxel Dörfler const ifaliasreq& request, net_device_interface* deviceInterface) 114961729d93SAxel Dörfler { 115061729d93SAxel Dörfler MutexLocker locker(sLock); 115161729d93SAxel Dörfler 115261729d93SAxel Dörfler if (find_interface(name) != NULL) 115361729d93SAxel Dörfler return B_NAME_IN_USE; 115461729d93SAxel Dörfler 115561729d93SAxel Dörfler Interface* interface 115661729d93SAxel Dörfler = new(std::nothrow) Interface(name, deviceInterface); 1157c22d69bfSAxel Dörfler if (interface == NULL) 1158c22d69bfSAxel Dörfler return B_NO_MEMORY; 1159c22d69bfSAxel Dörfler 116061729d93SAxel Dörfler sInterfaces.Add(interface); 116161729d93SAxel Dörfler interface->AcquireReference(); 116261729d93SAxel Dörfler // We need another reference to be able to use the interface without 116361729d93SAxel Dörfler // holding sLock. 1164c22d69bfSAxel Dörfler 116561729d93SAxel Dörfler locker.Unlock(); 1166c22d69bfSAxel Dörfler 116761729d93SAxel Dörfler notify_interface_added(interface); 116861729d93SAxel Dörfler add_interface_address(interface, domain, request); 1169c22d69bfSAxel Dörfler 117061729d93SAxel Dörfler interface->ReleaseReference(); 117127e0dea9SAxel Dörfler 1172c22d69bfSAxel Dörfler return B_OK; 1173c22d69bfSAxel Dörfler } 1174c22d69bfSAxel Dörfler 1175c22d69bfSAxel Dörfler 117661729d93SAxel Dörfler /*! Removes the interface from the list, and puts the stack's reference to it. 117761729d93SAxel Dörfler */ 11787aa2819cSAxel Dörfler void 117961729d93SAxel Dörfler remove_interface(Interface* interface) 1180c64feccaSHugo Santos { 11812b1c0755SAxel Dörfler interface->SetDown(); 11822b1c0755SAxel Dörfler interface->RemoveAddresses(); 1183c64feccaSHugo Santos 11842b1c0755SAxel Dörfler MutexLocker locker(sLock); 11852b1c0755SAxel Dörfler sInterfaces.Remove(interface); 11862b1c0755SAxel Dörfler locker.Unlock(); 1187f6d219a1SAxel Dörfler 118861729d93SAxel Dörfler notify_interface_removed(interface); 1189c22d69bfSAxel Dörfler 11902b1c0755SAxel Dörfler interface->ReleaseReference(); 11917aa2819cSAxel Dörfler } 11927aa2819cSAxel Dörfler 11937aa2819cSAxel Dörfler 11947aa2819cSAxel Dörfler /*! This is called whenever a device interface is being removed. We will get 11957aa2819cSAxel Dörfler the corresponding Interface, and remove it. 11967aa2819cSAxel Dörfler */ 11977aa2819cSAxel Dörfler void 11987aa2819cSAxel Dörfler interface_removed_device_interface(net_device_interface* deviceInterface) 11997aa2819cSAxel Dörfler { 12007aa2819cSAxel Dörfler MutexLocker locker(sLock); 12017aa2819cSAxel Dörfler 12027aa2819cSAxel Dörfler Interface* interface = find_interface(deviceInterface->device->name); 12037aa2819cSAxel Dörfler if (interface != NULL) 12047aa2819cSAxel Dörfler remove_interface(interface); 1205c22d69bfSAxel Dörfler } 1206c22d69bfSAxel Dörfler 1207c22d69bfSAxel Dörfler 120861729d93SAxel Dörfler status_t 120961729d93SAxel Dörfler add_interface_address(Interface* interface, net_domain_private* domain, 121061729d93SAxel Dörfler const ifaliasreq& request) 1211c22d69bfSAxel Dörfler { 121261729d93SAxel Dörfler // Make sure the family of the provided addresses is valid 121361729d93SAxel Dörfler if ((request.ifra_addr.ss_family != domain->family 121461729d93SAxel Dörfler && request.ifra_addr.ss_family != AF_UNSPEC) 121561729d93SAxel Dörfler || (request.ifra_mask.ss_family != domain->family 121661729d93SAxel Dörfler && request.ifra_mask.ss_family != AF_UNSPEC) 121761729d93SAxel Dörfler || (request.ifra_broadaddr.ss_family != domain->family 121861729d93SAxel Dörfler && request.ifra_broadaddr.ss_family != AF_UNSPEC)) 121961729d93SAxel Dörfler return B_BAD_VALUE; 1220c22d69bfSAxel Dörfler 122161729d93SAxel Dörfler RecursiveLocker locker(interface->Lock()); 122261729d93SAxel Dörfler 122361729d93SAxel Dörfler InterfaceAddress* address 122461729d93SAxel Dörfler = new(std::nothrow) InterfaceAddress(interface, domain); 122561729d93SAxel Dörfler if (address == NULL) 122661729d93SAxel Dörfler return B_NO_MEMORY; 122761729d93SAxel Dörfler 122861729d93SAxel Dörfler status_t status = address->SetTo(request); 122961729d93SAxel Dörfler if (status == B_OK) 123061729d93SAxel Dörfler status = interface->CreateDomainDatalinkIfNeeded(domain); 123161729d93SAxel Dörfler if (status == B_OK) 123261729d93SAxel Dörfler status = interface->AddAddress(address); 123361729d93SAxel Dörfler 123461729d93SAxel Dörfler if (status == B_OK && address->local != NULL) { 123561729d93SAxel Dörfler // update the datalink protocols 123661729d93SAxel Dörfler domain_datalink* datalink = interface->DomainDatalink(domain->family); 123761729d93SAxel Dörfler 123861729d93SAxel Dörfler status = datalink->first_protocol->module->change_address( 123961729d93SAxel Dörfler datalink->first_protocol, address, SIOCAIFADDR, NULL, 124061729d93SAxel Dörfler address->local); 124161729d93SAxel Dörfler if (status != B_OK) 124261729d93SAxel Dörfler interface->RemoveAddress(address); 124361729d93SAxel Dörfler } 124461729d93SAxel Dörfler if (status == B_OK) 124561729d93SAxel Dörfler notify_interface_changed(interface); 124661729d93SAxel Dörfler else 124761729d93SAxel Dörfler delete address; 124861729d93SAxel Dörfler 124961729d93SAxel Dörfler return status; 125061729d93SAxel Dörfler } 125161729d93SAxel Dörfler 125261729d93SAxel Dörfler 125361729d93SAxel Dörfler status_t 125461729d93SAxel Dörfler update_interface_address(InterfaceAddress* interfaceAddress, int32 option, 125561729d93SAxel Dörfler const sockaddr* oldAddress, const sockaddr* newAddress) 125661729d93SAxel Dörfler { 1257b0cf274aSAxel Dörfler TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress " 1258b0cf274aSAxel Dörfler "%s)\n", __FUNCTION__, interfaceAddress, option, 1259b0cf274aSAxel Dörfler AddressString(interfaceAddress->domain, oldAddress).Data(), 1260b0cf274aSAxel Dörfler AddressString(interfaceAddress->domain, newAddress).Data()); 1261b0cf274aSAxel Dörfler 126261729d93SAxel Dörfler MutexLocker locker(sHashLock); 126361729d93SAxel Dörfler 126461729d93SAxel Dörfler // set logical interface address 126561729d93SAxel Dörfler sockaddr** _address = interfaceAddress->AddressFor(option); 126661729d93SAxel Dörfler if (_address == NULL) 126761729d93SAxel Dörfler return B_BAD_VALUE; 126861729d93SAxel Dörfler 12692b1c0755SAxel Dörfler Interface* interface = (Interface*)interfaceAddress->interface; 12702b1c0755SAxel Dörfler 12712b1c0755SAxel Dörfler interfaceAddress->RemoveDefaultRoutes(option); 12722b1c0755SAxel Dörfler 12732b1c0755SAxel Dörfler if (option == SIOCDIFADDR) { 12742b1c0755SAxel Dörfler // Remove address, and release its reference (causing our caller to 12752b1c0755SAxel Dörfler // delete it) 12762b1c0755SAxel Dörfler locker.Unlock(); 12772b1c0755SAxel Dörfler 12782b1c0755SAxel Dörfler invalidate_routes(interfaceAddress); 12792b1c0755SAxel Dörfler 12802b1c0755SAxel Dörfler interface->RemoveAddress(interfaceAddress); 12812b1c0755SAxel Dörfler interfaceAddress->ReleaseReference(); 12822b1c0755SAxel Dörfler return B_OK; 12832b1c0755SAxel Dörfler } 12842b1c0755SAxel Dörfler 128561729d93SAxel Dörfler sAddressTable.Remove(interfaceAddress); 128661729d93SAxel Dörfler 128761729d93SAxel Dörfler // Copy new address over 128861729d93SAxel Dörfler status_t status = InterfaceAddress::Set(_address, newAddress); 128961729d93SAxel Dörfler if (status == B_OK) { 129061729d93SAxel Dörfler sockaddr* address = *_address; 129161729d93SAxel Dörfler 12921ebd87f4SAxel Dörfler if (option == SIOCSIFADDR) { 129361729d93SAxel Dörfler // Reset netmask and broadcast addresses to defaults 129461729d93SAxel Dörfler net_domain* domain = interfaceAddress->domain; 129561729d93SAxel Dörfler sockaddr* netmask = NULL; 129661729d93SAxel Dörfler const sockaddr* oldNetmask = NULL; 129761729d93SAxel Dörfler if (option == SIOCSIFADDR) { 129861729d93SAxel Dörfler netmask = InterfaceAddress::Prepare( 129961729d93SAxel Dörfler &interfaceAddress->mask, address->sa_len); 130061729d93SAxel Dörfler } else { 130161729d93SAxel Dörfler oldNetmask = oldAddress; 130261729d93SAxel Dörfler netmask = interfaceAddress->mask; 130361729d93SAxel Dörfler } 130461729d93SAxel Dörfler 130561729d93SAxel Dörfler // Reset the broadcast address if the address family has 130661729d93SAxel Dörfler // such 130761729d93SAxel Dörfler sockaddr* broadcast = NULL; 130861729d93SAxel Dörfler if ((domain->address_module->flags 130961729d93SAxel Dörfler & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) { 131061729d93SAxel Dörfler broadcast = InterfaceAddress::Prepare( 131161729d93SAxel Dörfler &interfaceAddress->destination, address->sa_len); 131261729d93SAxel Dörfler } else 131361729d93SAxel Dörfler InterfaceAddress::Set(&interfaceAddress->destination, NULL); 131461729d93SAxel Dörfler 131561729d93SAxel Dörfler domain->address_module->set_to_defaults(netmask, broadcast, 131661729d93SAxel Dörfler interfaceAddress->local, oldNetmask); 131761729d93SAxel Dörfler } 131861729d93SAxel Dörfler 13192b1c0755SAxel Dörfler interfaceAddress->AddDefaultRoutes(option); 13202b1c0755SAxel Dörfler notify_interface_changed(interface); 132161729d93SAxel Dörfler } 132261729d93SAxel Dörfler 132361729d93SAxel Dörfler sAddressTable.Insert(interfaceAddress); 132461729d93SAxel Dörfler return status; 132561729d93SAxel Dörfler } 132661729d93SAxel Dörfler 132761729d93SAxel Dörfler 132861729d93SAxel Dörfler Interface* 132961729d93SAxel Dörfler get_interface(net_domain* domain, uint32 index) 133061729d93SAxel Dörfler { 133161729d93SAxel Dörfler MutexLocker locker(sLock); 133261729d93SAxel Dörfler 133361729d93SAxel Dörfler if (index == 0) 133461729d93SAxel Dörfler return sInterfaces.First(); 133561729d93SAxel Dörfler 133661729d93SAxel Dörfler Interface* interface = find_interface(index); 1337c22d69bfSAxel Dörfler if (interface == NULL) 133861729d93SAxel Dörfler return NULL; 1339c22d69bfSAxel Dörfler 134061729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 134161729d93SAxel Dörfler return NULL; 134261729d93SAxel Dörfler 134361729d93SAxel Dörfler interface->AcquireReference(); 1344c22d69bfSAxel Dörfler return interface; 1345c22d69bfSAxel Dörfler } 1346c22d69bfSAxel Dörfler 134761729d93SAxel Dörfler 134861729d93SAxel Dörfler Interface* 134961729d93SAxel Dörfler get_interface(net_domain* domain, const char* name) 135061729d93SAxel Dörfler { 135161729d93SAxel Dörfler MutexLocker locker(sLock); 135261729d93SAxel Dörfler 135361729d93SAxel Dörfler Interface* interface = find_interface(name); 135461729d93SAxel Dörfler if (interface == NULL) 135561729d93SAxel Dörfler return NULL; 135661729d93SAxel Dörfler 135761729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 135861729d93SAxel Dörfler return NULL; 135961729d93SAxel Dörfler 136061729d93SAxel Dörfler interface->AcquireReference(); 136161729d93SAxel Dörfler return interface; 136261729d93SAxel Dörfler } 136361729d93SAxel Dörfler 136461729d93SAxel Dörfler 136561729d93SAxel Dörfler Interface* 136661729d93SAxel Dörfler get_interface_for_device(net_domain* domain, uint32 index) 136761729d93SAxel Dörfler { 136861729d93SAxel Dörfler MutexLocker locker(sLock); 136961729d93SAxel Dörfler 137061729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 137161729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 137261729d93SAxel Dörfler if (interface->device->index == index) { 137361729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 137461729d93SAxel Dörfler return NULL; 137561729d93SAxel Dörfler 137661729d93SAxel Dörfler interface->AcquireReference(); 137761729d93SAxel Dörfler return interface; 137861729d93SAxel Dörfler } 137961729d93SAxel Dörfler } 138061729d93SAxel Dörfler 1381c22d69bfSAxel Dörfler return NULL; 1382c22d69bfSAxel Dörfler } 1383c22d69bfSAxel Dörfler 1384c22d69bfSAxel Dörfler 1385cd08b9f7SAxel Dörfler /*! Returns a reference to an Interface that matches the given \a linkAddress. 1386cd08b9f7SAxel Dörfler The link address is checked against its hardware address, or its interface 1387cd08b9f7SAxel Dörfler name, or finally the interface index. 1388cd08b9f7SAxel Dörfler */ 1389cd08b9f7SAxel Dörfler Interface* 1390cd08b9f7SAxel Dörfler get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) 1391cd08b9f7SAxel Dörfler { 1392cd08b9f7SAxel Dörfler sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress; 1393cd08b9f7SAxel Dörfler 1394cd08b9f7SAxel Dörfler MutexLocker locker(sLock); 1395cd08b9f7SAxel Dörfler 1396cd08b9f7SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1397cd08b9f7SAxel Dörfler while (Interface* interface = iterator.Next()) { 1398cd08b9f7SAxel Dörfler // Test if the hardware address matches, or if the given interface 1399cd08b9f7SAxel Dörfler // matches, or if at least the index matches. 1400cd08b9f7SAxel Dörfler if ((linkAddress.sdl_alen == interface->device->address.length 1401cd08b9f7SAxel Dörfler && memcmp(LLADDR(&linkAddress), interface->device->address.data, 1402cd08b9f7SAxel Dörfler linkAddress.sdl_alen) == 0) 1403cd08b9f7SAxel Dörfler || (linkAddress.sdl_nlen > 0 1404cd08b9f7SAxel Dörfler && !strcmp(interface->name, (const char*)linkAddress.sdl_data)) 1405cd08b9f7SAxel Dörfler || (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0 1406cd08b9f7SAxel Dörfler && linkAddress.sdl_index == interface->index)) { 1407cd08b9f7SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1408cd08b9f7SAxel Dörfler return NULL; 1409cd08b9f7SAxel Dörfler 1410cd08b9f7SAxel Dörfler interface->AcquireReference(); 1411cd08b9f7SAxel Dörfler return interface; 1412cd08b9f7SAxel Dörfler } 1413cd08b9f7SAxel Dörfler } 1414cd08b9f7SAxel Dörfler 1415cd08b9f7SAxel Dörfler return NULL; 1416cd08b9f7SAxel Dörfler } 1417cd08b9f7SAxel Dörfler 1418cd08b9f7SAxel Dörfler 141961729d93SAxel Dörfler InterfaceAddress* 142061729d93SAxel Dörfler get_interface_address(const sockaddr* local) 1421c22d69bfSAxel Dörfler { 142261729d93SAxel Dörfler if (local->sa_family == AF_UNSPEC) 142361729d93SAxel Dörfler return NULL; 1424c22d69bfSAxel Dörfler 142561729d93SAxel Dörfler MutexLocker locker(sHashLock); 1426c22d69bfSAxel Dörfler 142761729d93SAxel Dörfler InterfaceAddress* address = sAddressTable.Lookup(local); 142861729d93SAxel Dörfler if (address == NULL) 142961729d93SAxel Dörfler return NULL; 1430c22d69bfSAxel Dörfler 143161729d93SAxel Dörfler address->AcquireReference(); 143261729d93SAxel Dörfler return address; 143361729d93SAxel Dörfler } 143461729d93SAxel Dörfler 143561729d93SAxel Dörfler 143661729d93SAxel Dörfler InterfaceAddress* 143761729d93SAxel Dörfler get_interface_address_for_destination(net_domain* domain, 1438cd08b9f7SAxel Dörfler const sockaddr* destination) 143961729d93SAxel Dörfler { 144061729d93SAxel Dörfler MutexLocker locker(sLock); 144161729d93SAxel Dörfler 144261729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 144361729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 144461729d93SAxel Dörfler InterfaceAddress* address 144561729d93SAxel Dörfler = interface->AddressForDestination(domain, destination); 144661729d93SAxel Dörfler if (address != NULL) 144761729d93SAxel Dörfler return address; 144861729d93SAxel Dörfler } 144961729d93SAxel Dörfler 145061729d93SAxel Dörfler return NULL; 145161729d93SAxel Dörfler } 145261729d93SAxel Dörfler 145361729d93SAxel Dörfler 1454cd08b9f7SAxel Dörfler /*! Returns a reference to an InterfaceAddress of the specified \a domain that 1455cd08b9f7SAxel Dörfler belongs to the interface identified via \a linkAddress. Only the hardware 1456cd08b9f7SAxel Dörfler address is matched. 1457cd08b9f7SAxel Dörfler 1458cd08b9f7SAxel Dörfler If \a unconfiguredOnly is set, the interface address must not yet be 1459cd08b9f7SAxel Dörfler configured, or must currently be in the process of being configured. 1460cd08b9f7SAxel Dörfler */ 146161729d93SAxel Dörfler InterfaceAddress* 1462cd08b9f7SAxel Dörfler get_interface_address_for_link(net_domain* domain, const sockaddr* address, 1463cd08b9f7SAxel Dörfler bool unconfiguredOnly) 146461729d93SAxel Dörfler { 1465cd08b9f7SAxel Dörfler sockaddr_dl& linkAddress = *(sockaddr_dl*)address; 146661729d93SAxel Dörfler 146761729d93SAxel Dörfler MutexLocker locker(sLock); 146861729d93SAxel Dörfler 146961729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 147061729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1471cd08b9f7SAxel Dörfler // Test if the hardware address matches, or if the given interface 1472cd08b9f7SAxel Dörfler // matches, or if at least the index matches. 147361729d93SAxel Dörfler if (linkAddress.sdl_alen == interface->device->address.length 147461729d93SAxel Dörfler && memcmp(LLADDR(&linkAddress), interface->device->address.data, 147561729d93SAxel Dörfler linkAddress.sdl_alen) == 0) { 1476b0cf274aSAxel Dörfler TRACE(" %s matches\n", interface->name); 147761729d93SAxel Dörfler // link address matches 147861729d93SAxel Dörfler if (unconfiguredOnly) 147961729d93SAxel Dörfler return interface->FirstUnconfiguredForFamily(domain->family); 148061729d93SAxel Dörfler 148161729d93SAxel Dörfler return interface->FirstForFamily(domain->family); 148261729d93SAxel Dörfler } 148361729d93SAxel Dörfler } 148461729d93SAxel Dörfler 148561729d93SAxel Dörfler return NULL; 1486c22d69bfSAxel Dörfler } 1487c22d69bfSAxel Dörfler 1488c22d69bfSAxel Dörfler 1489c22d69bfSAxel Dörfler uint32 149061729d93SAxel Dörfler count_interfaces() 1491c22d69bfSAxel Dörfler { 149261729d93SAxel Dörfler MutexLocker locker(sLock); 1493c22d69bfSAxel Dörfler 149461729d93SAxel Dörfler return sInterfaces.Count(); 1495c22d69bfSAxel Dörfler } 1496c22d69bfSAxel Dörfler 1497c22d69bfSAxel Dörfler 14983c13a5f5SAxel Dörfler /*! Dumps a list of all interfaces into the supplied userland buffer. 1499c22d69bfSAxel Dörfler If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is 1500c22d69bfSAxel Dörfler returned. 1501c22d69bfSAxel Dörfler */ 1502c22d69bfSAxel Dörfler status_t 150361729d93SAxel Dörfler list_interfaces(int family, void* _buffer, size_t* bufferSize) 1504c22d69bfSAxel Dörfler { 150561729d93SAxel Dörfler MutexLocker locker(sLock); 1506c22d69bfSAxel Dörfler 1507409b1fc0SHugo Santos UserBuffer buffer(_buffer, *bufferSize); 1508c22d69bfSAxel Dörfler 150961729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 151061729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1511715fed44SAxel Dörfler // Copy name 1512715fed44SAxel Dörfler buffer.Push(interface->name, IF_NAMESIZE); 1513c22d69bfSAxel Dörfler 1514715fed44SAxel Dörfler // Copy address 151561729d93SAxel Dörfler InterfaceAddress* address = interface->FirstForFamily(family); 15161f9c8c45SAxel Dörfler size_t length = 0; 1517715fed44SAxel Dörfler 151861729d93SAxel Dörfler if (address != NULL && address->local != NULL) { 1519715fed44SAxel Dörfler // Actual address 15201f9c8c45SAxel Dörfler buffer.Push(address->local, length = address->local->sa_len); 152161729d93SAxel Dörfler } else { 1522715fed44SAxel Dörfler // Empty address 15231f9c8c45SAxel Dörfler sockaddr empty; 15241f9c8c45SAxel Dörfler empty.sa_len = 2; 15251f9c8c45SAxel Dörfler empty.sa_family = AF_UNSPEC; 15261f9c8c45SAxel Dörfler buffer.Push(&empty, length = empty.sa_len); 1527715fed44SAxel Dörfler } 1528715fed44SAxel Dörfler 152961729d93SAxel Dörfler if (address != NULL) 153061729d93SAxel Dörfler address->ReleaseReference(); 153161729d93SAxel Dörfler 15321f9c8c45SAxel Dörfler if (IF_NAMESIZE + length < sizeof(ifreq)) { 15331f9c8c45SAxel Dörfler // Make sure at least sizeof(ifreq) bytes are written for each 15341f9c8c45SAxel Dörfler // interface for compatibility with other platforms 15351f9c8c45SAxel Dörfler buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length); 15361f9c8c45SAxel Dörfler } 15371f9c8c45SAxel Dörfler 15381f9c8c45SAxel Dörfler if (buffer.Status() != B_OK) 1539409b1fc0SHugo Santos return buffer.Status(); 1540c22d69bfSAxel Dörfler } 1541c22d69bfSAxel Dörfler 1542715fed44SAxel Dörfler *bufferSize = buffer.BytesConsumed(); 1543c22d69bfSAxel Dörfler return B_OK; 1544c22d69bfSAxel Dörfler } 1545c22d69bfSAxel Dörfler 1546c22d69bfSAxel Dörfler 1547c22d69bfSAxel Dörfler // #pragma mark - 1548c22d69bfSAxel Dörfler 1549c22d69bfSAxel Dörfler 1550c22d69bfSAxel Dörfler status_t 1551c22d69bfSAxel Dörfler init_interfaces() 1552c22d69bfSAxel Dörfler { 155361729d93SAxel Dörfler mutex_init(&sLock, "net interfaces"); 155461729d93SAxel Dörfler mutex_init(&sHashLock, "net local addresses"); 1555c22d69bfSAxel Dörfler 155661729d93SAxel Dörfler new (&sInterfaces) InterfaceList; 155761729d93SAxel Dörfler new (&sAddressTable) AddressTable; 15589206bb37SAxel Dörfler // static C++ objects are not initialized in the module startup 1559a3ec278aSAxel Dörfler 1560a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 1561a3ec278aSAxel Dörfler add_debugger_command("net_interface", &dump_interface, 1562a3ec278aSAxel Dörfler "Dump the given network interface"); 156361729d93SAxel Dörfler add_debugger_command("net_interfaces", &dump_interfaces, 156461729d93SAxel Dörfler "Dump all network interfaces"); 156561729d93SAxel Dörfler add_debugger_command("net_local", &dump_local, 156661729d93SAxel Dörfler "Dump all local interface addresses"); 156761729d93SAxel Dörfler add_debugger_command("net_route", &dump_route, 156861729d93SAxel Dörfler "Dump the given network route"); 1569a3ec278aSAxel Dörfler #endif 1570c22d69bfSAxel Dörfler return B_OK; 1571c22d69bfSAxel Dörfler } 1572c22d69bfSAxel Dörfler 1573c22d69bfSAxel Dörfler 1574c22d69bfSAxel Dörfler status_t 1575c22d69bfSAxel Dörfler uninit_interfaces() 1576c22d69bfSAxel Dörfler { 1577a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 1578a3ec278aSAxel Dörfler remove_debugger_command("net_interface", &dump_interface); 1579a3ec278aSAxel Dörfler #endif 1580a3ec278aSAxel Dörfler 158161729d93SAxel Dörfler mutex_destroy(&sLock); 158261729d93SAxel Dörfler mutex_destroy(&sHashLock); 1583c22d69bfSAxel Dörfler return B_OK; 1584c22d69bfSAxel Dörfler } 1585c22d69bfSAxel Dörfler 1586