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