[haiku-commits] r38110 - haiku/trunk/src/add-ons/kernel/network/datalink_protocols/arp

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 15 Aug 2010 12:39:39 +0200 (CEST)

Author: axeld
Date: 2010-08-15 12:39:39 +0200 (Sun, 15 Aug 2010)
New Revision: 38110
Changeset: http://dev.haiku-os.org/changeset/38110

Modified:
   haiku/trunk/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp
Log:
* 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).


Modified: haiku/trunk/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp       
2010-08-15 10:17:42 UTC (rev 38109)
+++ haiku/trunk/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp       
2010-08-15 10:39:39 UTC (rev 38110)
@@ -436,9 +436,51 @@
 }
 
 
+static status_t
+arp_set_local_entry(arp_protocol* protocol, const sockaddr* local)
+{
+       MutexLocker locker(sCacheLock);
+
+       net_interface* interface = protocol->interface;
+       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)));
+
+       if (protocol->local_address == 0)
+               protocol->local_address = inetAddress;
+
+       sockaddr_dl address;
+       address.sdl_len = sizeof(sockaddr_dl);
+       address.sdl_family = AF_LINK;
+       address.sdl_type = IFT_ETHER;
+       address.sdl_e_type = ETHER_TYPE_IP;
+       address.sdl_nlen = 0;
+       address.sdl_slen = 0;
+       address.sdl_alen = interface->device->address.length;
+       memcpy(LLADDR(&address), interface->device->address.data, 
address.sdl_alen);
+
+       memcpy(&protocol->hardware_address, &address, sizeof(sockaddr_dl));
+               // cache the address in our protocol
+
+       arp_entry* entry;
+       status_t status = arp_update_entry(inetAddress, &address,
+               ARP_FLAG_LOCAL | ARP_FLAG_PERMANENT, &entry);
+       if (status == B_OK)
+               entry->protocol = protocol;
+
+       return status;
+}
+
+
 static void
 arp_remove_local_entry(arp_protocol* protocol, const sockaddr* local,
-       bool updateLocalAddress)
+       net_interface_address* updateLocalAddress = NULL)
 {
        in_addr_t inetAddress;
 
@@ -458,14 +500,15 @@
                entry->flags |= ARP_FLAG_REMOVED;
        }
 
-       if (updateLocalAddress && protocol->local_address == inetAddress) {
+       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->local == NULL || address->local->sa_family 
!= AF_INET)
+                       if (address == updateLocalAddress || address->local == 
NULL
+                               || address->local->sa_family != AF_INET)
                                continue;
 
                        protocol->local_address
@@ -475,6 +518,11 @@
 
        locker.Unlock();
        delete entry;
+
+       if (protocol->local_address == 0 && updateLocalAddress) {
+               // Try to keep the interface operational
+               arp_set_local_entry(protocol, NULL);
+       }
 }
 
 
@@ -490,53 +538,11 @@
                if (address->local == NULL || address->local->sa_family != 
AF_INET)
                        continue;
 
-               arp_remove_local_entry(protocol, address->local, false);
+               arp_remove_local_entry(protocol, address->local);
        }
 }
 
 
-static status_t
-arp_set_local_entry(arp_protocol* protocol, const sockaddr* local)
-{
-       MutexLocker locker(sCacheLock);
-
-       net_interface* interface = protocol->interface;
-       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)));
-
-       if (protocol->local_address == 0)
-               protocol->local_address = inetAddress;
-
-       sockaddr_dl address;
-       address.sdl_len = sizeof(sockaddr_dl);
-       address.sdl_family = AF_LINK;
-       address.sdl_type = IFT_ETHER;
-       address.sdl_e_type = ETHER_TYPE_IP;
-       address.sdl_nlen = 0;
-       address.sdl_slen = 0;
-       address.sdl_alen = interface->device->address.length;
-       memcpy(LLADDR(&address), interface->device->address.data, 
address.sdl_alen);
-
-       memcpy(&protocol->hardware_address, &address, sizeof(sockaddr_dl));
-               // cache the address in our protocol
-
-       arp_entry* entry;
-       status_t status = arp_update_entry(inetAddress, &address,
-               ARP_FLAG_LOCAL | ARP_FLAG_PERMANENT, &entry);
-       if (status == B_OK)
-               entry->protocol = protocol;
-
-       return status;
-}
-
-
 /*!    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 @@
 
                                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;
 


Other related posts:

  • » [haiku-commits] r38110 - haiku/trunk/src/add-ons/kernel/network/datalink_protocols/arp - axeld