2 * Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
7 * Vegard Wærp, vegarwa@online.no
8 * Philippe Houdoin, <phoudoin at haiku-os dot org>
12 #include "DHCPClient.h"
15 #include <MessageRunner.h>
16 #include <NetworkDevice.h>
17 #include <NetworkInterface.h>
20 #include <arpa/inet.h>
26 #include <sys/sockio.h>
32 #include <MessageRunner.h>
34 #include "NetServer.h"
37 // See RFC 2131 for DHCP, see RFC 1533 for BOOTP/DHCP options
39 #define DHCP_CLIENT_PORT 68
40 #define DHCP_SERVER_PORT 67
42 #define DEFAULT_TIMEOUT 0.25 // secs
43 #define MAX_TIMEOUT 64 // secs
45 #define AS_USECS(t) (1000000 * t)
55 OPTION_MAGIC
= 0x63825363,
60 OPTION_SUBNET_MASK
= 1,
61 OPTION_TIME_OFFSET
= 2,
62 OPTION_ROUTER_ADDRESS
= 3,
63 OPTION_DOMAIN_NAME_SERVER
= 6,
64 OPTION_HOST_NAME
= 12,
65 OPTION_DOMAIN_NAME
= 15,
66 OPTION_MAX_DATAGRAM_SIZE
= 22,
67 OPTION_INTERFACE_MTU
= 26,
68 OPTION_BROADCAST_ADDRESS
= 28,
69 OPTION_NETWORK_TIME_PROTOCOL_SERVERS
= 42,
70 OPTION_NETBIOS_NAME_SERVER
= 44,
71 OPTION_NETBIOS_SCOPE
= 47,
73 // DHCP specific options
74 OPTION_REQUEST_IP_ADDRESS
= 50,
75 OPTION_ADDRESS_LEASE_TIME
= 51,
77 OPTION_MESSAGE_TYPE
= 53,
78 OPTION_SERVER_ADDRESS
= 54,
79 OPTION_REQUEST_PARAMETERS
= 55,
80 OPTION_ERROR_MESSAGE
= 56,
81 OPTION_MAX_MESSAGE_SIZE
= 57,
82 OPTION_RENEWAL_TIME
= 58,
83 OPTION_REBINDING_TIME
= 59,
84 OPTION_CLASS_IDENTIFIER
= 60,
85 OPTION_CLIENT_IDENTIFIER
= 61,
100 struct dhcp_option_cookie
{
104 file_has_options(false),
105 server_name_has_options(false)
111 bool file_has_options
;
112 bool server_name_has_options
;
115 struct dhcp_message
{
116 dhcp_message(message_type type
);
120 uint8 hardware_address_length
;
122 uint32 transaction_id
;
123 uint16 seconds_since_start
;
125 in_addr_t client_address
;
126 in_addr_t your_address
;
127 in_addr_t server_address
;
128 in_addr_t gateway_address
;
129 uint8 mac_address
[16];
130 uint8 server_name
[64];
132 uint32 options_magic
;
135 size_t MinSize() const { return 576; }
138 bool HasOptions() const;
139 bool NextOption(dhcp_option_cookie
& cookie
, message_option
& option
,
140 const uint8
*& data
, size_t& size
) const;
141 const uint8
* FindOption(message_option which
) const;
142 const uint8
* LastOption() const;
143 message_type
Type() const;
145 uint8
* PrepareMessage(uint8 type
);
146 uint8
* PutOption(uint8
* options
, message_option option
);
147 uint8
* PutOption(uint8
* options
, message_option option
, uint8 data
);
148 uint8
* PutOption(uint8
* options
, message_option option
, uint16 data
);
149 uint8
* PutOption(uint8
* options
, message_option option
, uint32 data
);
150 uint8
* PutOption(uint8
* options
, message_option option
, const uint8
* data
,
152 uint8
* FinishOptions(uint8
* options
);
154 static const char* TypeToString(message_type type
);
157 struct socket_timeout
{
158 socket_timeout(int socket
)
160 timeout(time_t(AS_USECS(DEFAULT_TIMEOUT
))),
163 UpdateSocket(socket
);
166 time_t timeout
; // in micro secs
169 bool Shift(int socket
, bigtime_t stateMaxTime
, const char* device
);
170 void UpdateSocket(int socket
) const;
173 #define DHCP_FLAG_BROADCAST 0x8000
175 #define ARP_HARDWARE_TYPE_ETHER 1
177 const uint32 kMsgLeaseTime
= 'lstm';
179 static const uint8 kRequestParameters
[] = {
180 OPTION_SUBNET_MASK
, OPTION_ROUTER_ADDRESS
,
181 OPTION_DOMAIN_NAME_SERVER
, OPTION_BROADCAST_ADDRESS
,
186 dhcp_message::dhcp_message(message_type type
)
188 // ASSERT(this == offsetof(this, opcode));
189 memset(this, 0, sizeof(*this));
190 options_magic
= htonl(OPTION_MAGIC
);
192 uint8
* next
= PrepareMessage(type
);
198 dhcp_message::HasOptions() const
200 return options_magic
== htonl(OPTION_MAGIC
);
205 dhcp_message::NextOption(dhcp_option_cookie
& cookie
,
206 message_option
& option
, const uint8
*& data
, size_t& size
) const
211 if (cookie
.state
== 0) {
213 cookie
.next
= options
;
216 uint32 bytesLeft
= 0;
218 switch (cookie
.state
) {
220 // options from "options"
221 bytesLeft
= sizeof(options
) - (cookie
.next
- options
);
225 // options from "file"
226 bytesLeft
= sizeof(file
) - (cookie
.next
- file
);
230 // options from "server_name"
231 bytesLeft
= sizeof(server_name
) - (cookie
.next
- server_name
);
236 if (bytesLeft
== 0) {
239 // handle option overload in file and/or server_name fields.
240 switch (cookie
.state
) {
242 // options from "file" field
243 if (cookie
.file_has_options
) {
244 bytesLeft
= sizeof(file
);
250 // options from "server_name" field
251 if (cookie
.server_name_has_options
) {
252 bytesLeft
= sizeof(server_name
);
253 cookie
.next
= server_name
;
258 // no more place to look for options
259 // if last option is not OPTION_END,
260 // there is no space left for other option!
261 if (option
!= OPTION_END
)
266 if (bytesLeft
== 0) {
267 // no options in this state, try next one
272 option
= (message_option
)cookie
.next
[0];
273 if (option
== OPTION_END
) {
276 } else if (option
== OPTION_PAD
) {
282 size
= cookie
.next
[1];
283 data
= &cookie
.next
[2];
284 cookie
.next
+= 2 + size
;
285 bytesLeft
-= 2 + size
;
287 if (option
== OPTION_OVERLOAD
) {
288 cookie
.file_has_options
= data
[0] & 1;
289 cookie
.server_name_has_options
= data
[0] & 2;
299 dhcp_message::FindOption(message_option which
) const
301 dhcp_option_cookie cookie
;
302 message_option option
;
305 while (NextOption(cookie
, option
, data
, size
)) {
306 // iterate through all options
316 dhcp_message::LastOption() const
318 dhcp_option_cookie cookie
;
319 message_option option
;
322 while (NextOption(cookie
, option
, data
, size
)) {
323 // iterate through all options
331 dhcp_message::Type() const
333 const uint8
* data
= FindOption(OPTION_MESSAGE_TYPE
);
335 return (message_type
)data
[0];
342 dhcp_message::Size() const
344 const uint8
* last
= LastOption();
346 if (last
< options
) {
347 // if last option is stored above "options" field, it means
348 // the whole options field and message is already filled...
349 return sizeof(dhcp_message
);
352 return sizeof(dhcp_message
) - sizeof(options
) + last
+ 1 - options
;
357 dhcp_message::PrepareMessage(uint8 type
)
359 uint8
* next
= options
;
360 next
= PutOption(next
, OPTION_MESSAGE_TYPE
, type
);
361 next
= PutOption(next
, OPTION_MAX_MESSAGE_SIZE
,
362 (uint16
)htons(sizeof(dhcp_message
)));
368 dhcp_message::PutOption(uint8
* options
, message_option option
)
376 dhcp_message::PutOption(uint8
* options
, message_option option
, uint8 data
)
378 return PutOption(options
, option
, &data
, 1);
383 dhcp_message::PutOption(uint8
* options
, message_option option
, uint16 data
)
385 return PutOption(options
, option
, (uint8
*)&data
, sizeof(data
));
390 dhcp_message::PutOption(uint8
* options
, message_option option
, uint32 data
)
392 return PutOption(options
, option
, (uint8
*)&data
, sizeof(data
));
397 dhcp_message::PutOption(uint8
* options
, message_option option
,
398 const uint8
* data
, uint32 size
)
400 // TODO: check enough space is available
404 memcpy(&options
[2], data
, size
);
406 return options
+ 2 + size
;
411 dhcp_message::FinishOptions(uint8
* options
)
413 return PutOption(options
, OPTION_END
);
417 /*static*/ const char*
418 dhcp_message::TypeToString(message_type type
)
421 #define CASE(x) case x: return #x;
439 socket_timeout::UpdateSocket(int socket
) const
441 struct timeval value
;
442 value
.tv_sec
= timeout
/ 1000000;
443 value
.tv_usec
= timeout
% 1000000;
444 setsockopt(socket
, SOL_SOCKET
, SO_RCVTIMEO
, &value
, sizeof(value
));
449 socket_timeout::Shift(int socket
, bigtime_t stateMaxTime
, const char* device
)
453 if (timeout
> AS_USECS(MAX_TIMEOUT
))
454 timeout
= AS_USECS(MAX_TIMEOUT
);
456 if (tries
> MAX_RETRIES
) {
457 if (stateMaxTime
== -1)
459 bigtime_t remaining
= (stateMaxTime
- system_time()) / 2 + 1;
460 timeout
= std::max(remaining
, bigtime_t(60));
463 syslog(LOG_DEBUG
, "%s: Timeout shift: %lu secs (try %lu)\n",
464 device
, timeout
, tries
);
466 UpdateSocket(socket
);
474 DHCPClient::DHCPClient(BMessenger target
, const char* device
)
476 AutoconfigClient("dhcp", target
, device
),
477 fConfiguration(kMsgConfigureInterface
),
478 fResolverConfiguration(kMsgConfigureResolver
),
481 fServer(AF_INET
, NULL
, DHCP_SERVER_PORT
, B_UNCONFIGURED_ADDRESS_FAMILIES
),
484 fTransactionID
= (uint32
)system_time() ^ rand();
486 BNetworkAddress link
;
487 BNetworkInterface
interface(device
);
488 fStatus
= interface
.GetHardwareAddress(link
);
492 memcpy(fMAC
, link
.LinkLevelAddress(), sizeof(fMAC
));
494 if ((interface
.Flags() & IFF_AUTO_CONFIGURED
) != 0) {
495 // Check for interface previous auto-configured address, if any.
496 BNetworkInterfaceAddress interfaceAddress
;
497 int index
= interface
.FindFirstAddress(AF_INET
);
499 && interface
.GetAddressAt(index
, interfaceAddress
) == B_OK
) {
500 BNetworkAddress address
= interfaceAddress
.Address();
501 const sockaddr_in
& addr
= (sockaddr_in
&)address
.SockAddr();
502 fAssignedAddress
= addr
.sin_addr
.s_addr
;
504 if ((ntohl(fAssignedAddress
) & IN_CLASSB_NET
) == 0xa9fe0000) {
505 // previous auto-configured address is a link-local one:
506 // there is no point asking a DHCP server to renew such
507 // server-less assigned address...
508 fAssignedAddress
= 0;
513 openlog_thread("DHCP", 0, LOG_DAEMON
);
517 DHCPClient::~DHCPClient()
524 int socket
= ::socket(AF_INET
, SOCK_DGRAM
, 0);
530 dhcp_message
release(DHCP_RELEASE
);
531 _PrepareMessage(release
, BOUND
);
533 _SendMessage(socket
, release
, fServer
);
541 DHCPClient::Initialize()
543 fStatus
= _Negotiate(fAssignedAddress
== 0 ? INIT
: INIT_REBOOT
);
544 syslog(LOG_DEBUG
, "%s: DHCP status = %s\n", Device(), strerror(fStatus
));
550 DHCPClient::_Negotiate(dhcp_state state
)
555 fStartTime
= system_time();
558 char hostName
[MAXHOSTNAMELEN
];
559 if (gethostname(hostName
, MAXHOSTNAMELEN
) == 0)
560 fHostName
.SetTo(hostName
, MAXHOSTNAMELEN
);
562 fHostName
.Truncate(0);
564 int socket
= ::socket(AF_INET
, SOCK_DGRAM
, 0);
568 // Enable reusing the port. This is needed in case there is more
569 // than 1 interface that needs to be configured. Note that the only reason
570 // this works is because there is code below to bind to a specific
573 setsockopt(socket
, SOL_SOCKET
, SO_REUSEPORT
, &option
, sizeof(option
));
575 BNetworkAddress local
;
576 local
.SetToWildcard(AF_INET
, DHCP_CLIENT_PORT
);
579 setsockopt(socket
, SOL_SOCKET
, SO_BROADCAST
, &option
, sizeof(option
));
581 if (bind(socket
, local
, local
.Length()) < 0) {
586 bigtime_t previousLeaseTime
= fLeaseTime
;
588 status_t status
= B_OK
;
589 while (state
!= BOUND
) {
590 status
= _StateTransition(socket
, state
);
591 if (status
!= B_OK
&& (state
== SELECTING
|| state
== REBOOTING
))
598 fLeaseTime
= previousLeaseTime
;
602 if (fRenewalTime
== 0)
603 fRenewalTime
= fLeaseTime
/ 2;
604 if (fRebindingTime
== 0)
605 fRebindingTime
= fLeaseTime
* 7 / 8;
606 fLeaseTime
+= fRequestTime
;
607 fRenewalTime
+= fRequestTime
;
608 fRebindingTime
+= fRequestTime
;
609 _RestartLease(fRenewalTime
);
615 // configure interface
617 status
= Target().SendMessage(&fConfiguration
, &reply
);
619 status
= reply
.FindInt32("status", &fStatus
);
621 // configure resolver
623 fResolverConfiguration
.AddString("device", Device());
624 status
= Target().SendMessage(&fResolverConfiguration
, &reply
);
626 status
= reply
.FindInt32("status", &fStatus
);
632 DHCPClient::_GotMessage(dhcp_state
& state
, dhcp_message
* message
)
636 if (message
->Type() == DHCP_OFFER
) {
639 fAssignedAddress
= message
->your_address
;
640 syslog(LOG_INFO
, " your_address: %s\n",
641 _AddressToString(fAssignedAddress
).String());
643 fConfiguration
.MakeEmpty();
644 fConfiguration
.AddString("device", Device());
645 fConfiguration
.AddBool("auto_configured", true);
648 address
.AddString("family", "inet");
649 address
.AddString("address", _AddressToString(fAssignedAddress
));
650 fResolverConfiguration
.MakeEmpty();
651 _ParseOptions(*message
, address
, fResolverConfiguration
);
653 fConfiguration
.AddMessage("address", &address
);
663 if (message
->Type() == DHCP_ACK
) {
664 // TODO: we might want to configure the stuff, don't we?
666 fResolverConfiguration
.MakeEmpty();
667 _ParseOptions(*message
, address
, fResolverConfiguration
);
668 // TODO: currently, only lease time and DNS is updated this
671 // our address request has been acknowledged
677 if (message
->Type() == DHCP_NACK
) {
678 // server reject our request on previous assigned address
679 // back to square one...
680 fAssignedAddress
= 0;
692 DHCPClient::_StateTransition(int socket
, dhcp_state
& state
)
695 // The local interface does not have an address yet, bind the socket
696 // to the device directly.
697 BNetworkDevice
device(Device());
698 int index
= device
.Index();
700 setsockopt(socket
, SOL_SOCKET
, SO_BINDTODEVICE
, &index
, sizeof(int));
703 BNetworkAddress broadcast
;
704 broadcast
.SetToBroadcast(AF_INET
, DHCP_SERVER_PORT
);
706 socket_timeout
timeout(socket
);
708 dhcp_message
discover(DHCP_DISCOVER
);
709 _PrepareMessage(discover
, state
);
711 dhcp_message
request(DHCP_REQUEST
);
712 _PrepareMessage(request
, state
);
714 bool skipRequest
= false;
715 dhcp_state originalState
= state
;
716 fRequestTime
= system_time();
719 _SendMessage(socket
, originalState
== INIT
? discover
: request
,
720 originalState
== RENEWING
? fServer
: broadcast
);
722 if (originalState
== INIT
)
724 else if (originalState
== INIT_REBOOT
)
729 struct sockaddr_in from
;
730 socklen_t fromLength
= sizeof(from
);
731 ssize_t bytesReceived
= recvfrom(socket
, buffer
, sizeof(buffer
),
732 0, (struct sockaddr
*)&from
, &fromLength
);
733 if (bytesReceived
< 0 && errno
== B_TIMED_OUT
) {
734 // depending on the state, we'll just try again
735 if (!_TimeoutShift(socket
, state
, timeout
))
739 } else if (bytesReceived
< 0)
743 dhcp_message
* message
= (dhcp_message
*)buffer
;
744 if (message
->transaction_id
!= htonl(fTransactionID
)
745 || !message
->HasOptions()
746 || memcmp(message
->mac_address
, discover
.mac_address
,
747 discover
.hardware_address_length
)) {
748 // this message is not for us
752 syslog(LOG_DEBUG
, "%s: Received %s from %s\n",
753 Device(), dhcp_message::TypeToString(message
->Type()),
754 _AddressToString(from
.sin_addr
.s_addr
).String());
756 if (_GotMessage(state
, message
) == B_OK
)
765 DHCPClient::_RestartLease(bigtime_t leaseTime
)
770 BMessage
lease(kMsgLeaseTime
);
771 fRunner
= new BMessageRunner(this, &lease
, leaseTime
- system_time(), 1);
776 DHCPClient::_ParseOptions(dhcp_message
& message
, BMessage
& address
,
777 BMessage
& resolverConfiguration
)
779 dhcp_option_cookie cookie
;
780 message_option option
;
783 while (message
.NextOption(cookie
, option
, data
, size
)) {
784 // iterate through all options
786 case OPTION_ROUTER_ADDRESS
:
787 syslog(LOG_DEBUG
, " gateway: %s\n",
788 _AddressToString(data
).String());
789 address
.AddString("gateway", _AddressToString(data
));
791 case OPTION_SUBNET_MASK
:
792 syslog(LOG_DEBUG
, " subnet: %s\n",
793 _AddressToString(data
).String());
794 address
.AddString("mask", _AddressToString(data
));
796 case OPTION_BROADCAST_ADDRESS
:
797 syslog(LOG_DEBUG
, " broadcast: %s\n",
798 _AddressToString(data
).String());
799 address
.AddString("broadcast", _AddressToString(data
));
801 case OPTION_DOMAIN_NAME_SERVER
:
803 for (uint32 i
= 0; i
< size
/ 4; i
++) {
804 syslog(LOG_DEBUG
, " nameserver[%d]: %s\n", i
,
805 _AddressToString(&data
[i
* 4]).String());
806 resolverConfiguration
.AddString("nameserver",
807 _AddressToString(&data
[i
* 4]).String());
809 resolverConfiguration
.AddInt32("nameserver_count",
813 case OPTION_SERVER_ADDRESS
:
815 syslog(LOG_DEBUG
, " server: %s\n",
816 _AddressToString(data
).String());
817 status_t status
= fServer
.SetAddress(*(in_addr_t
*)data
);
818 if (status
!= B_OK
) {
819 syslog(LOG_ERR
, " BNetworkAddress::SetAddress failed with %s!\n",
826 case OPTION_ADDRESS_LEASE_TIME
:
827 syslog(LOG_DEBUG
, " lease time: %lu seconds\n",
828 ntohl(*(uint32
*)data
));
829 fLeaseTime
= ntohl(*(uint32
*)data
) * 1000000LL;
831 case OPTION_RENEWAL_TIME
:
832 syslog(LOG_DEBUG
, " renewal time: %lu seconds\n",
833 ntohl(*(uint32
*)data
));
834 fRenewalTime
= ntohl(*(uint32
*)data
) * 1000000LL;
836 case OPTION_REBINDING_TIME
:
837 syslog(LOG_DEBUG
, " rebinding time: %lu seconds\n",
838 ntohl(*(uint32
*)data
));
839 fRebindingTime
= ntohl(*(uint32
*)data
) * 1000000LL;
842 case OPTION_HOST_NAME
:
843 syslog(LOG_DEBUG
, " host name: \"%.*s\"\n", (int)size
,
847 case OPTION_DOMAIN_NAME
:
850 strlcpy(domain
, (const char*)data
,
851 min_c(size
+ 1, sizeof(domain
)));
853 syslog(LOG_DEBUG
, " domain name: \"%s\"\n", domain
);
855 resolverConfiguration
.AddString("domain", domain
);
859 case OPTION_MESSAGE_TYPE
:
862 case OPTION_ERROR_MESSAGE
:
863 syslog(LOG_INFO
, " error message: \"%.*s\"\n", (int)size
,
868 syslog(LOG_DEBUG
, " UNKNOWN OPTION %lu (0x%x)\n",
869 (uint32
)option
, (uint32
)option
);
877 DHCPClient::_PrepareMessage(dhcp_message
& message
, dhcp_state state
)
879 message
.opcode
= BOOT_REQUEST
;
880 message
.hardware_type
= ARP_HARDWARE_TYPE_ETHER
;
881 message
.hardware_address_length
= 6;
882 message
.transaction_id
= htonl(fTransactionID
);
883 message
.seconds_since_start
= htons(min_c((system_time() - fStartTime
)
884 / 1000000LL, 65535));
885 memcpy(message
.mac_address
, fMAC
, 6);
887 message_type type
= message
.Type();
889 uint8
*next
= message
.PrepareMessage(type
);
893 next
= message
.PutOption(next
, OPTION_REQUEST_PARAMETERS
,
894 kRequestParameters
, sizeof(kRequestParameters
));
896 if (fHostName
.Length() > 0) {
897 next
= message
.PutOption(next
, OPTION_HOST_NAME
,
898 reinterpret_cast<const uint8
*>(fHostName
.String()),
904 next
= message
.PutOption(next
, OPTION_REQUEST_PARAMETERS
,
905 kRequestParameters
, sizeof(kRequestParameters
));
907 if (fHostName
.Length() > 0) {
908 next
= message
.PutOption(next
, OPTION_HOST_NAME
,
909 reinterpret_cast<const uint8
*>(fHostName
.String()),
913 if (state
== REQUESTING
) {
914 const sockaddr_in
& server
= (sockaddr_in
&)fServer
.SockAddr();
915 next
= message
.PutOption(next
, OPTION_SERVER_ADDRESS
,
916 (uint32
)server
.sin_addr
.s_addr
);
919 if (state
== INIT
|| state
== INIT_REBOOT
920 || state
== REQUESTING
) {
921 next
= message
.PutOption(next
, OPTION_REQUEST_IP_ADDRESS
,
922 (uint32
)fAssignedAddress
);
924 message
.client_address
= fAssignedAddress
;
928 const sockaddr_in
& server
= (sockaddr_in
&)fServer
.SockAddr();
929 next
= message
.PutOption(next
, OPTION_SERVER_ADDRESS
,
930 (uint32
)server
.sin_addr
.s_addr
);
932 message
.client_address
= fAssignedAddress
;
940 message
.FinishOptions(next
);
945 DHCPClient::_TimeoutShift(int socket
, dhcp_state
& state
,
946 socket_timeout
& timeout
)
948 bigtime_t stateMaxTime
= -1;
949 if (state
== RENEWING
)
950 stateMaxTime
= fRebindingTime
;
951 else if (state
== REBINDING
)
952 stateMaxTime
= fLeaseTime
;
954 if (system_time() > stateMaxTime
) {
955 state
= state
== REBINDING
? INIT
: REBINDING
;
959 return timeout
.Shift(socket
, stateMaxTime
, Device());
964 DHCPClient::_AddressToString(const uint8
* data
)
966 BString target
= inet_ntoa(*(in_addr
*)data
);
972 DHCPClient::_AddressToString(in_addr_t address
)
974 BString target
= inet_ntoa(*(in_addr
*)&address
);
980 DHCPClient::_SendMessage(int socket
, dhcp_message
& message
,
981 const BNetworkAddress
& address
) const
983 message_type type
= message
.Type();
985 text
<< dhcp_message::TypeToString(type
);
987 const uint8
* requestAddress
= message
.FindOption(OPTION_REQUEST_IP_ADDRESS
);
988 if (type
== DHCP_REQUEST
&& requestAddress
!= NULL
)
989 text
<< " for " << _AddressToString(requestAddress
).String();
991 syslog(LOG_DEBUG
, "%s: Send %s to %s\n", Device(), text
.String(),
992 address
.ToString().String());
994 ssize_t bytesSent
= sendto(socket
, &message
, message
.Size(),
995 address
.IsBroadcast() ? MSG_BCAST
: 0, address
, address
.Length());
1004 DHCPClient::_CurrentState() const
1006 bigtime_t now
= system_time();
1008 if (now
> fLeaseTime
|| fStatus
!= B_OK
)
1010 if (now
>= fRebindingTime
)
1012 if (now
>= fRenewalTime
)
1019 DHCPClient::MessageReceived(BMessage
* message
)
1021 switch (message
->what
) {
1023 _Negotiate(_CurrentState());
1027 BHandler::MessageReceived(message
);