Avoid deadlock.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41278 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -58,21 +58,19 @@ AutoconfigLooper::_RemoveClient()
|
|||||||
void
|
void
|
||||||
AutoconfigLooper::_Configure()
|
AutoconfigLooper::_Configure()
|
||||||
{
|
{
|
||||||
|
// start with DHCP
|
||||||
|
|
||||||
|
if (fCurrentClient == NULL) {
|
||||||
|
fCurrentClient = new DHCPClient(fTarget, fDevice.String());
|
||||||
|
AddHandler(fCurrentClient);
|
||||||
|
}
|
||||||
|
|
||||||
// set IFF_CONFIGURING flag on interface
|
// set IFF_CONFIGURING flag on interface
|
||||||
|
|
||||||
BNetworkInterface interface(fDevice.String());
|
BNetworkInterface interface(fDevice.String());
|
||||||
int32 flags = interface.Flags() & ~IFF_AUTO_CONFIGURED;
|
int32 flags = interface.Flags() & ~IFF_AUTO_CONFIGURED;
|
||||||
interface.SetFlags(flags | IFF_CONFIGURING);
|
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)
|
if (fCurrentClient->Initialize() == B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -91,7 +89,7 @@ AutoconfigLooper::_Configure()
|
|||||||
|
|
||||||
BMessage message(kMsgConfigureInterface);
|
BMessage message(kMsgConfigureInterface);
|
||||||
message.AddString("device", fDevice.String());
|
message.AddString("device", fDevice.String());
|
||||||
message.AddBool("auto", true);
|
message.AddBool("auto_configured", true);
|
||||||
|
|
||||||
BNetworkAddress link;
|
BNetworkAddress link;
|
||||||
uint8 last = 56;
|
uint8 last = 56;
|
||||||
|
|||||||
@@ -422,6 +422,7 @@ DHCPClient::DHCPClient(BMessenger target, const char* device)
|
|||||||
fConfiguration(kMsgConfigureInterface),
|
fConfiguration(kMsgConfigureInterface),
|
||||||
fResolverConfiguration(kMsgConfigureResolver),
|
fResolverConfiguration(kMsgConfigureResolver),
|
||||||
fRunner(NULL),
|
fRunner(NULL),
|
||||||
|
fAssignedAddress(0),
|
||||||
fServer(AF_INET, NULL, DHCP_SERVER_PORT),
|
fServer(AF_INET, NULL, DHCP_SERVER_PORT),
|
||||||
fLeaseTime(0)
|
fLeaseTime(0)
|
||||||
{
|
{
|
||||||
@@ -436,6 +437,18 @@ DHCPClient::DHCPClient(BMessenger target, const char* device)
|
|||||||
|
|
||||||
memcpy(fMAC, link.LinkLevelAddress(), sizeof(fMAC));
|
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);
|
openlog_thread("DHCP", 0, LOG_DAEMON);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,8 +479,8 @@ DHCPClient::~DHCPClient()
|
|||||||
status_t
|
status_t
|
||||||
DHCPClient::Initialize()
|
DHCPClient::Initialize()
|
||||||
{
|
{
|
||||||
fStatus = _Negotiate(INIT);
|
fStatus = _Negotiate(fAssignedAddress == 0 ? INIT : INIT_REBOOT);
|
||||||
syslog(LOG_DEBUG, "DHCP for %s, status: %s\n", Device(), strerror(fStatus));
|
syslog(LOG_DEBUG, "%s: DHCP status = %s\n", Device(), strerror(fStatus));
|
||||||
return fStatus;
|
return fStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,13 +540,15 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
|
|
||||||
// send discover/request message
|
// send discover/request message
|
||||||
_SendMessage(socket, state == INIT ? discover : request,
|
_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
|
// no need to check the status; in case of an error we'll just send
|
||||||
// the message again
|
// the message again
|
||||||
|
|
||||||
// receive loop until we've got an offer and acknowledged it
|
// 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];
|
char buffer[2048];
|
||||||
struct sockaddr_in from;
|
struct sockaddr_in from;
|
||||||
socklen_t fromLength = sizeof(from);
|
socklen_t fromLength = sizeof(from);
|
||||||
@@ -546,12 +561,8 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
return B_TIMED_OUT;
|
return B_TIMED_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == INIT)
|
_SendMessage(socket, state == INIT ? discover : request,
|
||||||
_SendMessage(socket, discover, broadcast);
|
state != RENEWING ? broadcast : fServer);
|
||||||
else {
|
|
||||||
_SendMessage(socket, request,
|
|
||||||
state != RENEWAL ? broadcast : fServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
} else if (bytesReceived < 0)
|
} else if (bytesReceived < 0)
|
||||||
@@ -566,9 +577,15 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog(LOG_DEBUG, "Received %s from %s for %s\n",
|
// advance from startup state
|
||||||
dhcp_message::TypeToString(message->Type()),
|
if (state == INIT)
|
||||||
_AddressToString(from.sin_addr.s_addr).String(), Device());
|
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()) {
|
switch (message->Type()) {
|
||||||
case DHCP_NONE:
|
case DHCP_NONE:
|
||||||
@@ -579,7 +596,7 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
case DHCP_OFFER:
|
case DHCP_OFFER:
|
||||||
{
|
{
|
||||||
// first offer wins
|
// first offer wins
|
||||||
if (state != INIT)
|
if (state != SELECTING)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// collect interface options
|
// collect interface options
|
||||||
@@ -590,7 +607,7 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
|
|
||||||
fConfiguration.MakeEmpty();
|
fConfiguration.MakeEmpty();
|
||||||
fConfiguration.AddString("device", Device());
|
fConfiguration.AddString("device", Device());
|
||||||
fConfiguration.AddBool("auto", true);
|
fConfiguration.AddBool("auto_configured", true);
|
||||||
|
|
||||||
BMessage address;
|
BMessage address;
|
||||||
address.AddString("family", "inet");
|
address.AddString("family", "inet");
|
||||||
@@ -614,8 +631,10 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
|
|
||||||
case DHCP_ACK:
|
case DHCP_ACK:
|
||||||
{
|
{
|
||||||
if (state != REQUESTING && state != REBINDING
|
if (state != REQUESTING
|
||||||
&& state != RENEWAL)
|
&& state != REBOOTING
|
||||||
|
&& state != REBINDING
|
||||||
|
&& state != RENEWING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO: we might want to configure the stuff, don't we?
|
// TODO: we might want to configure the stuff, don't we?
|
||||||
@@ -626,7 +645,7 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
// way
|
// way
|
||||||
|
|
||||||
// our address request has been acknowledged
|
// our address request has been acknowledged
|
||||||
state = ACKNOWLEDGED;
|
state = BOUND;
|
||||||
|
|
||||||
// configure interface
|
// configure interface
|
||||||
BMessage reply;
|
BMessage reply;
|
||||||
@@ -644,9 +663,18 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case DHCP_NACK:
|
case DHCP_NACK:
|
||||||
if (state != REQUESTING)
|
if (state != REQUESTING
|
||||||
|
&& state != REBOOTING
|
||||||
|
&& state != REBINDING
|
||||||
|
&& state != RENEWING)
|
||||||
continue;
|
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
|
// try again (maybe we should prefer other servers if this
|
||||||
// happens more than once)
|
// happens more than once)
|
||||||
status = _SendMessage(socket, discover, broadcast);
|
status = _SendMessage(socket, discover, broadcast);
|
||||||
@@ -819,7 +847,8 @@ DHCPClient::_PrepareMessage(dhcp_message& message, dhcp_state state)
|
|||||||
(uint32)server.sin_addr.s_addr);
|
(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,
|
next = message.PutOption(next, OPTION_REQUEST_IP_ADDRESS,
|
||||||
(uint32)fAssignedAddress);
|
(uint32)fAssignedAddress);
|
||||||
} else
|
} else
|
||||||
@@ -866,7 +895,7 @@ DHCPClient::_TimeoutShift(int socket, time_t& timeout, uint32& tries)
|
|||||||
if (++tries > 2)
|
if (++tries > 2)
|
||||||
return false;
|
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);
|
Device(), timeout, tries);
|
||||||
|
|
||||||
struct timeval value;
|
struct timeval value;
|
||||||
@@ -898,9 +927,16 @@ status_t
|
|||||||
DHCPClient::_SendMessage(int socket, dhcp_message& message,
|
DHCPClient::_SendMessage(int socket, dhcp_message& message,
|
||||||
const BNetworkAddress& address) const
|
const BNetworkAddress& address) const
|
||||||
{
|
{
|
||||||
syslog(LOG_DEBUG, "Send %s to %s on %s\n",
|
message_type type = message.Type();
|
||||||
dhcp_message::TypeToString(message.Type()),
|
BString text;
|
||||||
address.ToString().String(), Device());
|
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(),
|
ssize_t bytesSent = sendto(socket, &message, message.Size(),
|
||||||
address.IsBroadcast() ? MSG_BCAST : 0, address, address.Length());
|
address.IsBroadcast() ? MSG_BCAST : 0, address, address.Length());
|
||||||
@@ -921,7 +957,7 @@ DHCPClient::_CurrentState() const
|
|||||||
if (now >= fRebindingTime)
|
if (now >= fRebindingTime)
|
||||||
return REBINDING;
|
return REBINDING;
|
||||||
if (now >= fRenewalTime)
|
if (now >= fRenewalTime)
|
||||||
return RENEWAL;
|
return RENEWING;
|
||||||
|
|
||||||
return BOUND;
|
return BOUND;
|
||||||
}
|
}
|
||||||
@@ -938,7 +974,7 @@ DHCPClient::MessageReceived(BMessage* message)
|
|||||||
bigtime_t next;
|
bigtime_t next;
|
||||||
if (_Negotiate(state) == B_OK) {
|
if (_Negotiate(state) == B_OK) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case RENEWAL:
|
case RENEWING:
|
||||||
next = fRebindingTime;
|
next = fRebindingTime;
|
||||||
break;
|
break;
|
||||||
case REBINDING:
|
case REBINDING:
|
||||||
@@ -948,7 +984,7 @@ DHCPClient::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case RENEWAL:
|
case RENEWING:
|
||||||
next = (fLeaseTime - fRebindingTime) / 4 + system_time();
|
next = (fLeaseTime - fRebindingTime) / 4 + system_time();
|
||||||
break;
|
break;
|
||||||
case REBINDING:
|
case REBINDING:
|
||||||
|
|||||||
@@ -22,11 +22,13 @@ class dhcp_message;
|
|||||||
|
|
||||||
enum dhcp_state {
|
enum dhcp_state {
|
||||||
INIT,
|
INIT,
|
||||||
|
SELECTING,
|
||||||
|
INIT_REBOOT,
|
||||||
|
REBOOTING,
|
||||||
REQUESTING,
|
REQUESTING,
|
||||||
BOUND,
|
BOUND,
|
||||||
RENEWAL,
|
RENEWING,
|
||||||
REBINDING,
|
REBINDING,
|
||||||
ACKNOWLEDGED,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -533,12 +533,10 @@ NetServer::_ConfigureInterface(BMessage& message)
|
|||||||
parse_address(family, string, broadcast);
|
parse_address(family, string, broadcast);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!autoConfigured || autoConfig)
|
if (autoConfig) {
|
||||||
_QuitLooperForDevice(name);
|
_QuitLooperForDevice(name);
|
||||||
|
startAutoConfig = true;
|
||||||
startAutoConfig = autoConfig;
|
} else if (addressMessage.FindString("gateway", &string) == B_OK
|
||||||
|
|
||||||
if (addressMessage.FindString("gateway", &string) == B_OK
|
|
||||||
&& parse_address(family, string, gateway)) {
|
&& parse_address(family, string, gateway)) {
|
||||||
// add gateway route, if we're asked for it
|
// add gateway route, if we're asked for it
|
||||||
interface.RemoveDefaultRoute(family);
|
interface.RemoveDefaultRoute(family);
|
||||||
@@ -611,7 +609,8 @@ NetServer::_ConfigureInterface(BMessage& message)
|
|||||||
looper->Run();
|
looper->Run();
|
||||||
|
|
||||||
fDeviceMap[name] = looper;
|
fDeviceMap[name] = looper;
|
||||||
}
|
} else if (!autoConfigured)
|
||||||
|
_QuitLooperForDevice(name);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user