From 910ffb32fee4d6e04cd47f915a0e4e5292e05e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 12 Aug 2010 13:25:45 +0000 Subject: [PATCH] * If the network mask, and broadcast are not specified with a B_SOCKET_SET_ALIAS they will no longer be unset - instead they are set with defaults. * If B_SOCKET_SET_ALIAS gets an index of -1, it will now try to find the local address, and if that fails, will just use the first address there is. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38053 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/network/stack/interfaces.cpp | 46 +++++++++++++++++-- src/add-ons/kernel/network/stack/interfaces.h | 2 + 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/add-ons/kernel/network/stack/interfaces.cpp b/src/add-ons/kernel/network/stack/interfaces.cpp index bd55c0f3a6..da9148a92f 100644 --- a/src/add-ons/kernel/network/stack/interfaces.cpp +++ b/src/add-ons/kernel/network/stack/interfaces.cpp @@ -535,6 +535,28 @@ Interface::AddressForDestination(net_domain* domain, } +/*! Returns a reference to the InterfaceAddress that has the specified + \a local address. +*/ +InterfaceAddress* +Interface::AddressForLocal(net_domain* domain, const sockaddr* local) +{ + RecursiveLocker locker(fLock); + + AddressList::Iterator iterator = fAddresses.GetIterator(); + while (InterfaceAddress* address = iterator.Next()) { + if (address->domain == domain + && address->local != NULL + && domain->address_module->equal_addresses(address->local, local)) { + address->AcquireReference(); + return address; + } + } + + return NULL; +} + + status_t Interface::AddAddress(InterfaceAddress* address) { @@ -690,7 +712,21 @@ Interface::Control(net_domain* domain, int32 option, ifreq& request, != B_OK) return B_BAD_ADDRESS; - InterfaceAddress* address = AddressAt(aliasRequest.ifra_index); + InterfaceAddress* address = NULL; + if (aliasRequest.ifra_index < 0) { + if (!domain->address_module->is_empty_address( + (const sockaddr*)&aliasRequest.ifra_addr, false)) { + // Find first address that matches the local address + address = AddressForLocal(domain, + (const sockaddr*)&aliasRequest.ifra_addr); + } + if (address == NULL) { + // Find first address for family + address = FirstForFamily(domain->family); + } + } else + address = AddressAt(aliasRequest.ifra_index); + if (address == NULL) return B_BAD_VALUE; @@ -706,14 +742,18 @@ Interface::Control(net_domain* domain, int32 option, ifreq& request, } if (status == B_OK && !domain->address_module->equal_addresses( - (sockaddr*)&aliasRequest.ifra_mask, address->mask)) { + (sockaddr*)&aliasRequest.ifra_mask, address->mask) + && !domain->address_module->is_empty_address( + (sockaddr*)&aliasRequest.ifra_mask, false)) { status = _ChangeAddress(locker, address, SIOCSIFNETMASK, address->mask, (sockaddr*)&aliasRequest.ifra_mask); } if (status == B_OK && !domain->address_module->equal_addresses( (sockaddr*)&aliasRequest.ifra_destination, - address->destination)) { + address->destination) + && !domain->address_module->is_empty_address( + (sockaddr*)&aliasRequest.ifra_destination, false)) { status = _ChangeAddress(locker, address, (domain->address_module->flags & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0 diff --git a/src/add-ons/kernel/network/stack/interfaces.h b/src/add-ons/kernel/network/stack/interfaces.h index 5eaeccd3aa..8acde84739 100644 --- a/src/add-ons/kernel/network/stack/interfaces.h +++ b/src/add-ons/kernel/network/stack/interfaces.h @@ -122,6 +122,8 @@ public: InterfaceAddress* FirstUnconfiguredForFamily(int family); InterfaceAddress* AddressForDestination(net_domain* domain, const sockaddr* destination); + InterfaceAddress* AddressForLocal(net_domain* domain, + const sockaddr* local); status_t AddAddress(InterfaceAddress* address); void RemoveAddress(InterfaceAddress* address);