join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
dhcp.hpp
Go to the documentation of this file.
1
24#ifndef JOIN_FABRIC_DHCP_HPP
25#define JOIN_FABRIC_DHCP_HPP
26
27// libjoin.
29#include <join/dhcp_message.hpp>
30#include <join/condition.hpp>
31#include <join/reactor.hpp>
32#include <join/utils.hpp>
33#include <join/error.hpp>
34#include <join/arp.hpp>
35
36// C++.
37#include <unordered_map>
38#include <system_error>
39#include <chrono>
40#include <string>
41#include <vector>
42
43// C.
44#include <net/ethernet.h>
45#include <netinet/ip.h>
46#include <netinet/udp.h>
47#include <net/if.h>
48
49namespace join
50{
54 template <class Protocol>
55 class BasicDhcp : public EventHandler
56 {
57 public:
58 using Socket = typename Protocol::Socket;
59
63 BasicDhcp () = delete;
64
71 explicit BasicDhcp (const std::string& interface, Reactor& reactor = ReactorThread::reactor ())
72 : _buffer (std::make_unique<char[]> (sizeof (Frame) + Protocol::maxMsgSize))
75 , _reactor (reactor)
76 {
77 if (::if_nametoindex (_interface.c_str ()) == 0)
78 {
79 throw std::system_error (errno, std::system_category (), "dhcp interface lookup failed");
80 }
81
82 if (_socket.bind (_interface) == -1 || _socket.setOption (Socket::Broadcast, 1) == -1)
83 {
84 throw std::system_error (lastError, "dhcp socket setup failed"); // LCOV_EXCL_LINE
85 }
86
87 _reactor.addHandler (_socket.handle (), this);
88 }
89
94 BasicDhcp (const BasicDhcp& other) = delete;
95
101 BasicDhcp& operator= (const BasicDhcp& other) = delete;
102
107 BasicDhcp (BasicDhcp&& other) = delete;
108
114 BasicDhcp& operator= (BasicDhcp&& other) = delete;
115
119 virtual ~BasicDhcp ()
120 {
121 _reactor.delHandler (_socket.handle ());
122 }
123
128 const std::string& interface () const noexcept
129 {
130 return _interface;
131 }
132
137 const MacAddress& hardware () const noexcept
138 {
139 return _hardware;
140 }
141
142 protected:
146 struct __attribute__ ((packed)) Frame
147 {
148 struct ethhdr eth;
149 struct iphdr ip;
150 struct udphdr udp;
151 };
152
156 struct __attribute__ ((packed)) Pseudo
157 {
158 uint32_t source;
159 uint32_t destination;
160 uint8_t zero;
161 uint8_t protocol;
162 uint16_t length;
163 };
164
169 virtual void onMessage (DhcpPacket::Ptr packet) = 0;
170
175 void onReadable ([[maybe_unused]] int fd) override final
176 {
177 ssize_t size = _socket.read (_buffer.get (), sizeof (Frame) + Protocol::maxMsgSize);
178 if (size <= 0)
179 {
180 return; // LCOV_EXCL_LINE
181 }
182
183 DhcpPacket::Ptr packet = receive (_buffer.get (), static_cast<size_t> (size));
184 if (packet != nullptr)
185 {
186 onMessage (std::move (packet));
187 }
188 }
189
197 static uint16_t udpChecksum (const Frame& frame, const char* payload, size_t size)
198 {
199 Pseudo pseudo = {};
200 pseudo.source = frame.ip.saddr;
201 pseudo.destination = frame.ip.daddr;
202 pseudo.protocol = IPPROTO_UDP;
203 pseudo.length = frame.udp.len;
204
205 std::vector<uint8_t> scratch (sizeof (pseudo) + sizeof (frame.udp) + size, 0);
206 ::memcpy (scratch.data (), &pseudo, sizeof (pseudo));
207 ::memcpy (scratch.data () + sizeof (pseudo), &frame.udp, sizeof (frame.udp));
208 ::memcpy (scratch.data () + sizeof (pseudo) + sizeof (frame.udp), payload, size);
209
210 uint16_t sum = join::checksum (reinterpret_cast<const uint16_t*> (scratch.data ()), scratch.size ());
211
212 return sum ? sum : 0xffff;
213 }
214
222 int transmit (const DhcpPacket& packet, const IpAddress& source, const IpAddress& destination)
223 {
224 std::stringstream data;
225 if (_message.serialize (packet, data) == -1)
226 {
227 return -1; // LCOV_EXCL_LINE
228 }
229
230 const std::string payload = data.str ();
231
232 if (payload.size () > Protocol::maxMsgSize)
233 {
234 // LCOV_EXCL_START
236 return -1;
237 // LCOV_EXCL_STOP
238 }
239
240 const size_t size = sizeof (Frame) + payload.size ();
241
242 std::vector<char> buffer (size, 0);
243 Frame* frame = reinterpret_cast<Frame*> (buffer.data ());
244 ::memcpy (buffer.data () + sizeof (Frame), payload.data (), payload.size ());
245
246 const bool boot = (packet.op == DhcpMessage::BootRequest);
247 const uint16_t datagram = static_cast<uint16_t> (sizeof (frame->udp) + payload.size ());
248
249 frame->udp.source = htons (boot ? Protocol::clientPort : Protocol::serverPort);
250 frame->udp.dest = htons (boot ? Protocol::serverPort : Protocol::clientPort);
251 frame->udp.len = htons (datagram);
252 frame->udp.check = 0;
253
254 frame->ip.version = IPVERSION;
255 frame->ip.ihl = sizeof (frame->ip) >> 2;
256 frame->ip.tos = IPTOS_CLASS_CS6 | IPTOS_ECN_NOT_ECT;
257 frame->ip.tot_len = htons (static_cast<uint16_t> (sizeof (frame->ip) + datagram));
258 frame->ip.frag_off = htons (IP_DF);
259 frame->ip.ttl = IPDEFTTL;
260 frame->ip.protocol = IPPROTO_UDP;
261 ::memcpy (&frame->ip.saddr, source.addr (), sizeof (frame->ip.saddr));
262 ::memcpy (&frame->ip.daddr, destination.addr (), sizeof (frame->ip.daddr));
263 frame->ip.check = 0;
264 frame->ip.check = join::checksum (reinterpret_cast<const uint16_t*> (&frame->ip), sizeof (frame->ip));
265
266 frame->udp.check = udpChecksum (*frame, payload.data (), payload.size ());
267
268 ::memcpy (frame->eth.h_dest, packet.dest.addr (), ETH_ALEN);
269 ::memcpy (frame->eth.h_source, packet.src.addr (), ETH_ALEN);
270 frame->eth.h_proto = htons (ETH_P_IP);
271
272 return (_socket.write (buffer.data (), size) == -1) ? -1 : 0;
273 }
274
281 DhcpPacket::Ptr receive (const char* data, size_t size) const
282 {
283 if (size < sizeof (Frame) + DhcpMessage::headerSize)
284 {
285 return nullptr;
286 }
287
288 Frame frame;
289 ::memcpy (&frame, data, sizeof (frame));
290
291 if ((frame.eth.h_proto != htons (ETH_P_IP)) || (frame.ip.version != IPVERSION) ||
292 (frame.ip.ihl != (sizeof (frame.ip) >> 2)) || (frame.ip.protocol != IPPROTO_UDP))
293 {
294 return nullptr;
295 }
296
297 struct iphdr header = frame.ip;
298 const uint16_t check = header.check;
299 header.check = 0;
300
301 if (check != join::checksum (reinterpret_cast<const uint16_t*> (&header), sizeof (header)))
302 {
303 return nullptr;
304 }
305
306 if (((frame.udp.source != htons (Protocol::serverPort)) ||
307 (frame.udp.dest != htons (Protocol::clientPort))) &&
308 ((frame.udp.source != htons (Protocol::clientPort)) ||
309 (frame.udp.dest != htons (Protocol::serverPort))))
310 {
311 return nullptr;
312 }
313
314 const size_t datagram = ntohs (frame.udp.len);
315 const size_t available = size - sizeof (frame.eth) - sizeof (frame.ip);
316
317 if ((datagram < sizeof (frame.udp)) || (datagram > available))
318 {
319 return nullptr;
320 }
321
322 const char* payload = data + sizeof (Frame);
323 const size_t payloadSize = datagram - sizeof (frame.udp);
324
325 if (frame.udp.check)
326 {
327 Frame probe = frame;
328 probe.udp.check = 0;
329
330 if (frame.udp.check != udpChecksum (probe, payload, payloadSize))
331 {
332 return nullptr;
333 }
334 }
335
336 std::stringstream stream;
337 stream.rdbuf ()->pubsetbuf (const_cast<char*> (payload), payloadSize);
338
339 DhcpPacket::Ptr packet = std::make_unique<DhcpPacket> ();
340 if (_message.deserialize (*packet, stream) == -1)
341 {
342 return nullptr;
343 }
344
345 packet->src = MacAddress (frame.eth.h_source, ETH_ALEN);
346 packet->dest = MacAddress (frame.eth.h_dest, ETH_ALEN);
347
348 return packet;
349 }
350
353
356
358 std::unique_ptr<char[]> _buffer;
359
361 const std::string _interface;
362
365
368 };
369
373 template <class Protocol>
374 class BasicDhcpClient : public BasicDhcp<Protocol>
375 {
376 public:
377 using BasicDhcp<Protocol>::hardware;
378 using BasicDhcp<Protocol>::interface;
379 using BasicDhcp<Protocol>::transmit;
380
384 BasicDhcpClient () = delete;
385
395 explicit BasicDhcpClient (const std::string& interface, uint16_t maxSize = 0, const std::string& hostname = {},
396 Reactor& reactor = ReactorThread::reactor ())
397 : BasicDhcp<Protocol> (interface, reactor)
398 , _hostname (hostname)
399 , _maxSize (maxSize)
400 {
402 {
403 throw std::system_error (make_error_code (Errc::InvalidParam),
404 "dhcp maximum message size is too small");
405 }
406 }
407
411 virtual ~BasicDhcpClient () = default;
412
418 DhcpPacket compose (uint8_t type) const
419 {
420 DhcpPacket packet;
421
423 packet.id = randomize<uint32_t> ();
424 packet.hardware = hardware ();
425 packet.src = hardware ();
427
430
431 if (!_hostname.empty ())
432 {
434 }
435
436 if (_maxSize)
437 {
439 }
440
441 return packet;
442 }
443
452 DhcpPacket::Ptr exchange (DhcpPacket& request, const IpAddress& destination, uint8_t expected,
453 std::chrono::milliseconds timeout = std::chrono::seconds (1))
454 {
456
457 _reason.clear ();
458
459 auto inserted = _pending.emplace (request.id, std::make_unique<PendingRequest> ());
460 if (!inserted.second)
461 {
462 // LCOV_EXCL_START
463 lastError = make_error_code (Errc::InUse);
464 return nullptr;
465 // LCOV_EXCL_STOP
466 }
467
468 PendingRequest* pending = inserted.first->second.get ();
469
470 if (transmit (request, request.client, destination) == -1)
471 {
472 // LCOV_EXCL_START
473 _pending.erase (request.id);
474 return nullptr;
475 // LCOV_EXCL_STOP
476 }
477
478 if (!pending->cond.timedWait (lock, timeout, [pending] {
479 return pending->answer != nullptr;
480 }))
481 {
482 _pending.erase (request.id);
483 lastError = make_error_code (Errc::TimedOut);
484 return nullptr;
485 }
486
487 DhcpPacket::Ptr answer = std::move (pending->answer);
488 _pending.erase (request.id);
489
490 const uint8_t* type = answer->options.getIf<uint8_t> (DhcpOption::DhcpMessageType);
491 if (type == nullptr)
492 {
494 return nullptr;
495 }
496
497 if (*type == DhcpMessage::Nak)
498 {
499 const std::string* message = answer->options.getIf<std::string> (DhcpOption::Message);
500 if (message != nullptr)
501 {
502 _reason = *message;
503 }
504
506 return nullptr;
507 }
508
509 if (*type != expected)
510 {
512 return nullptr;
513 }
514
515 return answer;
516 }
517
522 std::string reason () const
523 {
525
526 return _reason;
527 }
528
536 std::chrono::milliseconds timeout = std::chrono::seconds (1))
537 {
539
541
542 if (!wants.isWildcard ())
543 {
545 }
546
548 }
549
557 DhcpPacket::Ptr request (const IpAddress& wants, const IpAddress& server,
558 std::chrono::milliseconds timeout = std::chrono::seconds (1))
559 {
561
565
566 return exchange (out, IpAddress::ipv4Broadcast, DhcpMessage::Ack, timeout);
567 }
568
576 DhcpPacket::Ptr renew (const IpAddress& client, const IpAddress& server,
577 std::chrono::milliseconds timeout = std::chrono::seconds (1))
578 {
579 MacAddress mac = Arp::get (interface (), server, timeout);
580 if (mac.isWildcard ())
581 {
582 return nullptr;
583 }
584
586
587 out.dest = mac;
588 out.client = client;
590
591 return exchange (out, server, DhcpMessage::Ack, timeout);
592 }
593
600 DhcpPacket::Ptr inform (const IpAddress& client, std::chrono::milliseconds timeout = std::chrono::seconds (1))
601 {
603
604 out.client = client;
606
607 return exchange (out, IpAddress::ipv4Broadcast, DhcpMessage::Ack, timeout);
608 }
609
617 int release (const IpAddress& client, const IpAddress& server,
618 std::chrono::milliseconds timeout = std::chrono::seconds (1))
619 {
620 MacAddress mac = Arp::get (interface (), server, timeout);
621 if (mac.isWildcard ())
622 {
623 return -1;
624 }
625
627
628 out.dest = mac;
629 out.client = client;
631
632 return transmit (out, client, server);
633 }
634
642 int decline (const IpAddress& address, const IpAddress& server, const std::string& message = {})
643 {
645
648
649 if (!message.empty ())
650 {
651 out.options.insert (DhcpOption::Message, message);
652 }
653
655 }
656
657 protected:
662 void onMessage (DhcpPacket::Ptr packet) override final
663 {
664 if (packet->op != DhcpMessage::BootReply)
665 {
666 return;
667 }
668
670
671 auto it = _pending.find (packet->id);
672 if (it != _pending.end ())
673 {
674 it->second->answer = std::move (packet);
675 it->second->cond.signal ();
676 }
677 }
678
690
693
695 std::unordered_map<uint32_t, std::unique_ptr<PendingRequest>> _pending;
696
699
701 std::string _reason;
702
704 const std::string _hostname;
705
707 const uint16_t _maxSize;
708 };
709
710 template <class Protocol>
714
718 template <class Protocol>
719 class BasicDhcpServer : public BasicDhcp<Protocol>
720 {
721 public:
722 using BasicDhcp<Protocol>::hardware;
723 using BasicDhcp<Protocol>::interface;
724 using BasicDhcp<Protocol>::transmit;
725
729 BasicDhcpServer () = delete;
730
737 explicit BasicDhcpServer (const std::string& interface, Reactor& reactor = ReactorThread::reactor ())
738 : BasicDhcp<Protocol> (interface, reactor)
739 {
740 }
741
745 virtual ~BasicDhcpServer () = default;
746
754 int offer (const DhcpPacket& request, const IpAddress& address, const DhcpOption& options = {})
755 {
756 return reply (request, DhcpMessage::Offer, address, options);
757 }
758
766 int ack (const DhcpPacket& request, const IpAddress& address, const DhcpOption& options = {})
767 {
768 return reply (request, DhcpMessage::Ack, address, options);
769 }
770
777 int nak (const DhcpPacket& request, const std::string& message = {})
778 {
779 DhcpOption options;
780
781 if (!message.empty ())
782 {
783 options.insert (DhcpOption::Message, message);
784 }
785
786 return reply (request, DhcpMessage::Nak, IpAddress::ipv4Wildcard, options);
787 }
788
789 protected:
794 virtual void onDiscover (const DhcpPacket& request) = 0;
795
800 virtual void onRequest (const DhcpPacket& request) = 0;
801
806 virtual void onRelease (const DhcpPacket& request) = 0;
807
812 virtual void onDecline (const DhcpPacket& request) = 0;
813
818 virtual void onInform (const DhcpPacket& request) = 0;
819
824 void onMessage (DhcpPacket::Ptr packet) override final
825 {
826 if (packet->op != DhcpMessage::BootRequest)
827 {
828 return;
829 }
830
831 const uint8_t* type = packet->options.getIf<uint8_t> (DhcpOption::DhcpMessageType);
832 if (type == nullptr)
833 {
834 return;
835 }
836
837 switch (*type)
838 {
840 onDiscover (*packet);
841 break;
842
844 onRequest (*packet);
845 break;
846
848 onRelease (*packet);
849 break;
850
852 onDecline (*packet);
853 break;
854
856 onInform (*packet);
857 break;
858
859 default:
860 break;
861 }
862 }
863
872 int reply (const DhcpPacket& request, uint8_t type, const IpAddress& address, const DhcpOption& options)
873 {
874 const IpAddress server = IpAddress::ipv4Address (interface ());
875 if (server.isWildcard ())
876 {
877 lastError = std::make_error_code (std::errc::address_not_available);
878 return -1;
879 }
880
881 DhcpPacket out;
883 out.id = request.id;
884 out.flags = request.flags;
885 out.hardware = request.hardware;
886
887 if (type == DhcpMessage::Ack)
888 {
889 out.client = request.client;
890 }
891 out.your = address;
892 out.server = server;
893 out.gateway = request.gateway;
894 out.src = hardware ();
895
898 out.options.insert (options.begin (), options.end ());
899
900 const bool broadcast =
901 (type == DhcpMessage::Nak) || (request.client.isWildcard () &&
902 ((request.flags & DhcpMessage::BroadcastFlag) || address.isWildcard ()));
903
904 out.dest = broadcast ? MacAddress::broadcast : request.hardware;
905
906 const IpAddress& unicast = request.client.isWildcard () ? address : request.client;
907
908 return transmit (out, server, broadcast ? IpAddress::ipv4Broadcast : unicast);
909 }
910 };
911}
912
913#endif
MacAddress get(const IpAddress &ip, std::chrono::duration< Rep, Period > timeout)
get the MAC address for the given IP address using netlink neighbor cache or ARP request.
Definition arp.hpp:102
DHCP client.
Definition dhcp_protocol.hpp:37
int decline(const IpAddress &address, const IpAddress &server, const std::string &message={})
tell the server that the address it offered is already in use.
Definition dhcp.hpp:642
std::string _reason
reason the server gave for the last refusal.
Definition dhcp.hpp:701
DhcpPacket::Ptr renew(const IpAddress &client, const IpAddress &server, std::chrono::milliseconds timeout=std::chrono::seconds(1))
send a REQUEST message to the server holding the lease and wait for an ACK.
Definition dhcp.hpp:576
std::unordered_map< uint32_t, std::unique_ptr< PendingRequest > > _pending
messages waiting for their answer, indexed by transaction identifier.
Definition dhcp.hpp:695
int release(const IpAddress &client, const IpAddress &server, std::chrono::milliseconds timeout=std::chrono::seconds(1))
give a lease back to the server holding it.
Definition dhcp.hpp:617
DhcpPacket::Ptr discover(const IpAddress &wants=IpAddress::ipv4Wildcard, std::chrono::milliseconds timeout=std::chrono::seconds(1))
broadcast a DISCOVER message and wait for an OFFER.
Definition dhcp.hpp:535
const std::string _hostname
host name to advertise.
Definition dhcp.hpp:704
static const ByteList _defaultParams
options a client asks for by default.
Definition dhcp.hpp:692
BasicDhcpClient()=delete
create the BasicDhcpClient instance.
Mutex _syncMutex
mutex for synchronous operations.
Definition dhcp.hpp:698
DhcpPacket::Ptr request(const IpAddress &wants, const IpAddress &server, std::chrono::milliseconds timeout=std::chrono::seconds(1))
broadcast a REQUEST message and wait for an ACK.
Definition dhcp.hpp:557
DhcpPacket::Ptr inform(const IpAddress &client, std::chrono::milliseconds timeout=std::chrono::seconds(1))
ask a server for the parameters of an externally configured address.
Definition dhcp.hpp:600
void onMessage(DhcpPacket::Ptr packet) override final
hand a received message to the request waiting for it.
Definition dhcp.hpp:662
DhcpPacket::Ptr exchange(DhcpPacket &request, const IpAddress &destination, uint8_t expected, std::chrono::milliseconds timeout=std::chrono::seconds(1))
send a message and wait for its answer.
Definition dhcp.hpp:452
DhcpPacket compose(uint8_t type) const
build a message carrying what every message a client sends has in common.
Definition dhcp.hpp:418
std::string reason() const
get the reason the server gave for the last refusal.
Definition dhcp.hpp:522
BasicDhcpClient(const std::string &interface, uint16_t maxSize=0, const std::string &hostname={}, Reactor &reactor=ReactorThread::reactor())
create the instance bound to the given interface.
Definition dhcp.hpp:395
const uint16_t _maxSize
biggest message the server may send back.
Definition dhcp.hpp:707
virtual ~BasicDhcpClient()=default
destroy the instance.
BasicDhcpServer()=delete
create the BasicDhcpServer instance.
virtual void onRelease(const DhcpPacket &request)=0
method called when a RELEASE message is received.
int ack(const DhcpPacket &request, const IpAddress &address, const DhcpOption &options={})
answer a REQUEST message with an ACK.
Definition dhcp.hpp:766
int nak(const DhcpPacket &request, const std::string &message={})
refuse a REQUEST message with a NAK.
Definition dhcp.hpp:777
virtual void onDiscover(const DhcpPacket &request)=0
method called when a DISCOVER message is received.
virtual void onDecline(const DhcpPacket &request)=0
method called when a DECLINE message is received.
virtual ~BasicDhcpServer()=default
destroy the instance.
void onMessage(DhcpPacket::Ptr packet) override final
dispatch a received message to the handler for its type.
Definition dhcp.hpp:824
int offer(const DhcpPacket &request, const IpAddress &address, const DhcpOption &options={})
answer a DISCOVER message with an OFFER.
Definition dhcp.hpp:754
virtual void onInform(const DhcpPacket &request)=0
method called when an INFORM message is received.
virtual void onRequest(const DhcpPacket &request)=0
method called when a REQUEST message is received.
BasicDhcpServer(const std::string &interface, Reactor &reactor=ReactorThread::reactor())
create the instance bound to the given interface.
Definition dhcp.hpp:737
int reply(const DhcpPacket &request, uint8_t type, const IpAddress &address, const DhcpOption &options)
answer a message received from a client.
Definition dhcp.hpp:872
carries DHCP messages over a packet socket.
Definition dhcp_protocol.hpp:34
Reactor & _reactor
event loop reactor.
Definition dhcp.hpp:367
const std::string & interface() const noexcept
get the name of the interface the instance is bound to.
Definition dhcp.hpp:128
virtual ~BasicDhcp()
destroy the instance.
Definition dhcp.hpp:119
BasicDhcp & operator=(const BasicDhcp &other)=delete
assign instance by copy.
static uint16_t udpChecksum(const Frame &frame, const char *payload, size_t size)
compute the checksum of a UDP datagram, RFC 768.
Definition dhcp.hpp:197
int transmit(const DhcpPacket &packet, const IpAddress &source, const IpAddress &destination)
frame a message and write it on the wire.
Definition dhcp.hpp:222
struct __attribute__((packed)) Frame
link, internet and transport headers a DHCP message is framed with.
Definition dhcp.hpp:146
std::unique_ptr< char[]> _buffer
receive buffer.
Definition dhcp.hpp:358
BasicDhcp(BasicDhcp &&other)=delete
create instance by move.
DhcpPacket::Ptr receive(const char *data, size_t size) const
decode a frame received on the wire.
Definition dhcp.hpp:281
virtual void onMessage(DhcpPacket::Ptr packet)=0
method called when a DHCP message is received.
BasicDhcp(const std::string &interface, Reactor &reactor=ReactorThread::reactor())
create the instance bound to the given interface.
Definition dhcp.hpp:71
typename Protocol::Socket Socket
Definition dhcp.hpp:58
const std::string _interface
interface name.
Definition dhcp.hpp:361
BasicDhcp(const BasicDhcp &other)=delete
create instance by copy.
BasicDhcp()=delete
create the BasicDhcp instance.
const MacAddress _hardware
hardware address of the interface.
Definition dhcp.hpp:364
DhcpMessage _message
DHCP message codec.
Definition dhcp.hpp:355
void onReadable(int fd) override final
method called when data are ready to be read.
Definition dhcp.hpp:175
const MacAddress & hardware() const noexcept
get the hardware address of the interface the instance is bound to.
Definition dhcp.hpp:137
Socket _socket
underlying socket.
Definition dhcp.hpp:352
condition variable class.
Definition condition.hpp:42
bool timedWait(Lock &lock, std::chrono::duration< Rep, Period > timeout)
wait on a condition until timeout expire.
Definition condition.hpp:121
DHCP message codec.
Definition dhcp_message.hpp:92
@ BootReply
Definition dhcp_message.hpp:115
@ BootRequest
Definition dhcp_message.hpp:114
@ Request
Definition dhcp_message.hpp:101
@ Nak
Definition dhcp_message.hpp:104
@ Discover
Definition dhcp_message.hpp:99
@ Ack
Definition dhcp_message.hpp:103
@ Decline
Definition dhcp_message.hpp:102
@ Offer
Definition dhcp_message.hpp:100
@ Inform
Definition dhcp_message.hpp:106
@ Release
Definition dhcp_message.hpp:105
int deserialize(DhcpPacket &packet, std::stringstream &data) const
deserialize a DHCP message from a byte stream.
Definition dhcp_message.hpp:199
@ BroadcastFlag
Definition dhcp_message.hpp:123
static constexpr size_t headerSize
size of the fixed part of a DHCP message, magic cookie included.
Definition dhcp_message.hpp:285
int serialize(const DhcpPacket &packet, std::stringstream &data) const
serialize a DHCP message into a byte stream.
Definition dhcp_message.hpp:141
DHCP option list.
Definition dhcp_option.hpp:61
static bool isValid(uint8_t code, T &&value)
check that a value can be carried by the given option.
Definition dhcp_option.hpp:410
@ Router
Definition dhcp_option.hpp:71
@ Message
Definition dhcp_option.hpp:124
@ ServerIdentifier
Definition dhcp_option.hpp:122
@ BroadcastAddress
Definition dhcp_option.hpp:96
@ DomainNameServer
Definition dhcp_option.hpp:74
@ ParameterRequestList
Definition dhcp_option.hpp:123
@ DomainName
Definition dhcp_option.hpp:83
@ SubnetMask
Definition dhcp_option.hpp:69
@ ClientIdentifier
Definition dhcp_option.hpp:129
@ MaximumDhcpMessageSize
Definition dhcp_option.hpp:125
@ RequestedIpAddress
Definition dhcp_option.hpp:118
@ DhcpMessageType
Definition dhcp_option.hpp:121
@ HostName
Definition dhcp_option.hpp:80
@ InterfaceMtu
Definition dhcp_option.hpp:94
const_iterator end() const
get an iterator to the element following the last element of the list.
Definition dhcp_option.hpp:291
bool insert(uint8_t code, T &&value)
add an option to the list, converting the value to the type the option carries.
Definition dhcp_option.hpp:348
const_iterator begin() const
get an iterator to the first element of the list.
Definition dhcp_option.hpp:273
IPv6, IPv4 address class.
Definition ip_address.hpp:51
static const IpAddress ipv4Wildcard
wildcard IPv4 address.
Definition ip_address.hpp:369
static const IpAddress ipv4Broadcast
broadcast IPv4 address.
Definition ip_address.hpp:372
static IpAddress ipv4Address(const std::string &interface)
get the specified interface IPv4 address.
Definition ip_address.cpp:1526
bool isWildcard() const
check if IP address is a wildcard address.
Definition ip_address.cpp:1295
const void * addr() const
get the internal address structure.
Definition ip_address.cpp:1259
MAC address class.
Definition mac_address.hpp:46
static const MacAddress broadcast
broadcast MAC address.
Definition mac_address.hpp:309
bool isWildcard() const
check if MAC address is a wildcard address.
Definition mac_address.cpp:182
const uint8_t * addr() const
get the internal MAC address array address.
Definition mac_address.cpp:164
class used to protect shared data from being simultaneously accessed by multiple threads.
Definition mutex.hpp:37
static Reactor & reactor()
get the global Reactor instance.
Definition reactor.cpp:584
Reactor class.
Definition reactor.hpp:156
int delHandler(int fd, bool sync=true) noexcept
delete handler from reactor.
Definition reactor.cpp:155
int addHandler(int fd, EventHandler *handler, bool wantRead=true, bool wantWrite=false, bool sync=true) noexcept
add handler to reactor.
Definition reactor.cpp:100
class owning a mutex for the duration of a scoped block.
Definition mutex.hpp:246
Definition acceptor.hpp:32
std::enable_if_t< std::numeric_limits< Type >::is_integer, Type > randomize()
create a random number.
Definition utils.hpp:434
uint16_t checksum(const uint16_t *data, size_t len, uint16_t current=0) noexcept
get standard 1s complement checksum.
Definition utils.hpp:357
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195
std::vector< uint8_t > ByteList
list of bytes.
Definition dhcp_option.hpp:45
Definition error.hpp:144
message waiting for its answer.
Definition dhcp.hpp:683
Condition cond
answer notification.
Definition dhcp.hpp:685
DhcpPacket::Ptr answer
answer received.
Definition dhcp.hpp:688
DHCP message.
Definition dhcp_message.hpp:47
uint16_t flags
message flags.
Definition dhcp_message.hpp:79
MacAddress hardware
client hardware address, carried by the message itself.
Definition dhcp_message.hpp:58
IpAddress client
client IP address, set when the client already owns a lease.
Definition dhcp_message.hpp:61
uint8_t op
operation code.
Definition dhcp_message.hpp:82
MacAddress src
link layer source address, set by the transport.
Definition dhcp_message.hpp:52
std::unique_ptr< DhcpPacket > Ptr
pointer to a DHCP message.
Definition dhcp_message.hpp:49
IpAddress your
IP address the server assigns to the client.
Definition dhcp_message.hpp:64
DhcpOption options
message options.
Definition dhcp_message.hpp:85
MacAddress dest
link layer destination address, set by the transport.
Definition dhcp_message.hpp:55
IpAddress gateway
IP address of the relay agent the message went through.
Definition dhcp_message.hpp:70
IpAddress server
IP address of the next server to use at boot time.
Definition dhcp_message.hpp:67
uint32_t id
transaction identifier.
Definition dhcp_message.hpp:73
IpAddress address
Definition tcp_acceptor_test.cpp:35