* Renamed some option to match more RFC2132 names

* dhcp_message::NextOption() now set cookie.next to NULL on exit if there is no space left
* dhcp_message::Size() now handle OPTION_OVERLOAD case
* Renamed _ToString() to _AddressToString()
* Any error message send by DHCP server will show up in syslog now
* Reorganize DHCPClient::_PrepareMessage() to make more easy to see which
  option is added per message type.
* OPTION_SERVER_ADDRESS was always added to DHCP_REQUEST, which MUST NOT
  in renewal and rebinding state according RFC 2131.
* add device name to resolver configuration: WIP for #6915...



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39650 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin
2010-11-26 17:11:22 +00:00
parent eaab4bd5e9
commit d5d2fdf0b3
2 changed files with 66 additions and 44 deletions
+64 -42
View File
@@ -5,6 +5,7 @@
* Authors: * Authors:
* Axel Dörfler, [email protected] * Axel Dörfler, [email protected]
* Vegard Wærp, [email protected] * Vegard Wærp, [email protected]
* Philippe Houdoin, <phoudoin at haiku-os dot org>
*/ */
@@ -55,10 +56,10 @@ enum message_option {
OPTION_DOMAIN_NAME_SERVER = 6, OPTION_DOMAIN_NAME_SERVER = 6,
OPTION_HOST_NAME = 12, OPTION_HOST_NAME = 12,
OPTION_DOMAIN_NAME = 15, OPTION_DOMAIN_NAME = 15,
OPTION_DATAGRAM_SIZE = 22, OPTION_MAX_DATAGRAM_SIZE = 22,
OPTION_MTU = 26, OPTION_INTERFACE_MTU = 26,
OPTION_BROADCAST_ADDRESS = 28, OPTION_BROADCAST_ADDRESS = 28,
OPTION_NETWORK_TIME_SERVERS = 42, OPTION_NETWORK_TIME_PROTOCOL_SERVERS = 42,
OPTION_NETBIOS_NAME_SERVER = 44, OPTION_NETBIOS_NAME_SERVER = 44,
OPTION_NETBIOS_SCOPE = 47, OPTION_NETBIOS_SCOPE = 47,
@@ -70,7 +71,7 @@ enum message_option {
OPTION_SERVER_ADDRESS = 54, OPTION_SERVER_ADDRESS = 54,
OPTION_REQUEST_PARAMETERS = 55, OPTION_REQUEST_PARAMETERS = 55,
OPTION_ERROR_MESSAGE = 56, OPTION_ERROR_MESSAGE = 56,
OPTION_MESSAGE_SIZE = 57, OPTION_MAX_MESSAGE_SIZE = 57,
OPTION_RENEWAL_TIME = 58, OPTION_RENEWAL_TIME = 58,
OPTION_REBINDING_TIME = 59, OPTION_REBINDING_TIME = 59,
OPTION_CLASS_IDENTIFIER = 60, OPTION_CLASS_IDENTIFIER = 60,
@@ -214,7 +215,7 @@ dhcp_message::NextOption(dhcp_option_cookie& cookie,
// handle option overload in file and/or server_name fields. // handle option overload in file and/or server_name fields.
switch (cookie.state) { switch (cookie.state) {
case 2: case 2:
// options from "file" // options from "file" field
if (cookie.file_has_options) { if (cookie.file_has_options) {
bytesLeft = sizeof(file); bytesLeft = sizeof(file);
cookie.next = file; cookie.next = file;
@@ -222,20 +223,24 @@ dhcp_message::NextOption(dhcp_option_cookie& cookie,
break; break;
case 3: case 3:
// options from "server_name" // options from "server_name" field
if (cookie.server_name_has_options) { if (cookie.server_name_has_options) {
bytesLeft = sizeof(server_name); bytesLeft = sizeof(server_name);
cookie.next = server_name; cookie.next = server_name;
} }
break; break;
case 4: default:
// no more place to look for options // no more place to look for options
// if last option is not OPTION_END,
// there is no space left for other option!
if (option != OPTION_END)
cookie.next = NULL;
return false; return false;
} }
if (bytesLeft == 0) { if (bytesLeft == 0) {
// no options for this state, try next one // no options in this state, try next one
continue; continue;
} }
} }
@@ -302,6 +307,13 @@ size_t
dhcp_message::Size() const dhcp_message::Size() const
{ {
const uint8* last = LastOption(); const uint8* last = LastOption();
if (last < options) {
// if last option is stored above "options" field, it means
// the whole options field and message is already filled...
return sizeof(dhcp_message);
}
return sizeof(dhcp_message) - sizeof(options) + last + 1 - options; return sizeof(dhcp_message) - sizeof(options) + last + 1 - options;
} }
@@ -311,7 +323,7 @@ dhcp_message::PrepareMessage(uint8 type)
{ {
uint8* next = options; uint8* next = options;
next = PutOption(next, OPTION_MESSAGE_TYPE, type); next = PutOption(next, OPTION_MESSAGE_TYPE, type);
next = PutOption(next, OPTION_MESSAGE_SIZE, next = PutOption(next, OPTION_MAX_MESSAGE_SIZE,
(uint16)htons(sizeof(dhcp_message))); (uint16)htons(sizeof(dhcp_message)));
return next; return next;
} }
@@ -350,6 +362,8 @@ uint8*
dhcp_message::PutOption(uint8* options, message_option option, dhcp_message::PutOption(uint8* options, message_option option,
const uint8* data, uint32 size) const uint8* data, uint32 size)
{ {
// TODO: check enough space is available
options[0] = option; options[0] = option;
options[1] = size; options[1] = size;
memcpy(&options[2], data, size); memcpy(&options[2], data, size);
@@ -562,7 +576,7 @@ DHCPClient::_Negotiate(dhcp_state state)
BMessage address; BMessage address;
address.AddString("family", "inet"); address.AddString("family", "inet");
address.AddString("address", _ToString(fAssignedAddress)); address.AddString("address", _AddressToString(fAssignedAddress));
fResolverConfiguration.MakeEmpty(); fResolverConfiguration.MakeEmpty();
_ParseOptions(*message, address, fResolverConfiguration); _ParseOptions(*message, address, fResolverConfiguration);
@@ -604,6 +618,7 @@ DHCPClient::_Negotiate(dhcp_state state)
// configure resolver // configure resolver
reply.MakeEmpty(); reply.MakeEmpty();
fResolverConfiguration.AddString("device", Device());
status = Target().SendMessage(&fResolverConfiguration, &reply); status = Target().SendMessage(&fResolverConfiguration, &reply);
if (status == B_OK) if (status == B_OK)
status = reply.FindInt32("status", &fStatus); status = reply.FindInt32("status", &fStatus);
@@ -673,21 +688,21 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address,
// iterate through all options // iterate through all options
switch (option) { switch (option) {
case OPTION_ROUTER_ADDRESS: case OPTION_ROUTER_ADDRESS:
address.AddString("gateway", _ToString(data)); address.AddString("gateway", _AddressToString(data));
break; break;
case OPTION_SUBNET_MASK: case OPTION_SUBNET_MASK:
address.AddString("mask", _ToString(data)); address.AddString("mask", _AddressToString(data));
break; break;
case OPTION_BROADCAST_ADDRESS: case OPTION_BROADCAST_ADDRESS:
address.AddString("broadcast", _ToString(data)); address.AddString("broadcast", _AddressToString(data));
break; break;
case OPTION_DOMAIN_NAME_SERVER: case OPTION_DOMAIN_NAME_SERVER:
{ {
for (uint32 i = 0; i < size / 4; i++) { for (uint32 i = 0; i < size / 4; i++) {
syslog(LOG_INFO, "DHCP for %s got DNS: %s\n", Device(), syslog(LOG_INFO, "DHCP for %s got DNS: %s\n", Device(),
_ToString(&data[i * 4]).String()); _AddressToString(&data[i * 4]).String());
resolverConfiguration.AddString("nameserver", resolverConfiguration.AddString("nameserver",
_ToString(&data[i * 4]).String()); _AddressToString(&data[i * 4]).String());
} }
resolverConfiguration.AddInt32("nameserver_count", resolverConfiguration.AddInt32("nameserver_count",
size / 4); size / 4);
@@ -733,6 +748,11 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address,
case OPTION_MESSAGE_TYPE: case OPTION_MESSAGE_TYPE:
break; break;
case OPTION_ERROR_MESSAGE:
syslog(LOG_INFO, "DHCP error message: \"%.*s\"\n", (int)size,
(const char*)data);
break;
default: default:
syslog(LOG_INFO, "unknown option %lu\n", (uint32)option); syslog(LOG_INFO, "unknown option %lu\n", (uint32)option);
break; break;
@@ -754,43 +774,45 @@ DHCPClient::_PrepareMessage(dhcp_message& message, dhcp_state state)
message_type type = message.Type(); message_type type = message.Type();
uint8 *next = message.PrepareMessage(type);
switch (type) { switch (type) {
case DHCP_DISCOVER:
next = message.PutOption(next, OPTION_REQUEST_PARAMETERS,
kRequestParameters, sizeof(kRequestParameters));
break;
case DHCP_REQUEST: case DHCP_REQUEST:
case DHCP_RELEASE: next = message.PutOption(next, OPTION_REQUEST_PARAMETERS,
{ kRequestParameters, sizeof(kRequestParameters));
// add server identifier option
if (state == REQUESTING) {
const sockaddr_in& server = (sockaddr_in&)fServer.SockAddr();
next = message.PutOption(next, OPTION_SERVER_ADDRESS,
(uint32)server.sin_addr.s_addr);
}
if (state == INIT || state == REQUESTING) {
next = message.PutOption(next, OPTION_REQUEST_IP_ADDRESS,
(uint32)fAssignedAddress);
} else
message.client_address = fAssignedAddress;
break;
case DHCP_RELEASE: {
const sockaddr_in& server = (sockaddr_in&)fServer.SockAddr(); const sockaddr_in& server = (sockaddr_in&)fServer.SockAddr();
uint8* next = message.PrepareMessage(type);
next = message.PutOption(next, OPTION_SERVER_ADDRESS, next = message.PutOption(next, OPTION_SERVER_ADDRESS,
(uint32)server.sin_addr.s_addr); (uint32)server.sin_addr.s_addr);
// In RENEWAL or REBINDING state, we must set the client_address field, and not message.client_address = fAssignedAddress;
// use OPTION_REQUEST_IP_ADDRESS for DHCP_REQUEST messages
if (type == DHCP_REQUEST && (state == INIT || state == REQUESTING)) {
next = message.PutOption(next, OPTION_REQUEST_IP_ADDRESS,
(uint32)fAssignedAddress);
next = message.PutOption(next, OPTION_REQUEST_PARAMETERS,
kRequestParameters, sizeof(kRequestParameters));
} else
message.client_address = fAssignedAddress;
message.FinishOptions(next);
break;
}
case DHCP_DISCOVER:
{
uint8* next = message.PrepareMessage(type);
next = message.PutOption(next, OPTION_REQUEST_PARAMETERS,
kRequestParameters, sizeof(kRequestParameters));
message.FinishOptions(next);
break; break;
} }
default: default:
// the default options are fine
break; break;
} }
message.FinishOptions(next);
} }
@@ -830,7 +852,7 @@ DHCPClient::_TimeoutShift(int socket, time_t& timeout, uint32& tries)
BString BString
DHCPClient::_ToString(const uint8* data) const DHCPClient::_AddressToString(const uint8* data) const
{ {
BString target = inet_ntoa(*(in_addr*)data); BString target = inet_ntoa(*(in_addr*)data);
return target; return target;
@@ -838,7 +860,7 @@ DHCPClient::_ToString(const uint8* data) const
BString BString
DHCPClient::_ToString(in_addr_t address) const DHCPClient::_AddressToString(in_addr_t address) const
{ {
BString target = inet_ntoa(*(in_addr*)&address); BString target = inet_ntoa(*(in_addr*)&address);
return target; return target;
+2 -2
View File
@@ -55,8 +55,8 @@ private:
bool _TimeoutShift(int socket, time_t& timeout, bool _TimeoutShift(int socket, time_t& timeout,
uint32& tries); uint32& tries);
void _RestartLease(bigtime_t lease); void _RestartLease(bigtime_t lease);
BString _ToString(const uint8* data) const; BString _AddressToString(const uint8* data) const;
BString _ToString(in_addr_t address) const; BString _AddressToString(in_addr_t address) const;
private: private:
BMessage fConfiguration; BMessage fConfiguration;