[haiku-commits] r41285 - haiku/trunk/src/servers/net

  • From: philippe.houdoin@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 27 Apr 2011 17:04:55 +0200 (CEST)

Author: phoudoin
Date: 2011-04-27 17:04:55 +0200 (Wed, 27 Apr 2011)
New Revision: 41285
Changeset: https://dev.haiku-os.org/changeset/41285
Ticket: https://dev.haiku-os.org/ticket/7346

Modified:
   haiku/trunk/src/servers/net/AutoconfigLooper.cpp
   haiku/trunk/src/servers/net/DHCPClient.cpp
   haiku/trunk/src/servers/net/DHCPClient.h
   haiku/trunk/src/servers/net/NetServer.cpp
Log:
Implemented INIT-REBOOT DHCP state: as required per DHCP specs,
we now request the last address we got from DHCP server, and only on failure
we fallback on the whole INIT state (discover, collect offer, etc).
This should fix people losing their IP address at each renewal, or far worse,
after the link goes up again.
Closed #7346.


Modified: haiku/trunk/src/servers/net/AutoconfigLooper.cpp
===================================================================
--- haiku/trunk/src/servers/net/AutoconfigLooper.cpp    2011-04-27 05:11:21 UTC 
(rev 41284)
+++ haiku/trunk/src/servers/net/AutoconfigLooper.cpp    2011-04-27 15:04:55 UTC 
(rev 41285)
@@ -58,21 +58,19 @@
 void
 AutoconfigLooper::_Configure()
 {
+       // start with DHCP
+       
+       if (fCurrentClient == NULL) {
+               fCurrentClient = new DHCPClient(fTarget, fDevice.String());
+               AddHandler(fCurrentClient);
+       }
+       
        // set IFF_CONFIGURING flag on interface
 
        BNetworkInterface interface(fDevice.String());
        int32 flags = interface.Flags() & ~IFF_AUTO_CONFIGURED;
        interface.SetFlags(flags | IFF_CONFIGURING);
 
-       // remove current handler
-
-       _RemoveClient();
-
-       // start with DHCP
-
-       fCurrentClient = new DHCPClient(fTarget, fDevice.String());
-       AddHandler(fCurrentClient);
-
        if (fCurrentClient->Initialize() == B_OK)
                return;
 
@@ -91,7 +89,7 @@
 
        BMessage message(kMsgConfigureInterface);
        message.AddString("device", fDevice.String());
-       message.AddBool("auto", true);
+       message.AddBool("auto_configured", true);
 
        BNetworkAddress link;
        uint8 last = 56;

Modified: haiku/trunk/src/servers/net/DHCPClient.cpp
===================================================================
--- haiku/trunk/src/servers/net/DHCPClient.cpp  2011-04-27 05:11:21 UTC (rev 
41284)
+++ haiku/trunk/src/servers/net/DHCPClient.cpp  2011-04-27 15:04:55 UTC (rev 
41285)
@@ -422,6 +422,7 @@
        fConfiguration(kMsgConfigureInterface),
        fResolverConfiguration(kMsgConfigureResolver),
        fRunner(NULL),
+       fAssignedAddress(0),
        fServer(AF_INET, NULL, DHCP_SERVER_PORT),
        fLeaseTime(0)
 {
@@ -436,6 +437,18 @@
 
        memcpy(fMAC, link.LinkLevelAddress(), sizeof(fMAC));
 
+       if ((interface.Flags() & IFF_AUTO_CONFIGURED) != 0) {
+               // Check for interface previous auto-configured address, if any.
+               BNetworkInterfaceAddress interfaceAddress;
+               int index = interface.FindFirstAddress(AF_INET);
+               if (index >= 0
+                       && interface.GetAddressAt(index, interfaceAddress) == 
B_OK) {
+                       BNetworkAddress address = interfaceAddress.Address();
+                       const sockaddr_in& addr = 
(sockaddr_in&)address.SockAddr();
+                       fAssignedAddress = addr.sin_addr.s_addr;
+               }
+       }
+
        openlog_thread("DHCP", 0, LOG_DAEMON);
 }
 
@@ -466,8 +479,8 @@
 status_t
 DHCPClient::Initialize()
 {
-       fStatus = _Negotiate(INIT);
-       syslog(LOG_DEBUG, "DHCP for %s, status: %s\n", Device(), 
strerror(fStatus));
+       fStatus = _Negotiate(fAssignedAddress == 0 ? INIT : INIT_REBOOT);
+       syslog(LOG_DEBUG, "%s: DHCP status = %s\n", Device(), 
strerror(fStatus));
        return fStatus;
 }
 
@@ -527,13 +540,13 @@
 
        // send discover/request message
        _SendMessage(socket, state == INIT ? discover : request,
-               state != RENEWAL ? broadcast : fServer);
+               state != RENEWING ? broadcast : fServer);
                // no need to check the status; in case of an error we'll just 
