* 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();
|
fTransactionID = system_time();
|
||||||
|
|
||||||
dhcp_message discover(DHCP_DISCOVER);
|
fStatus = get_mac_address(device, fMAC);
|
||||||
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);
|
|
||||||
if (fStatus < B_OK)
|
if (fStatus < B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
dhcp_message discover(DHCP_DISCOVER);
|
||||||
|
_PrepareMessage(discover);
|
||||||
|
|
||||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (socket < 0) {
|
if (socket < 0) {
|
||||||
fStatus = errno;
|
fStatus = errno;
|
||||||
@ -418,48 +415,7 @@ DHCPClient::DHCPClient(BMessenger target, const char* device)
|
|||||||
BMessage address;
|
BMessage address;
|
||||||
address.AddString("family", "inet");
|
address.AddString("family", "inet");
|
||||||
address.AddString("address", _ToString(fAssignedAddress));
|
address.AddString("address", _ToString(fAssignedAddress));
|
||||||
|
_ParseOptions(*message, 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configure.AddMessage("address", &address);
|
configure.AddMessage("address", &address);
|
||||||
|
|
||||||
@ -472,24 +428,9 @@ DHCPClient::DHCPClient(BMessenger target, const char* device)
|
|||||||
&& status == B_OK) {
|
&& status == B_OK) {
|
||||||
// configuration succeeded, request it from the server
|
// configuration succeeded, request it from the server
|
||||||
_ResetTimeout(socket);
|
_ResetTimeout(socket);
|
||||||
|
|
||||||
state = REQUESTING;
|
state = REQUESTING;
|
||||||
|
_PrepareMessage(request);
|
||||||
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);
|
|
||||||
|
|
||||||
fStatus = _SendMessage(socket, request, broadcast);
|
fStatus = _SendMessage(socket, request, broadcast);
|
||||||
// we're sending a broadcast so that all offers get an answer
|
// we're sending a broadcast so that all offers get an answer
|
||||||
@ -533,24 +474,93 @@ DHCPClient::~DHCPClient()
|
|||||||
// release lease
|
// release lease
|
||||||
|
|
||||||
dhcp_message release(DHCP_RELEASE);
|
dhcp_message release(DHCP_RELEASE);
|
||||||
release.opcode = BOOT_REQUEST;
|
_PrepareMessage(release);
|
||||||
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);
|
|
||||||
|
|
||||||
_SendMessage(socket, release, fServer);
|
_SendMessage(socket, release, fServer);
|
||||||
close(socket);
|
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
|
void
|
||||||
DHCPClient::_ResetTimeout(int socket)
|
DHCPClient::_ResetTimeout(int socket)
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,8 @@ class DHCPClient : public BHandler {
|
|||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
private:
|
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;
|
status_t _SendMessage(int socket, dhcp_message& message, sockaddr_in& address) const;
|
||||||
void _ResetTimeout(int socket);
|
void _ResetTimeout(int socket);
|
||||||
bool _TimeoutShift(int socket);
|
bool _TimeoutShift(int socket);
|
||||||
@ -37,6 +39,7 @@ class DHCPClient : public BHandler {
|
|||||||
|
|
||||||
BString fDevice;
|
BString fDevice;
|
||||||
BMessageRunner* fRunner;
|
BMessageRunner* fRunner;
|
||||||
|
uint8 fMAC[6];
|
||||||
uint32 fTransactionID;
|
uint32 fTransactionID;
|
||||||
in_addr_t fAssignedAddress;
|
in_addr_t fAssignedAddress;
|
||||||
sockaddr_in fServer;
|
sockaddr_in fServer;
|
||||||
|
@ -48,7 +48,8 @@ class NetServer : public BApplication {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool _TestForInterface(int socket, const char* name);
|
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);
|
bool _QuitLooperForDevice(const char* device);
|
||||||
BLooper* _LooperForDevice(const char* device);
|
BLooper* _LooperForDevice(const char* device);
|
||||||
status_t _ConfigureDevice(int socket, const char* path);
|
status_t _ConfigureDevice(int socket, const char* path);
|
||||||
@ -246,7 +247,7 @@ NetServer::MessageReceived(BMessage* message)
|
|||||||
if (socket < 0)
|
if (socket < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
status_t status = _ConfigureInterface(socket, *message);
|
status_t status = _ConfigureInterface(socket, *message, true);
|
||||||
|
|
||||||
BMessage reply(B_REPLY);
|
BMessage reply(B_REPLY);
|
||||||
reply.AddInt32("status", status);
|
reply.AddInt32("status", status);
|
||||||
@ -309,7 +310,7 @@ NetServer::_TestForInterface(int socket, const char* name)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
NetServer::_ConfigureInterface(int socket, BMessage& interface)
|
NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage)
|
||||||
{
|
{
|
||||||
const char *device;
|
const char *device;
|
||||||
if (interface.FindString("device", &device) != B_OK)
|
if (interface.FindString("device", &device) != B_OK)
|
||||||
@ -319,6 +320,8 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface)
|
|||||||
if (!prepare_request(request, device))
|
if (!prepare_request(request, device))
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
|
bool startAutoConfig = false;
|
||||||
|
|
||||||
int32 flags;
|
int32 flags;
|
||||||
if (interface.FindInt32("flags", &flags) < B_OK)
|
if (interface.FindInt32("flags", &flags) < B_OK)
|
||||||
flags = IFF_UP;
|
flags = IFF_UP;
|
||||||
@ -372,10 +375,19 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface)
|
|||||||
|
|
||||||
// retrieve addresses
|
// 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;
|
bool hasAddress = false, hasMask = false, hasPeer = false, hasBroadcast = false;
|
||||||
struct sockaddr address, mask, peer, broadcast, gateway;
|
struct sockaddr address, mask, peer, broadcast, gateway;
|
||||||
|
|
||||||
const char* string;
|
const char* string;
|
||||||
|
|
||||||
|
if (!autoConfig) {
|
||||||
if (addressMessage.FindString("address", &string) == B_OK
|
if (addressMessage.FindString("address", &string) == B_OK
|
||||||
&& parse_address(familyIndex, string, address)) {
|
&& parse_address(familyIndex, string, address)) {
|
||||||
hasAddress = true;
|
hasAddress = true;
|
||||||
@ -390,21 +402,32 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface)
|
|||||||
if (addressMessage.FindString("broadcast", &string) == B_OK
|
if (addressMessage.FindString("broadcast", &string) == B_OK
|
||||||
&& parse_address(familyIndex, string, broadcast))
|
&& parse_address(familyIndex, string, broadcast))
|
||||||
hasBroadcast = true;
|
hasBroadcast = true;
|
||||||
|
}
|
||||||
|
|
||||||
// add gateway route, if we're asked for it
|
|
||||||
|
|
||||||
if (addressMessage.FindString("gateway", &string) == B_OK
|
|
||||||
&& parse_address(familyIndex, string, gateway)) {
|
|
||||||
route_entry route;
|
route_entry route;
|
||||||
memset(&route, 0, sizeof(route_entry));
|
memset(&route, 0, sizeof(route_entry));
|
||||||
route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY;
|
route.flags = RTF_STATIC | RTF_DEFAULT;
|
||||||
route.gateway = &gateway;
|
|
||||||
|
|
||||||
request.ifr_route = route;
|
request.ifr_route = route;
|
||||||
ioctl(socket, SIOCDELRT, &request, sizeof(request));
|
ioctl(socket, SIOCDELRT, &request, sizeof(request));
|
||||||
// Try to remove a previous default route, doesn't matter
|
// Try to remove a previous default route, doesn't matter
|
||||||
// if it fails.
|
// 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)) {
|
||||||
|
// add gateway route, if we're asked for it
|
||||||
|
route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY;
|
||||||
|
route.gateway = &gateway;
|
||||||
|
|
||||||
if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) {
|
if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) {
|
||||||
fprintf(stderr, "%s: Could not add route for %s: %s\n",
|
fprintf(stderr, "%s: Could not add route for %s: %s\n",
|
||||||
Name(), device, strerror(errno));
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,40 +581,16 @@ NetServer::_LooperForDevice(const char* device)
|
|||||||
status_t
|
status_t
|
||||||
NetServer::_ConfigureDevice(int socket, const char* path)
|
NetServer::_ConfigureDevice(int socket, const char* path)
|
||||||
{
|
{
|
||||||
_QuitLooperForDevice(path);
|
|
||||||
|
|
||||||
// bring interface up, but don't configure it just yet
|
// bring interface up, but don't configure it just yet
|
||||||
BMessage interface;
|
BMessage interface;
|
||||||
interface.AddString("device", path);
|
interface.AddString("device", path);
|
||||||
BMessage address;
|
BMessage address;
|
||||||
address.AddString("family", "inet");
|
address.AddString("family", "inet");
|
||||||
|
address.AddBool("auto config", true);
|
||||||
interface.AddMessage("address", &address);
|
interface.AddMessage("address", &address);
|
||||||
|
|
||||||
status_t status = _ConfigureInterface(socket, interface);
|
return _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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user