From a89dbefb7d8e3747b6b8582c9cecb7664b1376b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 15 Aug 2010 10:39:39 +0000 Subject: [PATCH] * On change_address(), arp_remove_local_enty() must not switch to the address that caused the change (but that has not actually been changed yet). * Also, it will now reset the INADDR_ANY local address in case there is no other address configured. This should help with automatic configuring after deletion of an interface address (though it doesn't seem to work yet for some other reason, at least in VMware). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38110 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../network/datalink_protocols/arp/arp.cpp | 126 +++++++++--------- 1 file changed, 66 insertions(+), 60 deletions(-) diff --git a/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp b/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp index 0240a5483f..765c1a97f3 100644 --- a/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp +++ b/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp @@ -436,65 +436,6 @@ arp_update_entry(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress, } -static void -arp_remove_local_entry(arp_protocol* protocol, const sockaddr* local, - bool updateLocalAddress) -{ - in_addr_t inetAddress; - - if (local == NULL) { - // interface has not yet been set - inetAddress = INADDR_ANY; - } else - inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr; - - TRACE(("%s(): address %s\n", __FUNCTION__, inet_to_string(inetAddress))); - - MutexLocker locker(sCacheLock); - - arp_entry* entry = arp_entry::Lookup(inetAddress); - if (entry != NULL) { - hash_remove(sCache, entry); - entry->flags |= ARP_FLAG_REMOVED; - } - - if (updateLocalAddress && protocol->local_address == inetAddress) { - // find new local sender address - protocol->local_address = 0; - - net_interface_address* address = NULL; - while (sDatalinkModule->get_next_interface_address(protocol->interface, - &address)) { - if (address->local == NULL || address->local->sa_family != AF_INET) - continue; - - protocol->local_address - = ((sockaddr_in*)address->local)->sin_addr.s_addr; - } - } - - locker.Unlock(); - delete entry; -} - - -/*! Removes all entries belonging to the local interface of the \a procotol - given. -*/ -static void -arp_remove_local(arp_protocol* protocol) -{ - net_interface_address* address = NULL; - while (sDatalinkModule->get_next_interface_address(protocol->interface, - &address)) { - if (address->local == NULL || address->local->sa_family != AF_INET) - continue; - - arp_remove_local_entry(protocol, address->local, false); - } -} - - static status_t arp_set_local_entry(arp_protocol* protocol, const sockaddr* local) { @@ -537,6 +478,71 @@ arp_set_local_entry(arp_protocol* protocol, const sockaddr* local) } +static void +arp_remove_local_entry(arp_protocol* protocol, const sockaddr* local, + net_interface_address* updateLocalAddress = NULL) +{ + in_addr_t inetAddress; + + if (local == NULL) { + // interface has not yet been set + inetAddress = INADDR_ANY; + } else + inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr; + + TRACE(("%s(): address %s\n", __FUNCTION__, inet_to_string(inetAddress))); + + MutexLocker locker(sCacheLock); + + arp_entry* entry = arp_entry::Lookup(inetAddress); + if (entry != NULL) { + hash_remove(sCache, entry); + entry->flags |= ARP_FLAG_REMOVED; + } + + if (updateLocalAddress != NULL && protocol->local_address == inetAddress) { + // find new local sender address + protocol->local_address = 0; + + net_interface_address* address = NULL; + while (sDatalinkModule->get_next_interface_address(protocol->interface, + &address)) { + if (address == updateLocalAddress || address->local == NULL + || address->local->sa_family != AF_INET) + continue; + + protocol->local_address + = ((sockaddr_in*)address->local)->sin_addr.s_addr; + } + } + + locker.Unlock(); + delete entry; + + if (protocol->local_address == 0 && updateLocalAddress) { + // Try to keep the interface operational + arp_set_local_entry(protocol, NULL); + } +} + + +/*! Removes all entries belonging to the local interface of the \a procotol + given. +*/ +static void +arp_remove_local(arp_protocol* protocol) +{ + net_interface_address* address = NULL; + while (sDatalinkModule->get_next_interface_address(protocol->interface, + &address)) { + if (address->local == NULL || address->local->sa_family != AF_INET) + continue; + + arp_remove_local_entry(protocol, address->local); + } +} + + /*! Creates permanent local entries for all addresses of the interface belonging to this protocol. Returns an error if no entry could be added. @@ -1130,7 +1136,7 @@ arp_change_address(net_datalink_protocol* _protocol, if (option != SIOCAIFADDR && (oldAddress == NULL || oldAddress->sa_family == AF_INET)) - arp_remove_local_entry(protocol, oldAddress, true); + arp_remove_local_entry(protocol, oldAddress, address); } break;