send
                // the message again
 
        // receive loop until we've got an offer and acknowledged it
 
-       while (state != ACKNOWLEDGED) {
+       while (state != BOUND) {
                char buffer[2048];
                struct sockaddr_in from;
                socklen_t fromLength = sizeof(from);
@@ -546,12 +559,8 @@
                                return B_TIMED_OUT;
                        }
 
-                       if (state == INIT)
-                               _SendMessage(socket, discover, broadcast);
-                       else {
-                               _SendMessage(socket, request,
-                                       state != RENEWAL ? broadcast : fServer);
-                       }
+                       _SendMessage(socket, state == INIT ? discover : request,
+                               state != RENEWING ? broadcast : fServer);
 
                        continue;
                } else if (bytesReceived < 0)
@@ -566,10 +575,16 @@
                        continue;
                }
 
-               syslog(LOG_DEBUG, "Received %s from %s for %s\n",
-                       dhcp_message::TypeToString(message->Type()),
-                               
_AddressToString(from.sin_addr.s_addr).String(), Device());
+               // advance from startup state
+               if (state == INIT)
+                       state = SELECTING;
+               else if (state == INIT_REBOOT)
+                       state = REBOOTING;
 
+               syslog(LOG_DEBUG, "%s: Received %s from %s\n",
+                       Device(), dhcp_message::TypeToString(message->Type()),
+                       _AddressToString(from.sin_addr.s_addr).String());
+
                switch (message->Type()) {
                        case DHCP_NONE:
                        default:
@@ -579,7 +594,7 @@
                        case DHCP_OFFER:
                        {
                                // first offer wins
-                               if (state != INIT)
+                               if (state != SELECTING)
                                        break;
 
                                // collect interface options
@@ -590,7 +605,7 @@
 
                                fConfiguration.MakeEmpty();
                                fConfiguration.AddString("device", Device());
-                               fConfiguration.AddBool("auto", true);
+                               fConfiguration.AddBool("auto_configured", true);
 
                                BMessage address;
                                address.AddString("family", "inet");
@@ -614,8 +629,10 @@
 
                        case DHCP_ACK:
                        {
-                               if (state != REQUESTING && state != REBINDING
-                                       && state != RENEWAL)
+                               if (state != REQUESTING
+                                       && state != REBOOTING
+                                       && state != REBINDING
+                                       && state != RENEWING)
                                        continue;
 
                                // TODO: we might want to configure the stuff, 
don't we?
@@ -626,7 +643,7 @@
                                        // way
 
                                // our address request has been acknowledged
-                               state = ACKNOWLEDGED;
+                               state = BOUND;
 
                                // configure interface
                                BMessage reply;
@@ -644,9 +661,18 @@
                        }
 
                        case DHCP_NACK:
-                               if (state != REQUESTING)
+                               if (state != REQUESTING
+                                       && state != REBOOTING
+                                       && state != REBINDING
+                                       && state != RENEWING)
                                        continue;
 
+                               if (state == REBOOTING) {
+                                       // server reject our request on 
previous assigned address
+                                       // back to square one...
+                                       fAssignedAddress = 0;
+                               }
+
                                // try again (maybe we should prefer other 
servers if this
                                // happens more than once)
                                status = _SendMessage(socket, discover, 
broadcast);
@@ -819,7 +845,8 @@
                                        (uint32)server.sin_addr.s_addr);
                        }
 
-                       if (state == INIT || state == REQUESTING) {
+                       if (state == INIT || state == INIT_REBOOT 
+                               || state == REQUESTING) {
                                next = message.PutOption(next, 
OPTION_REQUEST_IP_ADDRESS,
                                        (uint32)fAssignedAddress);
                        } else
@@ -866,7 +893,7 @@
                if (++tries > 2)
                        return false;
        }
