/*! Returns a reference to an InterfaceAddress of the specified \a domain that belongs to the interface identified via \a linkAddress. Only the hardware address is matched. If \a unconfiguredOnly is set, the interface address must not yet be configured, or must currently be in the process of being configured. */ InterfaceAddress* get_interface_address_for_link(net_domain* domain, const sockaddr* address, bool unconfiguredOnly) { sockaddr_dl& linkAddress = *(sockaddr_dl*)address; RecursiveLocker locker(sLock); InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { if (interface->IsBusy()) continue; // Test if the hardware address matches, or if the given interface // matches, or if at least the index matches. if (linkAddress.sdl_alen == interface->device->address.length && memcmp(LLADDR(&linkAddress), interface->device->address.data, linkAddress.sdl_alen) == 0) { TRACE(" %s matches\n", interface->name); // link address matches if (unconfiguredOnly) return interface->FirstUnconfiguredForFamily(domain->family); return interface->FirstForFamily(domain->family); } } return NULL; }
/*! Returns a reference to an Interface that matches the given \a linkAddress. The link address is checked against its hardware address, or its interface name, or finally the interface index. */ Interface* get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) { sockaddr_dl& linkAddress = *(sockaddr_dl*)_linkAddress; RecursiveLocker locker(sLock); InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { if (interface->IsBusy()) continue; // Test if the hardware address matches, or if the given interface // matches, or if at least the index matches. if ((linkAddress.sdl_alen == interface->device->address.length && memcmp(LLADDR(&linkAddress), interface->device->address.data, linkAddress.sdl_alen) == 0) || (linkAddress.sdl_nlen > 0 && !strcmp(interface->name, (const char*)linkAddress.sdl_data)) || (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0 && linkAddress.sdl_index == interface->index)) { if (interface->IsBusy()) return NULL; if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) return NULL; interface->AcquireReference(); return interface; } } return NULL; }
static int dump_interfaces(int argc, char** argv) { InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { kprintf("%p %s\n", interface, interface->name); } return 0; }
//! For debugging purposes only void dump_interface_refs(void) { RecursiveLocker locker(sLock); InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { dprintf("%p: %s, %ld\n", interface, interface->name, interface->CountReferences()); } }
/*! Searches for a specific interface by index. You need to have the interface list's lock hold when calling this function. */ static struct Interface* find_interface(uint32 index) { InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { if (interface->index == index) return interface; } return NULL; }
/*! Searches for a specific interface by name. You need to have the interface list's lock hold when calling this function. */ static struct Interface* find_interface(const char* name) { ASSERT_LOCKED_RECURSIVE(&sLock); InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { if (!strcmp(interface->name, name)) return interface; } return NULL; }
/*! Dumps a list of all interfaces into the supplied userland buffer. If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is returned. */ status_t list_interfaces(int family, void* _buffer, size_t* bufferSize) { RecursiveLocker locker(sLock); UserBuffer buffer(_buffer, *bufferSize); InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { // Copy name buffer.Push(interface->name, IF_NAMESIZE); // Copy address InterfaceAddress* address = interface->FirstForFamily(family); size_t length = 0; if (address != NULL && address->local != NULL) { // Actual address buffer.Push(address->local, length = address->local->sa_len); } else { // Empty address sockaddr empty; empty.sa_len = 2; empty.sa_family = AF_UNSPEC; buffer.Push(&empty, length = empty.sa_len); } if (address != NULL) address->ReleaseReference(); if (IF_NAMESIZE + length < sizeof(ifreq)) { // Make sure at least sizeof(ifreq) bytes are written for each // interface for compatibility with other platforms buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - length); } if (buffer.Status() != B_OK) return buffer.Status(); } *bufferSize = buffer.BytesConsumed(); return B_OK; }
InterfaceAddress* get_interface_address_for_destination(net_domain* domain, const sockaddr* destination) { RecursiveLocker locker(sLock); InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { if (interface->IsBusy()) continue; InterfaceAddress* address = interface->AddressForDestination(domain, destination); if (address != NULL) return address; } return NULL; }
Interface* get_interface_for_device(net_domain* domain, uint32 index) { RecursiveLocker locker(sLock); InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { if (interface->device->index == index) { if (interface->IsBusy()) return NULL; if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) return NULL; interface->AcquireReference(); return interface; } } return NULL; }
static int dump_interface(int argc, char** argv) { if (argc != 2) { kprintf("usage: %s [name|address]\n", argv[0]); return 0; } Interface* interface = NULL; InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while ((interface = iterator.Next()) != NULL) { if (!strcmp(argv[1], interface->name)) break; } if (interface == NULL) interface = (Interface*)parse_expression(argv[1]); interface->Dump(); return 0; }