Author: phoudoin Date: 2011-04-23 03:52:16 +0200 (Sat, 23 Apr 2011) New Revision: 41278 Changeset: https://dev.haiku-os.org/changeset/41278 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: Avoid deadlock. Modified: haiku/trunk/src/servers/net/AutoconfigLooper.cpp =================================================================== --- haiku/trunk/src/servers/net/AutoconfigLooper.cpp 2011-04-23 01:02:02 UTC (rev 41277) +++ haiku/trunk/src/servers/net/AutoconfigLooper.cpp 2011-04-23 01:52:16 UTC (rev 41278) @@ -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-23 01:02:02 UTC (rev 41277) +++ haiku/trunk/src/servers/net/DHCPClient.cpp 2011-04-23 01:52:16 UTC (rev 41278) @@ -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,15 @@ // 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) { + printf("DHCPClient::_Negotiate(%d)\n", (int)state); + char buffer[2048]; struct sockaddr_in from; socklen_t fromLength = sizeof(from); @@ -546,12 +561,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 +577,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 +596,7 @@ case DHCP_OFFER: { // first offer wins - if (state != INIT) + if (state != SELECTING) break; // collect interface options @@ -590,7 +607,7 @@ fConfiguration.MakeEmpty(); fConfiguration.AddString("device", Device()); - fConfiguration.AddBool("auto", true); + fConfiguration.AddBool("auto_configured", true); BMessage address; address.AddString("family", "inet"); @@ -614,8 +631,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 +645,7 @@ // way // our address request has been acknowledged - state = ACKNOWLEDGED; + state = BOUND; // configure interface BMessage reply; @@ -644,9 +663,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 +847,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 +895,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 +927,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 +957,7 @@ if (now >= fRebindingTime) return REBINDING; if (now >= fRenewalTime) - return RENEWAL; + return RENEWING; return BOUND; } @@ -938,7 +974,7 @@ bigtime_t next; if (_Negotiate(state) == B_OK) { switch (state) { - case RENEWAL: + case RENEWING: next = fRebindingTime; break; case REBINDING: @@ -948,7 +984,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-23 01:02:02 UTC (rev 41277) +++ haiku/trunk/src/servers/net/DHCPClient.h 2011-04-23 01:52:16 UTC (rev 41278) @@ -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-23 01:02:02 UTC (rev 41277) +++ haiku/trunk/src/servers/net/NetServer.cpp 2011-04-23 01:52:16 UTC (rev 41278) @@ -533,12 +533,10 @@ parse_address(family, string, broadcast); } - if (!autoConfigured || autoConfig) + if (autoConfig) { _QuitLooperForDevice(name); - - startAutoConfig = autoConfig; - - if (addressMessage.FindString("gateway", &string) == B_OK + startAutoConfig = true; + } else if (addressMessage.FindString("gateway", &string) == B_OK && parse_address(family, string, gateway)) { // add gateway route, if we're asked for it interface.RemoveDefaultRoute(family); @@ -611,7 +609,8 @@ looper->Run(); fDeviceMap[name] = looper; - } + } else if (!autoConfigured) + _QuitLooperForDevice(name); return B_OK; }