* An interface can now also be configured to be "auto config" (which means DHCP for now).
* Some minor cleanup in the DHCP client. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19465 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
fb2b8194c2
commit
0ce7725e1c
@ -296,16 +296,13 @@ DHCPClient::DHCPClient(BMessenger target, const char* device)
|
||||
{
|
||||
fTransactionID = system_time();
|
||||
|
||||
dhcp_message discover(DHCP_DISCOVER);
|
||||
discover.opcode = BOOT_REQUEST;
|
||||
discover.hardware_type = ARP_HARDWARE_TYPE_ETHER;
|
||||
discover.hardware_address_length = 6;
|
||||
discover.transaction_id = htonl(fTransactionID);
|
||||
discover.seconds_since_boot = htons(max_c(system_time() / 1000000LL, 65535));
|
||||
fStatus = get_mac_address(device, discover.mac_address);
|
||||
fStatus = get_mac_address(device, fMAC);
|
||||
if (fStatus < B_OK)
|
||||
return;
|
||||
|
||||
dhcp_message discover(DHCP_DISCOVER);
|
||||
_PrepareMessage(discover);
|
||||
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket < 0) {
|
||||
fStatus = errno;
|
||||
@ -418,48 +415,7 @@ DHCPClient::DHCPClient(BMessenger target, const char* device)
|
||||
BMessage address;
|
||||
address.AddString("family", "inet");
|
||||
address.AddString("address", _ToString(fAssignedAddress));
|
||||
|
||||
dhcp_option_cookie cookie;
|
||||
message_option option;
|
||||
const uint8 *data;
|
||||
size_t size;
|
||||
while (message->NextOption(cookie, option, data, size)) {
|
||||
// iterate through all options
|
||||
switch (option) {
|
||||
case OPTION_ROUTER_ADDRESS:
|
||||
address.AddString("gateway", _ToString(data));
|
||||
break;
|
||||
case OPTION_SUBNET_MASK:
|
||||
address.AddString("mask", _ToString(data));
|
||||
break;
|
||||
case OPTION_DOMAIN_NAME_SERVER:
|
||||
// TODO: for now, write it out to /etc/resolv.conf
|
||||
for (uint32 i = 0; i < size / 4; i++) {
|
||||
printf("DNS: %s\n", _ToString(&data[i*4]).String());
|
||||
}
|
||||
break;
|
||||
case OPTION_SERVER_ADDRESS:
|
||||
fServer.sin_addr.s_addr = *(in_addr_t*)data;
|
||||
break;
|
||||
case OPTION_ADDRESS_LEASE_TIME:
|
||||
printf("lease time of %lu seconds\n", htonl(*(uint32*)data));
|
||||
break;
|
||||
|
||||
case OPTION_HOST_NAME:
|
||||
char name[256];
|
||||
memcpy(name, data, size);
|
||||
name[size] = '\0';
|
||||
printf("DHCP host name: \"%s\"\n", name);
|
||||
break;
|
||||
|
||||
case OPTION_MESSAGE_TYPE:
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("unknown option %lu\n", (uint32)option);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ParseOptions(*message, address);
|
||||
|
||||
configure.AddMessage("address", &address);
|
||||
|
||||
@ -472,24 +428,9 @@ DHCPClient::DHCPClient(BMessenger target, const char* device)
|
||||
&& status == B_OK) {
|
||||
// configuration succeeded, request it from the server
|
||||
_ResetTimeout(socket);
|
||||
|
||||
state = REQUESTING;
|
||||
|
||||
request.opcode = BOOT_REQUEST;
|
||||
request.hardware_type = ARP_HARDWARE_TYPE_ETHER;
|
||||
request.hardware_address_length = 6;
|
||||
request.transaction_id = htonl(fTransactionID);
|
||||
request.seconds_since_boot = htons(max_c(system_time() / 1000000LL, 65535));
|
||||
memcpy(request.mac_address, discover.mac_address, 6);
|
||||
|
||||
// add server identifier option
|
||||
uint8* next = request.options;
|
||||
next = request.PutOption(next, OPTION_MESSAGE_TYPE, (uint8)DHCP_REQUEST);
|
||||
next = request.PutOption(next, OPTION_MESSAGE_SIZE,
|
||||
(uint16)sizeof(dhcp_message));
|
||||
next = request.PutOption(next, OPTION_SERVER_ADDRESS,
|
||||
(uint32)fServer.sin_addr.s_addr);
|
||||
next = request.PutOption(next, OPTION_REQUEST_IP_ADDRESS, fAssignedAddress);
|
||||
next = request.PutOption(next, OPTION_END);
|
||||
_PrepareMessage(request);
|
||||
|
||||
fStatus = _SendMessage(socket, request, broadcast);
|
||||
// we're sending a broadcast so that all offers get an answer
|
||||
@ -533,24 +474,93 @@ DHCPClient::~DHCPClient()
|
||||
// release lease
|
||||
|
||||
dhcp_message release(DHCP_RELEASE);
|
||||
release.opcode = BOOT_REQUEST;
|
||||
release.hardware_type = ARP_HARDWARE_TYPE_ETHER;
|
||||
release.hardware_address_length = 6;
|
||||
release.transaction_id = htonl(fTransactionID);
|
||||
release.seconds_since_boot = htons(max_c(system_time() / 1000000LL, 65535));
|
||||
get_mac_address(fDevice.String(), release.mac_address);
|
||||
|
||||
// add server identifier option
|
||||
uint8* next = const_cast<uint8*>(release.LastOption());
|
||||
next = release.PutOption(next, OPTION_SERVER_ADDRESS, (uint32)fServer.sin_addr.s_addr);
|
||||
next = release.PutOption(next, OPTION_REQUEST_IP_ADDRESS, fAssignedAddress);
|
||||
next = release.PutOption(next, OPTION_END);
|
||||
_PrepareMessage(release);
|
||||
|
||||
_SendMessage(socket, release, fServer);
|
||||
close(socket);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address)
|
||||
{
|
||||
dhcp_option_cookie cookie;
|
||||
message_option option;
|
||||
const uint8 *data;
|
||||
size_t size;
|
||||
while (message.NextOption(cookie, option, data, size)) {
|
||||
// iterate through all options
|
||||
switch (option) {
|
||||
case OPTION_ROUTER_ADDRESS:
|
||||
address.AddString("gateway", _ToString(data));
|
||||
break;
|
||||
case OPTION_SUBNET_MASK:
|
||||
address.AddString("mask", _ToString(data));
|
||||
break;
|
||||
case OPTION_DOMAIN_NAME_SERVER:
|
||||
// TODO: for now, write it out to /etc/resolv.conf
|
||||
for (uint32 i = 0; i < size / 4; i++) {
|
||||
printf("DNS: %s\n", _ToString(&data[i*4]).String());
|
||||
}
|
||||
break;
|
||||
case OPTION_SERVER_ADDRESS:
|
||||
fServer.sin_addr.s_addr = *(in_addr_t*)data;
|
||||
break;
|
||||
case OPTION_ADDRESS_LEASE_TIME:
|
||||
printf("lease time of %lu seconds\n", htonl(*(uint32*)data));
|
||||
break;
|
||||
|
||||
case OPTION_HOST_NAME:
|
||||
char name[256];
|
||||
memcpy(name, data, size);
|
||||
name[size] = '\0';
|
||||
printf("DHCP host name: \"%s\"\n", name);
|
||||
break;
|
||||
|
||||
case OPTION_MESSAGE_TYPE:
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("unknown option %lu\n", (uint32)option);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DHCPClient::_PrepareMessage(dhcp_message& message)
|
||||
{
|
||||
message.opcode = BOOT_REQUEST;
|
||||
message.hardware_type = ARP_HARDWARE_TYPE_ETHER;
|
||||
message.hardware_address_length = 6;
|
||||
message.transaction_id = htonl(fTransactionID);
|
||||
message.seconds_since_boot = htons(max_c(system_time() / 1000000LL, 65535));
|
||||
memcpy(message.mac_address, fMAC, 6);
|
||||
|
||||
switch (message.Type()) {
|
||||
case DHCP_REQUEST:
|
||||
case DHCP_RELEASE:
|
||||
{
|
||||
// add server identifier option
|
||||
uint8* next = message.options;
|
||||
next = message.PutOption(next, OPTION_MESSAGE_TYPE, (uint8)DHCP_REQUEST);
|
||||
next = message.PutOption(next, OPTION_MESSAGE_SIZE,
|
||||
(uint16)sizeof(dhcp_message));
|
||||
next = message.PutOption(next, OPTION_SERVER_ADDRESS,
|
||||
(uint32)fServer.sin_addr.s_addr);
|
||||
next = message.PutOption(next, OPTION_REQUEST_IP_ADDRESS, fAssignedAddress);
|
||||
next = message.PutOption(next, OPTION_END);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// the default options are fine
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DHCPClient::_ResetTimeout(int socket)
|
||||
{
|
||||
|
@ -29,6 +29,8 @@ class DHCPClient : public BHandler {
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
void _ParseOptions(dhcp_message& message, BMessage& address);
|
||||
void _PrepareMessage(dhcp_message& message);
|
||||
status_t _SendMessage(int socket, dhcp_message& message, sockaddr_in& address) const;
|
||||
void _ResetTimeout(int socket);
|
||||
bool _TimeoutShift(int socket);
|
||||
@ -37,6 +39,7 @@ class DHCPClient : public BHandler {
|
||||
|
||||
BString fDevice;
|
||||
BMessageRunner* fRunner;
|
||||
uint8 fMAC[6];
|
||||
uint32 fTransactionID;
|
||||
in_addr_t fAssignedAddress;
|
||||
sockaddr_in fServer;
|
||||
|
@ -48,7 +48,8 @@ class NetServer : public BApplication {
|
||||
|
||||
private:
|
||||
bool _TestForInterface(int socket, const char* name);
|
||||
status_t _ConfigureInterface(int socket, BMessage& interface);
|
||||
status_t _ConfigureInterface(int socket, BMessage& interface,
|
||||
bool fromMessage = false);
|
||||
bool _QuitLooperForDevice(const char* device);
|
||||
BLooper* _LooperForDevice(const char* device);
|
||||
status_t _ConfigureDevice(int socket, const char* path);
|
||||
@ -246,8 +247,8 @@ NetServer::MessageReceived(BMessage* message)
|
||||
if (socket < 0)
|
||||
break;
|
||||
|
||||
status_t status = _ConfigureInterface(socket, *message);
|
||||
|
||||
status_t status = _ConfigureInterface(socket, *message, true);
|
||||
|
||||
BMessage reply(B_REPLY);
|
||||
reply.AddInt32("status", status);
|
||||
message->SendReply(&reply);
|
||||
@ -309,7 +310,7 @@ NetServer::_TestForInterface(int socket, const char* name)
|
||||
|
||||
|
||||
status_t
|
||||
NetServer::_ConfigureInterface(int socket, BMessage& interface)
|
||||
NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage)
|
||||
{
|
||||
const char *device;
|
||||
if (interface.FindString("device", &device) != B_OK)
|
||||
@ -319,6 +320,8 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface)
|
||||
if (!prepare_request(request, device))
|
||||
return B_ERROR;
|
||||
|
||||
bool startAutoConfig = false;
|
||||
|
||||
int32 flags;
|
||||
if (interface.FindInt32("flags", &flags) < B_OK)
|
||||
flags = IFF_UP;
|
||||
@ -372,39 +375,59 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface)
|
||||
|
||||
// retrieve addresses
|
||||
|
||||
bool autoConfig;
|
||||
if (addressMessage.FindBool("auto config", &autoConfig) != B_OK)
|
||||
autoConfig = false;
|
||||
if (autoConfig && fromMessage) {
|
||||
// we don't accept auto-config messages this way
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hasAddress = false, hasMask = false, hasPeer = false, hasBroadcast = false;
|
||||
struct sockaddr address, mask, peer, broadcast, gateway;
|
||||
|
||||
const char* string;
|
||||
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;
|
||||
if (!autoConfig) {
|
||||
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;
|
||||
}
|
||||
if (addressMessage.FindString("peer", &string) == B_OK
|
||||
&& parse_address(familyIndex, string, peer))
|
||||
hasPeer = true;
|
||||
if (addressMessage.FindString("broadcast", &string) == B_OK
|
||||
&& parse_address(familyIndex, string, broadcast))
|
||||
hasBroadcast = true;
|
||||
}
|
||||
if (addressMessage.FindString("peer", &string) == B_OK
|
||||
&& parse_address(familyIndex, string, peer))
|
||||
hasPeer = true;
|
||||
if (addressMessage.FindString("broadcast", &string) == B_OK
|
||||
&& parse_address(familyIndex, string, broadcast))
|
||||
hasBroadcast = true;
|
||||
|
||||
// add gateway route, if we're asked for it
|
||||
route_entry route;
|
||||
memset(&route, 0, sizeof(route_entry));
|
||||
route.flags = RTF_STATIC | RTF_DEFAULT;
|
||||
|
||||
if (addressMessage.FindString("gateway", &string) == B_OK
|
||||
request.ifr_route = route;
|
||||
ioctl(socket, SIOCDELRT, &request, sizeof(request));
|
||||
// Try to remove a previous default route, doesn't matter
|
||||
// if it fails.
|
||||
|
||||
if (autoConfig) {
|
||||
// add a default route to make the interface accessible, even without an address
|
||||
if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) {
|
||||
fprintf(stderr, "%s: Could not add route for %s: %s\n",
|
||||
Name(), device, strerror(errno));
|
||||
} else {
|
||||
_QuitLooperForDevice(device);
|
||||
startAutoConfig = true;
|
||||
}
|
||||
} else if (addressMessage.FindString("gateway", &string) == B_OK
|
||||
&& parse_address(familyIndex, string, gateway)) {
|
||||
route_entry route;
|
||||
memset(&route, 0, sizeof(route_entry));
|
||||
// add gateway route, if we're asked for it
|
||||
route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY;
|
||||
route.gateway = &gateway;
|
||||
|
||||
request.ifr_route = route;
|
||||
ioctl(socket, SIOCDELRT, &request, sizeof(request));
|
||||
// Try to remove a previous default route, doesn't matter
|
||||
// if it fails.
|
||||
|
||||
if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) {
|
||||
fprintf(stderr, "%s: Could not add route for %s: %s\n",
|
||||
Name(), device, strerror(errno));
|
||||
@ -516,6 +539,14 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface)
|
||||
}
|
||||
}
|
||||
|
||||
if (startAutoConfig) {
|
||||
// start auto configuration
|
||||
AutoconfigLooper* looper = new AutoconfigLooper(this, device);
|
||||
looper->Run();
|
||||
|
||||
fDeviceMap[device] = looper;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -550,40 +581,16 @@ NetServer::_LooperForDevice(const char* device)
|
||||
status_t
|
||||
NetServer::_ConfigureDevice(int socket, const char* path)
|
||||
{
|
||||
_QuitLooperForDevice(path);
|
||||
|
||||
// bring interface up, but don't configure it just yet
|
||||
BMessage interface;
|
||||
interface.AddString("device", path);
|
||||
BMessage address;
|
||||
address.AddString("family", "inet");
|
||||
address.AddBool("auto config", true);
|
||||
interface.AddMessage("address", &address);
|
||||
|
||||
status_t status = _ConfigureInterface(socket, interface);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
// add a default route to make the interface accessible, even without an address
|
||||
route_entry route;
|
||||
memset(&route, 0, sizeof(route_entry));
|
||||
route.flags = RTF_STATIC | RTF_DEFAULT;
|
||||
|
||||
ifreq request;
|
||||
if (!prepare_request(request, path))
|
||||
return B_ERROR;
|
||||
|
||||
request.ifr_route = route;
|
||||
if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) {
|
||||
fprintf(stderr, "%s: Could not add route for %s: %s\n",
|
||||
Name(), path, strerror(errno));
|
||||
}
|
||||
|
||||
AutoconfigLooper* looper = new AutoconfigLooper(this, path);
|
||||
looper->Run();
|
||||
|
||||
fDeviceMap[path] = looper;
|
||||
|
||||
return B_OK;
|
||||
return _ConfigureInterface(socket, interface);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user