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 538*910ffb32SAxel Dörfler /*! Returns a reference to the InterfaceAddress that has the specified 539*910ffb32SAxel Dörfler \a local address. 540*910ffb32SAxel Dörfler */ 541*910ffb32SAxel Dörfler InterfaceAddress* 542*910ffb32SAxel Dörfler Interface::AddressForLocal(net_domain* domain, const sockaddr* local) 543*910ffb32SAxel Dörfler { 544*910ffb32SAxel Dörfler RecursiveLocker locker(fLock); 545*910ffb32SAxel Dörfler 546*910ffb32SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 547*910ffb32SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 548*910ffb32SAxel Dörfler if (address->domain == domain 549*910ffb32SAxel Dörfler && address->local != NULL 550*910ffb32SAxel Dörfler && domain->address_module->equal_addresses(address->local, local)) { 551*910ffb32SAxel Dörfler address->AcquireReference(); 552*910ffb32SAxel Dörfler return address; 553*910ffb32SAxel Dörfler } 554*910ffb32SAxel Dörfler } 555*910ffb32SAxel Dörfler 556*910ffb32SAxel Dörfler return NULL; 557*910ffb32SAxel Dörfler } 558*910ffb32SAxel Dörfler 559*910ffb32SAxel 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 6419d771afbSAxel Dörfler size_t 6429d771afbSAxel Dörfler Interface::CountAddresses() 6439d771afbSAxel Dörfler { 6449d771afbSAxel Dörfler RecursiveLocker locker(fLock); 6459d771afbSAxel Dörfler return fAddresses.Count(); 6469d771afbSAxel Dörfler } 6479d771afbSAxel Dörfler 6489d771afbSAxel Dörfler 6492b1c0755SAxel Dörfler void 6502b1c0755SAxel Dörfler Interface::RemoveAddresses() 6512b1c0755SAxel Dörfler { 6522b1c0755SAxel Dörfler RecursiveLocker locker(fLock); 6532b1c0755SAxel Dörfler 6542b1c0755SAxel Dörfler while (InterfaceAddress* address = fAddresses.RemoveHead()) { 6552b1c0755SAxel Dörfler address->ReleaseReference(); 6562b1c0755SAxel Dörfler } 6572b1c0755SAxel Dörfler } 6582b1c0755SAxel Dörfler 6592b1c0755SAxel Dörfler 6609d771afbSAxel Dörfler /*! This is called in order to call the correct methods of the datalink 6619d771afbSAxel Dörfler protocols, ie. it will translate address changes to 6629d771afbSAxel Dörfler net_datalink_protocol::change_address(), and IFF_UP changes to 6639d771afbSAxel Dörfler net_datalink_protocol::interface_up(), and interface_down(). 6649d771afbSAxel Dörfler 6659d771afbSAxel Dörfler Everything else is passed unchanged to net_datalink_protocol::control(). 6669d771afbSAxel Dörfler */ 66761729d93SAxel Dörfler status_t 66861729d93SAxel Dörfler Interface::Control(net_domain* domain, int32 option, ifreq& request, 66961729d93SAxel Dörfler ifreq* userRequest, size_t length) 67061729d93SAxel Dörfler { 67161729d93SAxel Dörfler switch (option) { 67261729d93SAxel Dörfler case SIOCSIFFLAGS: 67361729d93SAxel Dörfler { 674e8802e49SAxel Dörfler if (length != sizeof(ifreq)) 675e8802e49SAxel Dörfler return B_BAD_VALUE; 676e8802e49SAxel Dörfler 67761729d93SAxel Dörfler uint32 requestFlags = request.ifr_flags; 67861729d93SAxel Dörfler uint32 oldFlags = flags; 67961729d93SAxel Dörfler status_t status = B_OK; 68061729d93SAxel Dörfler 68161729d93SAxel Dörfler request.ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST); 68261729d93SAxel Dörfler 68361729d93SAxel Dörfler if ((requestFlags & IFF_UP) != (flags & IFF_UP)) { 68461729d93SAxel Dörfler if ((requestFlags & IFF_UP) != 0) 68561729d93SAxel Dörfler status = _SetUp(); 68661729d93SAxel Dörfler else 6872b1c0755SAxel Dörfler SetDown(); 68861729d93SAxel Dörfler } 68961729d93SAxel Dörfler 69061729d93SAxel Dörfler if (status == B_OK) { 69161729d93SAxel Dörfler // TODO: maybe allow deleting IFF_BROADCAST on the interface 69261729d93SAxel Dörfler // level? 69361729d93SAxel Dörfler flags &= IFF_UP | IFF_LINK | IFF_BROADCAST; 69461729d93SAxel Dörfler flags |= request.ifr_flags; 69561729d93SAxel Dörfler } 69661729d93SAxel Dörfler 69761729d93SAxel Dörfler if (oldFlags != flags) 69861729d93SAxel Dörfler notify_interface_changed(this, oldFlags, flags); 69961729d93SAxel Dörfler 70061729d93SAxel Dörfler return status; 70161729d93SAxel Dörfler } 70261729d93SAxel Dörfler 7032b1c0755SAxel Dörfler case B_SOCKET_SET_ALIAS: 7049d771afbSAxel Dörfler { 705e8802e49SAxel Dörfler if (length != sizeof(ifaliasreq)) 706e8802e49SAxel Dörfler return B_BAD_VALUE; 707e8802e49SAxel Dörfler 7089d771afbSAxel Dörfler RecursiveLocker locker(fLock); 7099d771afbSAxel Dörfler 7109d771afbSAxel Dörfler ifaliasreq aliasRequest; 7119d771afbSAxel Dörfler if (user_memcpy(&aliasRequest, userRequest, sizeof(ifaliasreq)) 7129d771afbSAxel Dörfler != B_OK) 7139d771afbSAxel Dörfler return B_BAD_ADDRESS; 7149d771afbSAxel Dörfler 715*910ffb32SAxel Dörfler InterfaceAddress* address = NULL; 716*910ffb32SAxel Dörfler if (aliasRequest.ifra_index < 0) { 717*910ffb32SAxel Dörfler if (!domain->address_module->is_empty_address( 718*910ffb32SAxel Dörfler (const sockaddr*)&aliasRequest.ifra_addr, false)) { 719*910ffb32SAxel Dörfler // Find first address that matches the local address 720*910ffb32SAxel Dörfler address = AddressForLocal(domain, 721*910ffb32SAxel Dörfler (const sockaddr*)&aliasRequest.ifra_addr); 722*910ffb32SAxel Dörfler } 723*910ffb32SAxel Dörfler if (address == NULL) { 724*910ffb32SAxel Dörfler // Find first address for family 725*910ffb32SAxel Dörfler address = FirstForFamily(domain->family); 726*910ffb32SAxel Dörfler } 727*910ffb32SAxel Dörfler } else 728*910ffb32SAxel Dörfler address = AddressAt(aliasRequest.ifra_index); 729*910ffb32SAxel Dörfler 7309d771afbSAxel Dörfler if (address == NULL) 7319d771afbSAxel Dörfler return B_BAD_VALUE; 7329d771afbSAxel Dörfler 7339d771afbSAxel Dörfler status_t status = B_OK; 7349d771afbSAxel Dörfler address->AcquireReference(); 7359d771afbSAxel Dörfler // _ChangeAddress() currently unlocks, so we need another 7369d771afbSAxel Dörfler // reference to make sure "address" is not going away. 7379d771afbSAxel Dörfler 7389d771afbSAxel Dörfler if (!domain->address_module->equal_addresses( 7399d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_addr, address->local)) { 7409d771afbSAxel Dörfler status = _ChangeAddress(locker, address, SIOCSIFADDR, 7419d771afbSAxel Dörfler address->local, (sockaddr*)&aliasRequest.ifra_addr); 7429d771afbSAxel Dörfler } 7439d771afbSAxel Dörfler 7449d771afbSAxel Dörfler if (status == B_OK && !domain->address_module->equal_addresses( 745*910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_mask, address->mask) 746*910ffb32SAxel Dörfler && !domain->address_module->is_empty_address( 747*910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_mask, false)) { 7489d771afbSAxel Dörfler status = _ChangeAddress(locker, address, SIOCSIFNETMASK, 7499d771afbSAxel Dörfler address->mask, (sockaddr*)&aliasRequest.ifra_mask); 7509d771afbSAxel Dörfler } 7519d771afbSAxel Dörfler 7529d771afbSAxel Dörfler if (status == B_OK && !domain->address_module->equal_addresses( 7539d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination, 754*910ffb32SAxel Dörfler address->destination) 755*910ffb32SAxel Dörfler && !domain->address_module->is_empty_address( 756*910ffb32SAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination, false)) { 7579d771afbSAxel Dörfler status = _ChangeAddress(locker, address, 7589d771afbSAxel Dörfler (domain->address_module->flags 7599d771afbSAxel Dörfler & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0 7609d771afbSAxel Dörfler ? SIOCSIFBRDADDR : SIOCSIFDSTADDR, 7619d771afbSAxel Dörfler address->destination, 7629d771afbSAxel Dörfler (sockaddr*)&aliasRequest.ifra_destination); 7639d771afbSAxel Dörfler } 7649d771afbSAxel Dörfler 7659d771afbSAxel Dörfler address->ReleaseReference(); 7669d771afbSAxel Dörfler return status; 7679d771afbSAxel Dörfler } 7689d771afbSAxel Dörfler 76961729d93SAxel Dörfler case SIOCSIFADDR: 77061729d93SAxel Dörfler case SIOCSIFNETMASK: 77161729d93SAxel Dörfler case SIOCSIFBRDADDR: 77261729d93SAxel Dörfler case SIOCSIFDSTADDR: 77361729d93SAxel Dörfler case SIOCDIFADDR: 77461729d93SAxel Dörfler { 775e8802e49SAxel Dörfler if (length != sizeof(ifreq)) 776e8802e49SAxel Dörfler return B_BAD_VALUE; 777e8802e49SAxel Dörfler 77861729d93SAxel Dörfler RecursiveLocker locker(fLock); 77961729d93SAxel Dörfler 78061729d93SAxel Dörfler InterfaceAddress* address = NULL; 78161729d93SAxel Dörfler sockaddr_storage newAddress; 78261729d93SAxel Dörfler 78361729d93SAxel Dörfler size_t size = max_c(request.ifr_addr.sa_len, sizeof(sockaddr)); 78461729d93SAxel Dörfler if (size > sizeof(sockaddr_storage)) 78561729d93SAxel Dörfler size = sizeof(sockaddr_storage); 78661729d93SAxel Dörfler 78761729d93SAxel Dörfler if (user_memcpy(&newAddress, &userRequest->ifr_addr, size) != B_OK) 78861729d93SAxel Dörfler return B_BAD_ADDRESS; 78961729d93SAxel Dörfler 79061729d93SAxel Dörfler if (option == SIOCDIFADDR) { 79161729d93SAxel Dörfler // Find referring address - we can't use the hash, as another 79261729d93SAxel Dörfler // interface might use the same address. 79361729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 79461729d93SAxel Dörfler while ((address = iterator.Next()) != NULL) { 79561729d93SAxel Dörfler if (address->domain == domain 79661729d93SAxel Dörfler && domain->address_module->equal_addresses( 79761729d93SAxel Dörfler address->local, (sockaddr*)&newAddress)) 79861729d93SAxel Dörfler break; 79961729d93SAxel Dörfler } 80061729d93SAxel Dörfler 80161729d93SAxel Dörfler if (address == NULL) 80261729d93SAxel Dörfler return B_BAD_VALUE; 80378abd727SAxel Dörfler } else { 80478abd727SAxel Dörfler // Just use the first address for this family 80578abd727SAxel Dörfler address = _FirstForFamily(domain->family); 80678abd727SAxel Dörfler if (address == NULL) { 80778abd727SAxel Dörfler // Create new on the fly 80878abd727SAxel Dörfler address = new(std::nothrow) InterfaceAddress(this, domain); 80978abd727SAxel Dörfler if (address == NULL) 81078abd727SAxel Dörfler return B_NO_MEMORY; 81178abd727SAxel Dörfler 81278abd727SAxel Dörfler status_t status = AddAddress(address); 81378abd727SAxel Dörfler if (status != B_OK) 81478abd727SAxel Dörfler return status; 81578abd727SAxel Dörfler 81678abd727SAxel Dörfler // Note, even if setting the address failed, the empty 81778abd727SAxel Dörfler // address added here will still be added to the interface. 81878abd727SAxel Dörfler } 81978abd727SAxel Dörfler } 82061729d93SAxel Dörfler 8219d771afbSAxel Dörfler return _ChangeAddress(locker, address, option, 8229d771afbSAxel Dörfler *address->AddressFor(option), 82361729d93SAxel Dörfler option != SIOCDIFADDR ? (sockaddr*)&newAddress : NULL); 82461729d93SAxel Dörfler } 82561729d93SAxel Dörfler 82661729d93SAxel Dörfler default: 82761729d93SAxel Dörfler // pass the request into the datalink protocol stack 82861729d93SAxel Dörfler domain_datalink* datalink = DomainDatalink(domain->family); 82961729d93SAxel Dörfler if (datalink->first_info != NULL) { 83061729d93SAxel Dörfler return datalink->first_info->control( 83161729d93SAxel Dörfler datalink->first_protocol, option, userRequest, length); 83261729d93SAxel Dörfler } 83361729d93SAxel Dörfler break; 83461729d93SAxel Dörfler } 83561729d93SAxel Dörfler 83661729d93SAxel Dörfler return B_BAD_VALUE; 83761729d93SAxel Dörfler } 83861729d93SAxel Dörfler 83961729d93SAxel Dörfler 8402b1c0755SAxel Dörfler void 8412b1c0755SAxel Dörfler Interface::SetDown() 8422b1c0755SAxel Dörfler { 8432b1c0755SAxel Dörfler if ((flags & IFF_UP) == 0) 8442b1c0755SAxel Dörfler return; 8452b1c0755SAxel Dörfler 8462b1c0755SAxel Dörfler RecursiveLocker locker(fLock); 8472b1c0755SAxel Dörfler 8482b1c0755SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 8492b1c0755SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) { 8502b1c0755SAxel Dörfler datalink->first_info->interface_down(datalink->first_protocol); 8512b1c0755SAxel Dörfler } 8522b1c0755SAxel Dörfler 8532b1c0755SAxel Dörfler flags &= ~IFF_UP; 8542b1c0755SAxel Dörfler } 8552b1c0755SAxel Dörfler 8562b1c0755SAxel Dörfler 8572b1c0755SAxel Dörfler /*! Called when a device lost its IFF_UP status. We will invalidate all 8582b1c0755SAxel Dörfler interface routes here. 8592b1c0755SAxel Dörfler */ 8602b1c0755SAxel Dörfler void 8612b1c0755SAxel Dörfler Interface::WentDown() 8622b1c0755SAxel Dörfler { 8632b1c0755SAxel Dörfler RecursiveLocker locker(fLock); 8642b1c0755SAxel Dörfler 8652b1c0755SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 8662b1c0755SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 8672b1c0755SAxel Dörfler if (address->domain != NULL) 8682b1c0755SAxel Dörfler invalidate_routes(address->domain, this); 8692b1c0755SAxel Dörfler } 8702b1c0755SAxel Dörfler } 8712b1c0755SAxel Dörfler 8722b1c0755SAxel Dörfler 87361729d93SAxel Dörfler status_t 87461729d93SAxel Dörfler Interface::CreateDomainDatalinkIfNeeded(net_domain* domain) 87561729d93SAxel Dörfler { 87661729d93SAxel Dörfler RecursiveLocker locker(fLock); 87761729d93SAxel Dörfler 87861729d93SAxel Dörfler if (fDatalinkTable.Lookup(domain->family) != NULL) 87961729d93SAxel Dörfler return B_OK; 88061729d93SAxel Dörfler 88161729d93SAxel Dörfler TRACE("Interface %p: create domain datalink for domain %p\n", this, domain); 88261729d93SAxel Dörfler 88361729d93SAxel Dörfler domain_datalink* datalink = new(std::nothrow) domain_datalink; 88461729d93SAxel Dörfler if (datalink == NULL) 88561729d93SAxel Dörfler return B_NO_MEMORY; 88661729d93SAxel Dörfler 88761729d93SAxel Dörfler datalink->domain = domain; 88861729d93SAxel Dörfler 88961729d93SAxel Dörfler // setup direct route for bound devices 89061729d93SAxel Dörfler datalink->direct_route.destination = NULL; 89161729d93SAxel Dörfler datalink->direct_route.mask = NULL; 89261729d93SAxel Dörfler datalink->direct_route.gateway = NULL; 89361729d93SAxel Dörfler datalink->direct_route.flags = 0; 89461729d93SAxel Dörfler datalink->direct_route.mtu = 0; 89561729d93SAxel Dörfler datalink->direct_route.interface_address = &datalink->direct_address; 89661729d93SAxel Dörfler datalink->direct_route.ref_count = 1; 89761729d93SAxel Dörfler // make sure this doesn't get deleted accidently 89861729d93SAxel Dörfler 89961729d93SAxel Dörfler // provide its link back to the interface 90061729d93SAxel Dörfler datalink->direct_address.local = NULL; 90161729d93SAxel Dörfler datalink->direct_address.destination = NULL; 90261729d93SAxel Dörfler datalink->direct_address.mask = NULL; 90361729d93SAxel Dörfler datalink->direct_address.domain = domain; 90461729d93SAxel Dörfler datalink->direct_address.interface = this; 9052b1c0755SAxel Dörfler datalink->direct_address.flags = IFAF_DIRECT_ADDRESS; 90661729d93SAxel Dörfler 90761729d93SAxel Dörfler fDatalinkTable.Insert(datalink); 90861729d93SAxel Dörfler 90961729d93SAxel Dörfler status_t status = get_domain_datalink_protocols(this, domain); 91061729d93SAxel Dörfler if (status == B_OK) 91161729d93SAxel Dörfler return B_OK; 91261729d93SAxel Dörfler 91361729d93SAxel Dörfler fDatalinkTable.Remove(datalink); 91461729d93SAxel Dörfler delete datalink; 91561729d93SAxel Dörfler 91661729d93SAxel Dörfler return status; 91761729d93SAxel Dörfler } 91861729d93SAxel Dörfler 91961729d93SAxel Dörfler 92061729d93SAxel Dörfler domain_datalink* 92161729d93SAxel Dörfler Interface::DomainDatalink(uint8 family) 92261729d93SAxel Dörfler { 92361729d93SAxel Dörfler // Note: domain datalinks cannot be removed while the interface is alive, 92461729d93SAxel Dörfler // since this would require us either to hold the lock while calling this 92561729d93SAxel Dörfler // function, or introduce reference counting for the domain_datalink 92661729d93SAxel Dörfler // structure. 92761729d93SAxel Dörfler RecursiveLocker locker(fLock); 92861729d93SAxel Dörfler return fDatalinkTable.Lookup(family); 92961729d93SAxel Dörfler } 93061729d93SAxel Dörfler 93161729d93SAxel Dörfler 93261729d93SAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 93361729d93SAxel Dörfler 93461729d93SAxel Dörfler 93561729d93SAxel Dörfler void 93661729d93SAxel Dörfler Interface::Dump() const 93761729d93SAxel Dörfler { 93861729d93SAxel Dörfler kprintf("name: %s\n", name); 93961729d93SAxel Dörfler kprintf("device: %p\n", device); 94061729d93SAxel Dörfler kprintf("device_interface: %p\n", fDeviceInterface); 94161729d93SAxel Dörfler kprintf("index: %" B_PRIu32 "\n", index); 94261729d93SAxel Dörfler kprintf("flags: %#" B_PRIx32 "\n", flags); 94361729d93SAxel Dörfler kprintf("type: %u\n", type); 94461729d93SAxel Dörfler kprintf("mtu: %" B_PRIu32 "\n", mtu); 94561729d93SAxel Dörfler kprintf("metric: %" B_PRIu32 "\n", metric); 94661729d93SAxel Dörfler 94761729d93SAxel Dörfler kprintf("datalink protocols:\n"); 94861729d93SAxel Dörfler 94961729d93SAxel Dörfler DatalinkTable::Iterator datalinkIterator = fDatalinkTable.GetIterator(); 95061729d93SAxel Dörfler size_t i = 0; 95161729d93SAxel Dörfler while (domain_datalink* datalink = datalinkIterator.Next()) { 95261729d93SAxel Dörfler kprintf("%2zu. domain: %p\n", ++i, datalink->domain); 95361729d93SAxel Dörfler kprintf(" first_protocol: %p\n", datalink->first_protocol); 95461729d93SAxel Dörfler kprintf(" first_info: %p\n", datalink->first_info); 95561729d93SAxel Dörfler kprintf(" direct_route: %p\n", &datalink->direct_route); 95661729d93SAxel Dörfler } 95761729d93SAxel Dörfler 95861729d93SAxel Dörfler kprintf("addresses:\n"); 95961729d93SAxel Dörfler 96061729d93SAxel Dörfler AddressList::ConstIterator iterator = fAddresses.GetIterator(); 96161729d93SAxel Dörfler i = 0; 96261729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 96361729d93SAxel Dörfler address->Dump(++i, true); 96461729d93SAxel Dörfler } 96561729d93SAxel Dörfler } 96661729d93SAxel Dörfler 96761729d93SAxel Dörfler 96861729d93SAxel Dörfler #endif // ENABLE_DEBUGGER_COMMANDS 96961729d93SAxel Dörfler 97061729d93SAxel Dörfler 97161729d93SAxel Dörfler status_t 97261729d93SAxel Dörfler Interface::_SetUp() 97361729d93SAxel Dörfler { 97461729d93SAxel Dörfler status_t status = up_device_interface(fDeviceInterface); 97561729d93SAxel Dörfler if (status != B_OK) 97661729d93SAxel Dörfler return status; 97761729d93SAxel Dörfler 9782b1c0755SAxel Dörfler // Propagate flag to all datalink protocols 97961729d93SAxel Dörfler 98061729d93SAxel Dörfler RecursiveLocker locker(fLock); 98161729d93SAxel Dörfler 98261729d93SAxel Dörfler DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); 98361729d93SAxel Dörfler while (domain_datalink* datalink = iterator.Next()) { 98461729d93SAxel Dörfler status = datalink->first_info->interface_up(datalink->first_protocol); 98561729d93SAxel Dörfler if (status != B_OK) { 98661729d93SAxel Dörfler // Revert "up" status 98761729d93SAxel Dörfler DatalinkTable::Iterator secondIterator 98861729d93SAxel Dörfler = fDatalinkTable.GetIterator(); 98961729d93SAxel Dörfler while (secondIterator.HasNext()) { 99061729d93SAxel Dörfler domain_datalink* secondDatalink = secondIterator.Next(); 99161729d93SAxel Dörfler if (secondDatalink == NULL || secondDatalink == datalink) 992c22d69bfSAxel Dörfler break; 993c22d69bfSAxel Dörfler 99461729d93SAxel Dörfler secondDatalink->first_info->interface_down( 99561729d93SAxel Dörfler secondDatalink->first_protocol); 99661729d93SAxel Dörfler } 99761729d93SAxel Dörfler 99861729d93SAxel Dörfler down_device_interface(fDeviceInterface); 99961729d93SAxel Dörfler return status; 100061729d93SAxel Dörfler } 100161729d93SAxel Dörfler } 100261729d93SAxel Dörfler 10032b1c0755SAxel Dörfler // Add default routes for the existing addresses 10042b1c0755SAxel Dörfler 10052b1c0755SAxel Dörfler AddressList::Iterator addressIterator = fAddresses.GetIterator(); 10062b1c0755SAxel Dörfler while (InterfaceAddress* address = addressIterator.Next()) { 10072b1c0755SAxel Dörfler address->AddDefaultRoutes(SIOCSIFADDR); 10082b1c0755SAxel Dörfler } 10092b1c0755SAxel Dörfler 101061729d93SAxel Dörfler flags |= IFF_UP; 101161729d93SAxel Dörfler return B_OK; 101261729d93SAxel Dörfler } 101361729d93SAxel Dörfler 101461729d93SAxel Dörfler 101561729d93SAxel Dörfler InterfaceAddress* 101661729d93SAxel Dörfler Interface::_FirstForFamily(int family) 101761729d93SAxel Dörfler { 101861729d93SAxel Dörfler ASSERT_LOCKED_RECURSIVE(&fLock); 101961729d93SAxel Dörfler 102061729d93SAxel Dörfler AddressList::Iterator iterator = fAddresses.GetIterator(); 102161729d93SAxel Dörfler while (InterfaceAddress* address = iterator.Next()) { 102261729d93SAxel Dörfler if (address->domain != NULL && address->domain->family == family) 102361729d93SAxel Dörfler return address; 102461729d93SAxel Dörfler } 102561729d93SAxel Dörfler 102661729d93SAxel Dörfler return NULL; 102761729d93SAxel Dörfler } 102861729d93SAxel Dörfler 102961729d93SAxel Dörfler 10309d771afbSAxel Dörfler status_t 10319d771afbSAxel Dörfler Interface::_ChangeAddress(RecursiveLocker& locker, InterfaceAddress* address, 1032b0cf274aSAxel Dörfler int32 option, const sockaddr* originalAddress, 1033b0cf274aSAxel Dörfler const sockaddr* requestedAddress) 10349d771afbSAxel Dörfler { 1035b0cf274aSAxel Dörfler // Copy old address 10369d771afbSAxel Dörfler sockaddr_storage oldAddress; 10379d771afbSAxel Dörfler if (address->domain->address_module->set_to((sockaddr*)&oldAddress, 10389d771afbSAxel Dörfler originalAddress) != B_OK) 10399d771afbSAxel Dörfler oldAddress.ss_family = AF_UNSPEC; 10409d771afbSAxel Dörfler 1041b0cf274aSAxel Dörfler // Copy new address (this also makes sure that sockaddr::sa_len is set 1042b0cf274aSAxel Dörfler // correctly) 1043b0cf274aSAxel Dörfler sockaddr_storage newAddress; 1044b0cf274aSAxel Dörfler if (address->domain->address_module->set_to((sockaddr*)&newAddress, 1045b0cf274aSAxel Dörfler requestedAddress) != B_OK) 1046b0cf274aSAxel Dörfler newAddress.ss_family = AF_UNSPEC; 1047b0cf274aSAxel Dörfler 10486b1e1488SAxel Dörfler // Test if anything changed for real 1049b0cf274aSAxel Dörfler if (address->domain->address_module->equal_addresses( 1050b0cf274aSAxel Dörfler (sockaddr*)&oldAddress, (sockaddr*)&newAddress)) { 10516b1e1488SAxel Dörfler // Nothing to do 1052b0cf274aSAxel Dörfler TRACE(" option %" B_PRId32 " addresses are equal!\n", option); 10536b1e1488SAxel Dörfler return B_OK; 10546b1e1488SAxel Dörfler } 10556b1e1488SAxel Dörfler 10569d771afbSAxel Dörfler // TODO: mark this address busy or call while holding the lock! 10579d771afbSAxel Dörfler address->AcquireReference(); 10589d771afbSAxel Dörfler locker.Unlock(); 10599d771afbSAxel Dörfler 10609d771afbSAxel Dörfler domain_datalink* datalink = DomainDatalink(address->domain); 10619d771afbSAxel Dörfler status_t status = datalink->first_protocol->module->change_address( 10629d771afbSAxel Dörfler datalink->first_protocol, address, option, 10639d771afbSAxel Dörfler oldAddress.ss_family != AF_UNSPEC ? (sockaddr*)&oldAddress : NULL, 1064b0cf274aSAxel Dörfler newAddress.ss_family != AF_UNSPEC ? (sockaddr*)&newAddress : NULL); 10659d771afbSAxel Dörfler 10669d771afbSAxel Dörfler locker.Lock(); 10679d771afbSAxel Dörfler address->ReleaseReference(); 10689d771afbSAxel Dörfler return status; 10699d771afbSAxel Dörfler } 10709d771afbSAxel Dörfler 10719d771afbSAxel Dörfler 107261729d93SAxel Dörfler // #pragma mark - 107361729d93SAxel Dörfler 107461729d93SAxel Dörfler 107561729d93SAxel Dörfler /*! Searches for a specific interface by name. 107661729d93SAxel Dörfler You need to have the interface list's lock hold when calling this function. 107761729d93SAxel Dörfler */ 107861729d93SAxel Dörfler static struct Interface* 107961729d93SAxel Dörfler find_interface(const char* name) 108061729d93SAxel Dörfler { 108161729d93SAxel Dörfler ASSERT_LOCKED_MUTEX(&sLock); 108261729d93SAxel Dörfler 108361729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 108461729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1085c22d69bfSAxel Dörfler if (!strcmp(interface->name, name)) 1086c22d69bfSAxel Dörfler return interface; 1087c22d69bfSAxel Dörfler } 1088c22d69bfSAxel Dörfler 1089c22d69bfSAxel Dörfler return NULL; 1090c22d69bfSAxel Dörfler } 1091c22d69bfSAxel Dörfler 1092c22d69bfSAxel Dörfler 109361729d93SAxel Dörfler /*! Searches for a specific interface by index. 109461729d93SAxel Dörfler You need to have the interface list's lock hold when calling this function. 1095c22d69bfSAxel Dörfler */ 109661729d93SAxel Dörfler static struct Interface* 109761729d93SAxel Dörfler find_interface(uint32 index) 1098c22d69bfSAxel Dörfler { 109961729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 110061729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1101c22d69bfSAxel Dörfler if (interface->index == index) 1102c22d69bfSAxel Dörfler return interface; 1103c22d69bfSAxel Dörfler } 1104c22d69bfSAxel Dörfler 1105c22d69bfSAxel Dörfler return NULL; 1106c22d69bfSAxel Dörfler } 1107c22d69bfSAxel Dörfler 1108c22d69bfSAxel Dörfler 110961729d93SAxel Dörfler // #pragma mark - 111061729d93SAxel Dörfler 111161729d93SAxel Dörfler 111261729d93SAxel Dörfler status_t 111361729d93SAxel Dörfler add_interface(const char* name, net_domain_private* domain, 111461729d93SAxel Dörfler const ifaliasreq& request, net_device_interface* deviceInterface) 111561729d93SAxel Dörfler { 111661729d93SAxel Dörfler MutexLocker locker(sLock); 111761729d93SAxel Dörfler 111861729d93SAxel Dörfler if (find_interface(name) != NULL) 111961729d93SAxel Dörfler return B_NAME_IN_USE; 112061729d93SAxel Dörfler 112161729d93SAxel Dörfler Interface* interface 112261729d93SAxel Dörfler = new(std::nothrow) Interface(name, deviceInterface); 1123c22d69bfSAxel Dörfler if (interface == NULL) 1124c22d69bfSAxel Dörfler return B_NO_MEMORY; 1125c22d69bfSAxel Dörfler 112661729d93SAxel Dörfler sInterfaces.Add(interface); 112761729d93SAxel Dörfler interface->AcquireReference(); 112861729d93SAxel Dörfler // We need another reference to be able to use the interface without 112961729d93SAxel Dörfler // holding sLock. 1130c22d69bfSAxel Dörfler 113161729d93SAxel Dörfler locker.Unlock(); 1132c22d69bfSAxel Dörfler 113361729d93SAxel Dörfler notify_interface_added(interface); 113461729d93SAxel Dörfler add_interface_address(interface, domain, request); 1135c22d69bfSAxel Dörfler 113661729d93SAxel Dörfler interface->ReleaseReference(); 113727e0dea9SAxel Dörfler 1138c22d69bfSAxel Dörfler return B_OK; 1139c22d69bfSAxel Dörfler } 1140c22d69bfSAxel Dörfler 1141c22d69bfSAxel Dörfler 114261729d93SAxel Dörfler /*! Removes the interface from the list, and puts the stack's reference to it. 114361729d93SAxel Dörfler */ 11447aa2819cSAxel Dörfler void 114561729d93SAxel Dörfler remove_interface(Interface* interface) 1146c64feccaSHugo Santos { 11472b1c0755SAxel Dörfler interface->SetDown(); 11482b1c0755SAxel Dörfler interface->RemoveAddresses(); 1149c64feccaSHugo Santos 11502b1c0755SAxel Dörfler MutexLocker locker(sLock); 11512b1c0755SAxel Dörfler sInterfaces.Remove(interface); 11522b1c0755SAxel Dörfler locker.Unlock(); 1153f6d219a1SAxel Dörfler 115461729d93SAxel Dörfler notify_interface_removed(interface); 1155c22d69bfSAxel Dörfler 11562b1c0755SAxel Dörfler interface->ReleaseReference(); 11577aa2819cSAxel Dörfler } 11587aa2819cSAxel Dörfler 11597aa2819cSAxel Dörfler 11607aa2819cSAxel Dörfler /*! This is called whenever a device interface is being removed. We will get 11617aa2819cSAxel Dörfler the corresponding Interface, and remove it. 11627aa2819cSAxel Dörfler */ 11637aa2819cSAxel Dörfler void 11647aa2819cSAxel Dörfler interface_removed_device_interface(net_device_interface* deviceInterface) 11657aa2819cSAxel Dörfler { 11667aa2819cSAxel Dörfler MutexLocker locker(sLock); 11677aa2819cSAxel Dörfler 11687aa2819cSAxel Dörfler Interface* interface = find_interface(deviceInterface->device->name); 11697aa2819cSAxel Dörfler if (interface != NULL) 11707aa2819cSAxel Dörfler remove_interface(interface); 1171c22d69bfSAxel Dörfler } 1172c22d69bfSAxel Dörfler 1173c22d69bfSAxel Dörfler 117461729d93SAxel Dörfler status_t 117561729d93SAxel Dörfler add_interface_address(Interface* interface, net_domain_private* domain, 117661729d93SAxel Dörfler const ifaliasreq& request) 1177c22d69bfSAxel Dörfler { 117861729d93SAxel Dörfler // Make sure the family of the provided addresses is valid 117961729d93SAxel Dörfler if ((request.ifra_addr.ss_family != domain->family 118061729d93SAxel Dörfler && request.ifra_addr.ss_family != AF_UNSPEC) 118161729d93SAxel Dörfler || (request.ifra_mask.ss_family != domain->family 118261729d93SAxel Dörfler && request.ifra_mask.ss_family != AF_UNSPEC) 118361729d93SAxel Dörfler || (request.ifra_broadaddr.ss_family != domain->family 118461729d93SAxel Dörfler && request.ifra_broadaddr.ss_family != AF_UNSPEC)) 118561729d93SAxel Dörfler return B_BAD_VALUE; 1186c22d69bfSAxel Dörfler 118761729d93SAxel Dörfler RecursiveLocker locker(interface->Lock()); 118861729d93SAxel Dörfler 118961729d93SAxel Dörfler InterfaceAddress* address 119061729d93SAxel Dörfler = new(std::nothrow) InterfaceAddress(interface, domain); 119161729d93SAxel Dörfler if (address == NULL) 119261729d93SAxel Dörfler return B_NO_MEMORY; 119361729d93SAxel Dörfler 119461729d93SAxel Dörfler status_t status = address->SetTo(request); 119561729d93SAxel Dörfler if (status == B_OK) 119661729d93SAxel Dörfler status = interface->CreateDomainDatalinkIfNeeded(domain); 119761729d93SAxel Dörfler if (status == B_OK) 119861729d93SAxel Dörfler status = interface->AddAddress(address); 119961729d93SAxel Dörfler 120061729d93SAxel Dörfler if (status == B_OK && address->local != NULL) { 120161729d93SAxel Dörfler // update the datalink protocols 120261729d93SAxel Dörfler domain_datalink* datalink = interface->DomainDatalink(domain->family); 120361729d93SAxel Dörfler 120461729d93SAxel Dörfler status = datalink->first_protocol->module->change_address( 120561729d93SAxel Dörfler datalink->first_protocol, address, SIOCAIFADDR, NULL, 120661729d93SAxel Dörfler address->local); 120761729d93SAxel Dörfler if (status != B_OK) 120861729d93SAxel Dörfler interface->RemoveAddress(address); 120961729d93SAxel Dörfler } 121061729d93SAxel Dörfler if (status == B_OK) 121161729d93SAxel Dörfler notify_interface_changed(interface); 121261729d93SAxel Dörfler else 121361729d93SAxel Dörfler delete address; 121461729d93SAxel Dörfler 121561729d93SAxel Dörfler return status; 121661729d93SAxel Dörfler } 121761729d93SAxel Dörfler 121861729d93SAxel Dörfler 121961729d93SAxel Dörfler status_t 122061729d93SAxel Dörfler update_interface_address(InterfaceAddress* interfaceAddress, int32 option, 122161729d93SAxel Dörfler const sockaddr* oldAddress, const sockaddr* newAddress) 122261729d93SAxel Dörfler { 1223b0cf274aSAxel Dörfler TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress " 1224b0cf274aSAxel Dörfler "%s)\n", __FUNCTION__, interfaceAddress, option, 1225b0cf274aSAxel Dörfler AddressString(interfaceAddress->domain, oldAddress).Data(), 1226b0cf274aSAxel Dörfler AddressString(interfaceAddress->domain, newAddress).Data()); 1227b0cf274aSAxel Dörfler 122861729d93SAxel Dörfler MutexLocker locker(sHashLock); 122961729d93SAxel Dörfler 123061729d93SAxel Dörfler // set logical interface address 123161729d93SAxel Dörfler sockaddr** _address = interfaceAddress->AddressFor(option); 123261729d93SAxel Dörfler if (_address == NULL) 123361729d93SAxel Dörfler return B_BAD_VALUE; 123461729d93SAxel Dörfler 12352b1c0755SAxel Dörfler Interface* interface = (Interface*)interfaceAddress->interface; 12362b1c0755SAxel Dörfler 12372b1c0755SAxel Dörfler interfaceAddress->RemoveDefaultRoutes(option); 12382b1c0755SAxel Dörfler 12392b1c0755SAxel Dörfler if (option == SIOCDIFADDR) { 12402b1c0755SAxel Dörfler // Remove address, and release its reference (causing our caller to 12412b1c0755SAxel Dörfler // delete it) 12422b1c0755SAxel Dörfler locker.Unlock(); 12432b1c0755SAxel Dörfler 12442b1c0755SAxel Dörfler invalidate_routes(interfaceAddress); 12452b1c0755SAxel Dörfler 12462b1c0755SAxel Dörfler interface->RemoveAddress(interfaceAddress); 12472b1c0755SAxel Dörfler interfaceAddress->ReleaseReference(); 12482b1c0755SAxel Dörfler return B_OK; 12492b1c0755SAxel Dörfler } 12502b1c0755SAxel Dörfler 125161729d93SAxel Dörfler sAddressTable.Remove(interfaceAddress); 125261729d93SAxel Dörfler 125361729d93SAxel Dörfler // Copy new address over 125461729d93SAxel Dörfler status_t status = InterfaceAddress::Set(_address, newAddress); 125561729d93SAxel Dörfler if (status == B_OK) { 125661729d93SAxel Dörfler sockaddr* address = *_address; 125761729d93SAxel Dörfler 12581ebd87f4SAxel Dörfler if (option == SIOCSIFADDR) { 125961729d93SAxel Dörfler // Reset netmask and broadcast addresses to defaults 126061729d93SAxel Dörfler net_domain* domain = interfaceAddress->domain; 126161729d93SAxel Dörfler sockaddr* netmask = NULL; 126261729d93SAxel Dörfler const sockaddr* oldNetmask = NULL; 126361729d93SAxel Dörfler if (option == SIOCSIFADDR) { 126461729d93SAxel Dörfler netmask = InterfaceAddress::Prepare( 126561729d93SAxel Dörfler &interfaceAddress->mask, address->sa_len); 126661729d93SAxel Dörfler } else { 126761729d93SAxel Dörfler oldNetmask = oldAddress; 126861729d93SAxel Dörfler netmask = interfaceAddress->mask; 126961729d93SAxel Dörfler } 127061729d93SAxel Dörfler 127161729d93SAxel Dörfler // Reset the broadcast address if the address family has 127261729d93SAxel Dörfler // such 127361729d93SAxel Dörfler sockaddr* broadcast = NULL; 127461729d93SAxel Dörfler if ((domain->address_module->flags 127561729d93SAxel Dörfler & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) { 127661729d93SAxel Dörfler broadcast = InterfaceAddress::Prepare( 127761729d93SAxel Dörfler &interfaceAddress->destination, address->sa_len); 127861729d93SAxel Dörfler } else 127961729d93SAxel Dörfler InterfaceAddress::Set(&interfaceAddress->destination, NULL); 128061729d93SAxel Dörfler 128161729d93SAxel Dörfler domain->address_module->set_to_defaults(netmask, broadcast, 128261729d93SAxel Dörfler interfaceAddress->local, oldNetmask); 128361729d93SAxel Dörfler } 128461729d93SAxel Dörfler 12852b1c0755SAxel Dörfler interfaceAddress->AddDefaultRoutes(option); 12862b1c0755SAxel Dörfler notify_interface_changed(interface); 128761729d93SAxel Dörfler } 128861729d93SAxel Dörfler 128961729d93SAxel Dörfler sAddressTable.Insert(interfaceAddress); 129061729d93SAxel Dörfler return status; 129161729d93SAxel Dörfler } 129261729d93SAxel Dörfler 129361729d93SAxel Dörfler 129461729d93SAxel Dörfler Interface* 129561729d93SAxel Dörfler get_interface(net_domain* domain, uint32 index) 129661729d93SAxel Dörfler { 129761729d93SAxel Dörfler MutexLocker locker(sLock); 129861729d93SAxel Dörfler 129961729d93SAxel Dörfler if (index == 0) 130061729d93SAxel Dörfler return sInterfaces.First(); 130161729d93SAxel Dörfler 130261729d93SAxel Dörfler Interface* interface = find_interface(index); 1303c22d69bfSAxel Dörfler if (interface == NULL) 130461729d93SAxel Dörfler return NULL; 1305c22d69bfSAxel Dörfler 130661729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 130761729d93SAxel Dörfler return NULL; 130861729d93SAxel Dörfler 130961729d93SAxel Dörfler interface->AcquireReference(); 1310c22d69bfSAxel Dörfler return interface; 1311c22d69bfSAxel Dörfler } 1312c22d69bfSAxel Dörfler 131361729d93SAxel Dörfler 131461729d93SAxel Dörfler Interface* 131561729d93SAxel Dörfler get_interface(net_domain* domain, const char* name) 131661729d93SAxel Dörfler { 131761729d93SAxel Dörfler MutexLocker locker(sLock); 131861729d93SAxel Dörfler 131961729d93SAxel Dörfler Interface* interface = find_interface(name); 132061729d93SAxel Dörfler if (interface == NULL) 132161729d93SAxel Dörfler return NULL; 132261729d93SAxel Dörfler 132361729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 132461729d93SAxel Dörfler return NULL; 132561729d93SAxel Dörfler 132661729d93SAxel Dörfler interface->AcquireReference(); 132761729d93SAxel Dörfler return interface; 132861729d93SAxel Dörfler } 132961729d93SAxel Dörfler 133061729d93SAxel Dörfler 133161729d93SAxel Dörfler Interface* 133261729d93SAxel Dörfler get_interface_for_device(net_domain* domain, uint32 index) 133361729d93SAxel Dörfler { 133461729d93SAxel Dörfler MutexLocker locker(sLock); 133561729d93SAxel Dörfler 133661729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 133761729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 133861729d93SAxel Dörfler if (interface->device->index == index) { 133961729d93SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 134061729d93SAxel Dörfler return NULL; 134161729d93SAxel Dörfler 134261729d93SAxel Dörfler interface->AcquireReference(); 134361729d93SAxel Dörfler return interface; 134461729d93SAxel Dörfler } 134561729d93SAxel Dörfler } 134661729d93SAxel Dörfler 1347c22d69bfSAxel Dörfler return NULL; 1348c22d69bfSAxel Dörfler } 1349c22d69bfSAxel Dörfler 1350c22d69bfSAxel Dörfler 1351cd08b9f7SAxel Dörfler /*! Returns a reference to an Interface that matches the given \a linkAddress. 1352cd08b9f7SAxel Dörfler The link address is checked against its hardware address, or its interface 1353cd08b9f7SAxel Dörfler name, or finally the interface index. 1354cd08b9f7SAxel Dörfler */ 1355cd08b9f7SAxel Dörfler Interface* 1356cd08b9f7SAxel Dörfler get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) 1357cd08b9f7SAxel Dörfler { 1358cd08b9f7SAxel Dörfler sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress; 1359cd08b9f7SAxel Dörfler 1360cd08b9f7SAxel Dörfler MutexLocker locker(sLock); 1361cd08b9f7SAxel Dörfler 1362cd08b9f7SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 1363cd08b9f7SAxel Dörfler while (Interface* interface = iterator.Next()) { 1364cd08b9f7SAxel Dörfler // Test if the hardware address matches, or if the given interface 1365cd08b9f7SAxel Dörfler // matches, or if at least the index matches. 1366cd08b9f7SAxel Dörfler if ((linkAddress.sdl_alen == interface->device->address.length 1367cd08b9f7SAxel Dörfler && memcmp(LLADDR(&linkAddress), interface->device->address.data, 1368cd08b9f7SAxel Dörfler linkAddress.sdl_alen) == 0) 1369cd08b9f7SAxel Dörfler || (linkAddress.sdl_nlen > 0 1370cd08b9f7SAxel Dörfler && !strcmp(interface->name, (const char*)linkAddress.sdl_data)) 1371cd08b9f7SAxel Dörfler || (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0 1372cd08b9f7SAxel Dörfler && linkAddress.sdl_index == interface->index)) { 1373cd08b9f7SAxel Dörfler if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) 1374cd08b9f7SAxel Dörfler return NULL; 1375cd08b9f7SAxel Dörfler 1376cd08b9f7SAxel Dörfler interface->AcquireReference(); 1377cd08b9f7SAxel Dörfler return interface; 1378cd08b9f7SAxel Dörfler } 1379cd08b9f7SAxel Dörfler } 1380cd08b9f7SAxel Dörfler 1381cd08b9f7SAxel Dörfler return NULL; 1382cd08b9f7SAxel Dörfler } 1383cd08b9f7SAxel Dörfler 1384cd08b9f7SAxel Dörfler 138561729d93SAxel Dörfler InterfaceAddress* 138661729d93SAxel Dörfler get_interface_address(const sockaddr* local) 1387c22d69bfSAxel Dörfler { 138861729d93SAxel Dörfler if (local->sa_family == AF_UNSPEC) 138961729d93SAxel Dörfler return NULL; 1390c22d69bfSAxel Dörfler 139161729d93SAxel Dörfler MutexLocker locker(sHashLock); 1392c22d69bfSAxel Dörfler 139361729d93SAxel Dörfler InterfaceAddress* address = sAddressTable.Lookup(local); 139461729d93SAxel Dörfler if (address == NULL) 139561729d93SAxel Dörfler return NULL; 1396c22d69bfSAxel Dörfler 139761729d93SAxel Dörfler address->AcquireReference(); 139861729d93SAxel Dörfler return address; 139961729d93SAxel Dörfler } 140061729d93SAxel Dörfler 140161729d93SAxel Dörfler 140261729d93SAxel Dörfler InterfaceAddress* 140361729d93SAxel Dörfler get_interface_address_for_destination(net_domain* domain, 1404cd08b9f7SAxel Dörfler const sockaddr* destination) 140561729d93SAxel Dörfler { 140661729d93SAxel Dörfler MutexLocker locker(sLock); 140761729d93SAxel Dörfler 140861729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 140961729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 141061729d93SAxel Dörfler InterfaceAddress* address 141161729d93SAxel Dörfler = interface->AddressForDestination(domain, destination); 141261729d93SAxel Dörfler if (address != NULL) 141361729d93SAxel Dörfler return address; 141461729d93SAxel Dörfler } 141561729d93SAxel Dörfler 141661729d93SAxel Dörfler return NULL; 141761729d93SAxel Dörfler } 141861729d93SAxel Dörfler 141961729d93SAxel Dörfler 1420cd08b9f7SAxel Dörfler /*! Returns a reference to an InterfaceAddress of the specified \a domain that 1421cd08b9f7SAxel Dörfler belongs to the interface identified via \a linkAddress. Only the hardware 1422cd08b9f7SAxel Dörfler address is matched. 1423cd08b9f7SAxel Dörfler 1424cd08b9f7SAxel Dörfler If \a unconfiguredOnly is set, the interface address must not yet be 1425cd08b9f7SAxel Dörfler configured, or must currently be in the process of being configured. 1426cd08b9f7SAxel Dörfler */ 142761729d93SAxel Dörfler InterfaceAddress* 1428cd08b9f7SAxel Dörfler get_interface_address_for_link(net_domain* domain, const sockaddr* address, 1429cd08b9f7SAxel Dörfler bool unconfiguredOnly) 143061729d93SAxel Dörfler { 1431cd08b9f7SAxel Dörfler sockaddr_dl& linkAddress = *(sockaddr_dl*)address; 143261729d93SAxel Dörfler 143361729d93SAxel Dörfler MutexLocker locker(sLock); 143461729d93SAxel Dörfler 143561729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 143661729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1437cd08b9f7SAxel Dörfler // Test if the hardware address matches, or if the given interface 1438cd08b9f7SAxel Dörfler // matches, or if at least the index matches. 143961729d93SAxel Dörfler if (linkAddress.sdl_alen == interface->device->address.length 144061729d93SAxel Dörfler && memcmp(LLADDR(&linkAddress), interface->device->address.data, 144161729d93SAxel Dörfler linkAddress.sdl_alen) == 0) { 1442b0cf274aSAxel Dörfler TRACE(" %s matches\n", interface->name); 144361729d93SAxel Dörfler // link address matches 144461729d93SAxel Dörfler if (unconfiguredOnly) 144561729d93SAxel Dörfler return interface->FirstUnconfiguredForFamily(domain->family); 144661729d93SAxel Dörfler 144761729d93SAxel Dörfler return interface->FirstForFamily(domain->family); 144861729d93SAxel Dörfler } 144961729d93SAxel Dörfler } 145061729d93SAxel Dörfler 145161729d93SAxel Dörfler return NULL; 1452c22d69bfSAxel Dörfler } 1453c22d69bfSAxel Dörfler 1454c22d69bfSAxel Dörfler 1455c22d69bfSAxel Dörfler uint32 145661729d93SAxel Dörfler count_interfaces() 1457c22d69bfSAxel Dörfler { 145861729d93SAxel Dörfler MutexLocker locker(sLock); 1459c22d69bfSAxel Dörfler 146061729d93SAxel Dörfler return sInterfaces.Count(); 1461c22d69bfSAxel Dörfler } 1462c22d69bfSAxel Dörfler 1463c22d69bfSAxel Dörfler 14643c13a5f5SAxel Dörfler /*! Dumps a list of all interfaces into the supplied userland buffer. 1465c22d69bfSAxel Dörfler If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is 1466c22d69bfSAxel Dörfler returned. 1467c22d69bfSAxel Dörfler */ 1468c22d69bfSAxel Dörfler status_t 146961729d93SAxel Dörfler list_interfaces(int family, void* _buffer, size_t* bufferSize) 1470c22d69bfSAxel Dörfler { 147161729d93SAxel Dörfler MutexLocker locker(sLock); 1472c22d69bfSAxel Dörfler 1473409b1fc0SHugo Santos UserBuffer buffer(_buffer, *bufferSize); 1474c22d69bfSAxel Dörfler 147561729d93SAxel Dörfler InterfaceList::Iterator iterator = sInterfaces.GetIterator(); 147661729d93SAxel Dörfler while (Interface* interface = iterator.Next()) { 1477715fed44SAxel Dörfler // Copy name 1478715fed44SAxel Dörfler buffer.Push(interface->name, IF_NAMESIZE); 1479c22d69bfSAxel Dörfler 1480715fed44SAxel Dörfler // Copy address 148161729d93SAxel Dörfler InterfaceAddress* address = interface->FirstForFamily(family); 14821f9c8c45SAxel Dörfler size_t length = 0; 1483715fed44SAxel Dörfler 148461729d93SAxel Dörfler if (address != NULL && address->local != NULL) { 1485715fed44SAxel Dörfler // Actual address 14861f9c8c45SAxel Dörfler buffer.Push(address->local, length = address->local->sa_len); 148761729d93SAxel Dörfler } else { 1488715fed44SAxel Dörfler // Empty address 14891f9c8c45SAxel Dörfler sockaddr empty; 14901f9c8c45SAxel Dörfler empty.sa_len = 2; 14911f9c8c45SAxel Dörfler empty.sa_family = AF_UNSPEC; 14921f9c8c45SAxel Dörfler buffer.Push(&empty, length = empty.sa_len); 1493715fed44SAxel Dörfler } 1494715fed44SAxel Dörfler 149561729d93SAxel Dörfler if (address != NULL) 149661729d93SAxel Dörfler address->ReleaseReference(); 149761729d93SAxel Dörfler 14981f9c8c45SAxel Dörfler if (IF_NAMESIZE + length < sizeof(ifreq)) { 14991f9c8c45SAxel Dörfler // Make sure at least sizeof(ifreq) bytes are written for each 15001f9c8c45SAxel Dörfler // interface for compatibility with other platforms 15011f9c8c45SAxel Dörfler buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length); 15021f9c8c45SAxel Dörfler } 15031f9c8c45SAxel Dörfler 15041f9c8c45SAxel Dörfler if (buffer.Status() != B_OK) 1505409b1fc0SHugo Santos return buffer.Status(); 1506c22d69bfSAxel Dörfler } 1507c22d69bfSAxel Dörfler 1508715fed44SAxel Dörfler *bufferSize = buffer.BytesConsumed(); 1509c22d69bfSAxel Dörfler return B_OK; 1510c22d69bfSAxel Dörfler } 1511c22d69bfSAxel Dörfler 1512c22d69bfSAxel Dörfler 1513c22d69bfSAxel Dörfler // #pragma mark - 1514c22d69bfSAxel Dörfler 1515c22d69bfSAxel Dörfler 1516c22d69bfSAxel Dörfler status_t 1517c22d69bfSAxel Dörfler init_interfaces() 1518c22d69bfSAxel Dörfler { 151961729d93SAxel Dörfler mutex_init(&sLock, "net interfaces"); 152061729d93SAxel Dörfler mutex_init(&sHashLock, "net local addresses"); 1521c22d69bfSAxel Dörfler 152261729d93SAxel Dörfler new (&sInterfaces) InterfaceList; 152361729d93SAxel Dörfler new (&sAddressTable) AddressTable; 15249206bb37SAxel Dörfler // static C++ objects are not initialized in the module startup 1525a3ec278aSAxel Dörfler 1526a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 1527a3ec278aSAxel Dörfler add_debugger_command("net_interface", &dump_interface, 1528a3ec278aSAxel Dörfler "Dump the given network interface"); 152961729d93SAxel Dörfler add_debugger_command("net_interfaces", &dump_interfaces, 153061729d93SAxel Dörfler "Dump all network interfaces"); 153161729d93SAxel Dörfler add_debugger_command("net_local", &dump_local, 153261729d93SAxel Dörfler "Dump all local interface addresses"); 153361729d93SAxel Dörfler add_debugger_command("net_route", &dump_route, 153461729d93SAxel Dörfler "Dump the given network route"); 1535a3ec278aSAxel Dörfler #endif 1536c22d69bfSAxel Dörfler return B_OK; 1537c22d69bfSAxel Dörfler } 1538c22d69bfSAxel Dörfler 1539c22d69bfSAxel Dörfler 1540c22d69bfSAxel Dörfler status_t 1541c22d69bfSAxel Dörfler uninit_interfaces() 1542c22d69bfSAxel Dörfler { 1543a3ec278aSAxel Dörfler #if ENABLE_DEBUGGER_COMMANDS 1544a3ec278aSAxel Dörfler remove_debugger_command("net_interface", &dump_interface); 1545a3ec278aSAxel Dörfler #endif 1546a3ec278aSAxel Dörfler 154761729d93SAxel Dörfler mutex_destroy(&sLock); 154861729d93SAxel Dörfler mutex_destroy(&sHashLock); 1549c22d69bfSAxel Dörfler return B_OK; 1550c22d69bfSAxel Dörfler } 1551c22d69bfSAxel Dörfler 1552