-       syslog(LOG_DEBUG, "Timeout shift for %s: %lu secs (try %lu)\n",
+       syslog(LOG_DEBUG, "%s: Timeout shift: %lu secs (try %lu)\n",
                Device(), timeout, tries);
 
        struct timeval value;
@@ -898,9 +925,16 @@
 DHCPClient::_SendMessage(int socket, dhcp_message& message,
        const BNetworkAddress& address) const
 {
-       syslog(LOG_DEBUG, "Send %s to %s on %s\n",
-               dhcp_message::TypeToString(message.Type()),
-                       address.ToString().String(), Device());
+       message_type type = message.Type();
+       BString text;
+       text << dhcp_message::TypeToString(type);
+ 
+       const uint8* requestAddress = 
message.FindOption(OPTION_REQUEST_IP_ADDRESS);
+       if (type == DHCP_REQUEST && requestAddress != NULL)
+               text << " for " << _AddressToString(requestAddress).String();
+       
+       syslog(LOG_DEBUG, "%s: Send %s to %s\n", Device(), text.String(), 
+               address.ToString().String());
 
        ssize_t bytesSent = sendto(socket, &message, message.Size(),
                address.IsBroadcast() ? MSG_BCAST : 0, address, 
address.Length());
@@ -921,7 +955,7 @@
        if (now >= fRebindingTime)
                return REBINDING;
        if (now >= fRenewalTime)
-               return RENEWAL;
+               return RENEWING;
 
        return BOUND;
 }
@@ -938,7 +972,7 @@
                        bigtime_t next;
                        if (_Negotiate(state) == B_OK) {
                                switch (state) {
-                                       case RENEWAL:
+                                       case RENEWING:
                                                next = fRebindingTime;
                                                break;
                                        case REBINDING:
@@ -948,7 +982,7 @@
                                }
                        } else {
                                switch (state) {
-                                       case RENEWAL:
+                                       case RENEWING:
                                                next = (fLeaseTime - 
fRebindingTime) / 4 + system_time();
                                                break;
                                        case REBINDING:

Modified: haiku/trunk/src/servers/net/DHCPClient.h
===================================================================
--- haiku/trunk/src/servers/net/DHCPClient.h    2011-04-27 05:11:21 UTC (rev 
41284)
+++ haiku/trunk/src/servers/net/DHCPClient.h    2011-04-27 15:04:55 UTC (rev 
41285)
@@ -22,11 +22,13 @@
 
 enum dhcp_state {
        INIT,
+       SELECTING,
+       INIT_REBOOT,
+       REBOOTING,
        REQUESTING,
        BOUND,
-       RENEWAL,
+       RENEWING,
        REBINDING,
-       ACKNOWLEDGED,
 };
 
 
@@ -55,9 +57,9 @@
                        bool                            _TimeoutShift(int 
socket, time_t& timeout,
                                                                        uint32& 
tries);
                        void                            _RestartLease(bigtime_t 
lease);
-                       
+
        static  BString                         _AddressToString(const uint8* 
data);
-       static  BString                         _AddressToString(in_addr_t 
address);
+       static  BString                         _AddressToString(in_addr_t 
address);
 
 private:
                        BMessage                        fConfiguration;

Modified: haiku/trunk/src/servers/net/NetServer.cpp
===================================================================
--- haiku/trunk/src/servers/net/NetServer.cpp   2011-04-27 05:11:21 UTC (rev 
41284)
+++ haiku/trunk/src/servers/net/NetServer.cpp   2011-04-27 15:04:55 UTC (rev 
41285)
@@ -443,7 +443,7 @@
                flags = IFF_UP;
 
        bool autoConfigured;
-       if (message.FindBool("auto", &autoConfigured) == B_OK && autoConfigured)
+       if (message.FindBool("auto_configured", &autoConfigured) == B_OK && 
autoConfigured)
                flags |= IFF_AUTO_CONFIGURED;
 
        int32 mtu;
@@ -532,7 +532,7 @@
                        if (addressMessage.FindString("broadcast", &string) == 
B_OK)
                                parse_address(family, string, broadcast);
                }
-
+               
                if (autoConfig) {
                        _QuitLooperForDevice(name);
                        startAutoConfig = true;


Other related posts:

  • » [haiku-commits] r41285 - haiku/trunk/src/servers/net - philippe . houdoin