status_t Interface::AddAddress(InterfaceAddress* address) { net_domain* domain = address->domain; if (domain == NULL) return B_BAD_VALUE; RecursiveLocker locker(fLock); fAddresses.Add(address); locker.Unlock(); if (address->LocalIsDefined()) { MutexLocker hashLocker(sHashLock); sAddressTable.Insert(address); } return B_OK; }
status_t update_interface_address(InterfaceAddress* interfaceAddress, int32 option, const sockaddr* oldAddress, const sockaddr* newAddress) { TRACE("%s(address %p, option %" B_PRId32 ", oldAddress %s, newAddress " "%s)\n", __FUNCTION__, interfaceAddress, option, AddressString(interfaceAddress->domain, oldAddress).Data(), AddressString(interfaceAddress->domain, newAddress).Data()); MutexLocker locker(sHashLock); // set logical interface address sockaddr** _address = interfaceAddress->AddressFor(option); if (_address == NULL) return B_BAD_VALUE; Interface* interface = (Interface*)interfaceAddress->interface; interfaceAddress->RemoveDefaultRoutes(option); if (option == SIOCDIFADDR) { // Remove address, and release its reference (causing our caller to // delete it) locker.Unlock(); invalidate_routes(interfaceAddress); interface->RemoveAddress(interfaceAddress); interfaceAddress->ReleaseReference(); return B_OK; } if (interfaceAddress->LocalIsDefined()) sAddressTable.Remove(interfaceAddress); // Copy new address over status_t status = InterfaceAddress::Set(_address, newAddress); if (status == B_OK) { sockaddr* address = *_address; if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) { // Reset netmask and broadcast addresses to defaults net_domain* domain = interfaceAddress->domain; sockaddr* defaultNetmask = NULL; const sockaddr* netmask = NULL; if (option == SIOCSIFADDR) { defaultNetmask = InterfaceAddress::Prepare( &interfaceAddress->mask, address->sa_len); } else netmask = newAddress; // Reset the broadcast address if the address family has // such sockaddr* defaultBroadcast = NULL; if ((domain->address_module->flags & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) { defaultBroadcast = InterfaceAddress::Prepare( &interfaceAddress->destination, address->sa_len); } else InterfaceAddress::Set(&interfaceAddress->destination, NULL); domain->address_module->set_to_defaults(defaultNetmask, defaultBroadcast, interfaceAddress->local, netmask); } interfaceAddress->AddDefaultRoutes(option); notify_interface_changed(interface); } if (interfaceAddress->LocalIsDefined()) sAddressTable.Insert(interfaceAddress); return status; }