* Pulled an AutoconfigClient class out of DHCPClient - all clients are supposed

to inherit from that one (there is still just a single client, though, this
  just simplifies having a generic mechanism to register and use auto-config
  clients).
* AutoconfigLooper now listens to link changes, and will reconfigure the
  interface if a new link is there - this even seems to work in emulation, will
  test on real hardware next.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28827 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-12-27 22:15:17 +00:00
parent bf6bf2e36b
commit 293ed4fe5b
8 changed files with 190 additions and 72 deletions

View File

@ -0,0 +1,31 @@
/*
* Copyright 2008, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
#include "AutoconfigClient.h"
AutoconfigClient::AutoconfigClient(const char* name, BMessenger target,
const char* device)
: BHandler(name),
fTarget(target),
fDevice(device)
{
}
AutoconfigClient::~AutoconfigClient()
{
}
status_t
AutoconfigClient::Initialize()
{
return B_NOT_SUPPORTED;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2008, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef AUTOCONFIG_CLIENT_H
#define AUTOCONFIG_CLIENT_H
#include <Handler.h>
#include <Messenger.h>
#include <String.h>
class AutoconfigClient : public BHandler {
public:
AutoconfigClient(const char* name,
BMessenger target, const char* device);
virtual ~AutoconfigClient();
virtual status_t Initialize();
const BMessenger& Target() const { return fTarget; }
const char* Device() const { return fDevice.String(); }
private:
BMessenger fTarget;
BString fDevice;
};
#endif // AUTOCONFIG_CLIENT_H

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -8,16 +8,20 @@
#include "AutoconfigLooper.h"
#include "DHCPClient.h"
#include "NetServer.h"
#include <errno.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net_notifications.h>
#include "DHCPClient.h"
#include "NetServer.h"
static const uint32 kMsgReadyToRun = 'rdyr';
@ -25,7 +29,8 @@ static const uint32 kMsgReadyToRun = 'rdyr';
AutoconfigLooper::AutoconfigLooper(BMessenger target, const char* device)
: BLooper(device),
fTarget(target),
fDevice(device)
fDevice(device),
fCurrentClient(NULL)
{
BMessage ready(kMsgReadyToRun);
PostMessage(&ready);
@ -38,7 +43,19 @@ AutoconfigLooper::~AutoconfigLooper()
void
AutoconfigLooper::_ReadyToRun()
AutoconfigLooper::_RemoveClient()
{
if (fCurrentClient == NULL)
return;
RemoveHandler(fCurrentClient);
delete fCurrentClient;
fCurrentClient = NULL;
}
void
AutoconfigLooper::_Configure()
{
ifreq request;
if (!prepare_request(request, fDevice.String()))
@ -57,16 +74,19 @@ AutoconfigLooper::_ReadyToRun()
close(socket);
// remove current handler
_RemoveClient();
// start with DHCP
DHCPClient* client = new DHCPClient(fTarget, fDevice.String());
AddHandler(client);
fCurrentClient = new DHCPClient(fTarget, fDevice.String());
AddHandler(fCurrentClient);
if (client->Initialize() == B_OK)
if (fCurrentClient->Initialize() == B_OK)
return;
RemoveHandler(client);
delete client;
_RemoveClient();
puts("DHCP failed miserably!");
@ -89,11 +109,11 @@ AutoconfigLooper::_ReadyToRun()
last = 1;
}
char string[64];
// IANA defined the default autoconfig network (for when a DHCP request
// fails for some reason) as being 169.254.0.0/255.255.0.0. We are only
// generating the last octet but we could also use the 2 last octets if
// wanted.
char string[64];
snprintf(string, sizeof(string), "169.254.0.%u", last);
BMessage address;
@ -105,6 +125,14 @@ AutoconfigLooper::_ReadyToRun()
}
void
AutoconfigLooper::_ReadyToRun()
{
start_watching_network(B_WATCH_NETWORK_LINK_CHANGES, this);
_Configure();
}
void
AutoconfigLooper::MessageReceived(BMessage* message)
{
@ -113,6 +141,23 @@ AutoconfigLooper::MessageReceived(BMessage* message)
_ReadyToRun();
break;
case B_NETWORK_MONITOR:
const char* device;
int32 opcode;
int32 media;
if (message->FindInt32("opcode", &opcode) != B_OK
|| opcode != B_NETWORK_DEVICE_LINK_CHANGED
|| message->FindString("device", &device) != B_OK
|| fDevice != device
|| message->FindInt32("media", &media) != B_OK)
break;
if ((media & IFM_ACTIVE) != 0) {
// Reconfigure the interface when we have a link again
_Configure();
}
break;
default:
BLooper::MessageReceived(message);
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -13,21 +13,26 @@
#include <Messenger.h>
#include <String.h>
class AutoconfigClient;
class AutoconfigLooper : public BLooper {
public:
AutoconfigLooper(BMessenger target, const char* device);
virtual ~AutoconfigLooper();
public:
AutoconfigLooper(BMessenger target,
const char* device);
virtual ~AutoconfigLooper();
virtual void MessageReceived(BMessage* message);
virtual void MessageReceived(BMessage* message);
BMessenger Target() const { return fTarget; }
BMessenger Target() const { return fTarget; }
private:
void _ReadyToRun();
private:
void _RemoveClient();
void _Configure();
void _ReadyToRun();
BMessenger fTarget;
BString fDevice;
BMessenger fTarget;
BString fDevice;
AutoconfigClient* fCurrentClient;
};
#endif // AUTOCONFIG_LOOPER_H

View File

@ -17,6 +17,7 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <sys/sockio.h>
#include <sys/time.h>
@ -329,9 +330,7 @@ dhcp_message::FinishOptions(uint8 *next)
DHCPClient::DHCPClient(BMessenger target, const char* device)
: BHandler("dhcp"),
fTarget(target),
fDevice(device),
: AutoconfigClient("dhcp", target, device),
fConfiguration(kMsgConfigureInterface),
fRunner(NULL),
fLeaseTime(0)
@ -347,6 +346,8 @@ DHCPClient::DHCPClient(BMessenger target, const char* device)
fServer.sin_family = AF_INET;
fServer.sin_len = sizeof(struct sockaddr_in);
fServer.sin_port = htons(DHCP_SERVER_PORT);
openlog_thread("DHCP", 0, LOG_DAEMON);
}
@ -368,6 +369,8 @@ DHCPClient::~DHCPClient()
_SendMessage(socket, release, fServer);
close(socket);
closelog_thread();
}
@ -375,7 +378,7 @@ status_t
DHCPClient::Initialize()
{
fStatus = _Negotiate(INIT);
printf("DHCP for %s, status: %s\n", fDevice.String(), strerror(fStatus));
syslog(LOG_DEBUG, "DHCP for %s, status: %s\n", Device(), strerror(fStatus));
return fStatus;
}
@ -416,7 +419,7 @@ DHCPClient::_Negotiate(dhcp_state state)
if (linkSocket >= 0) {
// we need to know the index of the device to be able to bind to it
ifreq request;
prepare_request(request, fDevice.String());
prepare_request(request, Device());
if (ioctl(linkSocket, SIOCGIFINDEX, &request, sizeof(struct ifreq))
== 0) {
setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE,
@ -502,7 +505,7 @@ DHCPClient::_Negotiate(dhcp_state state)
fAssignedAddress = message->your_address;
fConfiguration.MakeEmpty();
fConfiguration.AddString("device", fDevice.String());
fConfiguration.AddString("device", Device());
fConfiguration.AddBool("auto", true);
BMessage address;
@ -540,7 +543,7 @@ DHCPClient::_Negotiate(dhcp_state state)
// configure interface
BMessage reply;
fTarget.SendMessage(&fConfiguration, &reply);
Target().SendMessage(&fConfiguration, &reply);
if (reply.FindInt32("status", &fStatus) != B_OK)
status = B_OK;
@ -622,10 +625,11 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address)
// TODO: for now, we write it just out to /etc/resolv.conf
FILE* file = fopen("/etc/resolv.conf", "w");
for (uint32 i = 0; i < size / 4; i++) {
printf("DNS: %s\n", _ToString(&data[i*4]).String());
syslog(LOG_INFO, "DNS: %s\n",
_ToString(&data[i * 4]).String());
if (file != NULL) {
fprintf(file, "nameserver %s\n",
_ToString(&data[i*4]).String());
_ToString(&data[i * 4]).String());
}
}
fclose(file);
@ -636,16 +640,17 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address)
break;
case OPTION_ADDRESS_LEASE_TIME:
printf("lease time of %lu seconds\n", htonl(*(uint32*)data));
syslog(LOG_INFO, "lease time of %lu seconds\n",
htonl(*(uint32*)data));
fLeaseTime = htonl(*(uint32*)data) * 1000000LL;
break;
case OPTION_RENEWAL_TIME:
printf("renewal time of %lu seconds\n",
syslog(LOG_INFO, "renewal time of %lu seconds\n",
htonl(*(uint32*)data));
fRenewalTime = htonl(*(uint32*)data) * 1000000LL;
break;
case OPTION_REBINDING_TIME:
printf("rebinding time of %lu seconds\n",
syslog(LOG_INFO, "rebinding time of %lu seconds\n",
htonl(*(uint32*)data));
fRebindingTime = htonl(*(uint32*)data) * 1000000LL;
break;
@ -655,7 +660,7 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address)
char name[256];
memcpy(name, data, size);
name[size] = '\0';
printf("DHCP host name: \"%s\"\n", name);
syslog(LOG_INFO, "DHCP host name: \"%s\"\n", name);
break;
}
@ -664,7 +669,7 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address)
char name[256];
memcpy(name, data, size);
name[size] = '\0';
printf("DHCP domain name: \"%s\"\n", name);
syslog(LOG_INFO, "DHCP domain name: \"%s\"\n", name);
break;
}
@ -672,7 +677,7 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address)
break;
default:
printf("unknown option %lu\n", (uint32)option);
syslog(LOG_INFO, "unknown option %lu\n", (uint32)option);
break;
}
}
@ -754,7 +759,8 @@ DHCPClient::_TimeoutShift(int socket, time_t& timeout, uint32& tries)
if (++tries > 2)
return false;
}
printf("DHCP timeout shift: %lu secs (try %lu)\n", timeout, tries);
syslog(LOG_DEBUG, "DHCP timeout shift: %lu secs (try %lu)\n", timeout,
tries);
struct timeval value;
value.tv_sec = timeout;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -9,9 +9,7 @@
#define DHCP_CLIENT_H
#include <Handler.h>
#include <Messenger.h>
#include <String.h>
#include "AutoconfigClient.h"
#include <netinet/in.h>
@ -28,12 +26,12 @@ enum dhcp_state {
};
class DHCPClient : public BHandler {
class DHCPClient : public AutoconfigClient {
public:
DHCPClient(BMessenger target, const char* device);
virtual ~DHCPClient();
status_t Initialize();
virtual status_t Initialize();
virtual void MessageReceived(BMessage* message);
@ -49,8 +47,6 @@ class DHCPClient : public BHandler {
BString _ToString(const uint8* data) const;
BString _ToString(in_addr_t address) const;
BMessenger fTarget;
BString fDevice;
BMessage fConfiguration;
BMessageRunner* fRunner;
uint8 fMAC[6];

View File

@ -11,6 +11,7 @@ AddResources net_server : net_server.rdef ;
Server net_server :
NetServer.cpp
Settings.cpp
AutoconfigClient.cpp
AutoconfigLooper.cpp
DHCPClient.cpp
Services.cpp

View File

@ -7,10 +7,22 @@
*/
#include "AutoconfigLooper.h"
#include "NetServer.h"
#include "Services.h"
#include "Settings.h"
#include <errno.h>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <Alert.h>
#include <Deskbar.h>
@ -22,26 +34,15 @@
#include <Server.h>
#include <TextView.h>
#include <arpa/inet.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <map>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <unistd.h>
#include "AutoconfigLooper.h"
#include "Services.h"
#include "Settings.h"
static const char *kSignature = "application/x-vnd.haiku-net_server";
typedef std::map<std::string, BLooper*> LooperMap;
typedef std::map<std::string, AutoconfigLooper*> LooperMap;
class NetServer : public BServer {
@ -59,7 +60,7 @@ class NetServer : public BServer {
status_t _ConfigureInterface(int socket, BMessage& interface,
bool fromMessage = false);
bool _QuitLooperForDevice(const char* device);
BLooper* _LooperForDevice(const char* device);
AutoconfigLooper* _LooperForDevice(const char* device);
status_t _ConfigureDevice(int socket, const char* path);
void _ConfigureDevices(int socket, const char* path,
BMessage* suggestedInterface = NULL);
@ -258,7 +259,7 @@ NetServer::AboutRequested()
view->GetFont(&font);
font.SetSize(18);
font.SetFace(B_BOLD_FACE);
font.SetFace(B_BOLD_FACE);
view->SetFontAndColor(0, 17, &font);
alert->Go(NULL);
@ -363,7 +364,7 @@ NetServer::_IsValidInterface(int socket, const char* name)
if (addresses == 0)
return false;
// check if it has a hardware address, too, in case of ethernet
// check if it has a hardware address, too, in case of ethernet
if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) < 0)
return false;
@ -568,7 +569,7 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage
if (addressMessage.FindString("address", &string) == B_OK
&& parse_address(familyIndex, string, address)) {
hasAddress = true;
if (addressMessage.FindString("mask", &string) == B_OK
&& parse_address(familyIndex, string, mask))
hasMask = true;
@ -612,13 +613,13 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage
if (hasAddress) {
memcpy(&request.ifr_addr, &address, address.sa_len);
if (ioctl(familySocket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0) {
fprintf(stderr, "%s: Setting address failed: %s\n", Name(), strerror(errno));
continue;
}
}
if (ioctl(familySocket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
fprintf(stderr, "%s: Getting flags failed: %s\n", Name(), strerror(errno));
continue;
@ -695,15 +696,15 @@ NetServer::_QuitLooperForDevice(const char* device)
return false;
// there is a looper for this device - quit it
iterator->second->Lock();
iterator->second->Quit();
if (iterator->second->Lock())
iterator->second->Quit();
fDeviceMap.erase(iterator);
return true;
}
BLooper*
AutoconfigLooper*
NetServer::_LooperForDevice(const char* device)
{
LooperMap::const_iterator iterator = fDeviceMap.find(device);