join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
dhcp_message.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_FABRIC_DHCP_MESSAGE_HPP
26#define JOIN_FABRIC_DHCP_MESSAGE_HPP
27
28// libjoin.
29#include <join/dhcp_option.hpp>
30#include <join/utils.hpp>
31
32// C++.
33#include <vector>
34
35// C.
36#include <net/ethernet.h>
37#include <netinet/in.h>
38#include <cstring>
39
40namespace join
41{
46 {
49
52
55
57 IpAddress client{AF_INET};
58
60 IpAddress your{AF_INET};
61
63 IpAddress server{AF_INET};
64
67
69 uint32_t id = 0;
70
72 uint16_t secs = 0;
73
75 uint16_t flags = 0;
76
78 uint8_t op = 0;
79
82 };
83
88 {
89 public:
93 enum MessageType : uint8_t
94 {
96 Offer = 2,
97 Request = 3,
98 Decline = 4,
99 Ack = 5,
100 Nak = 6,
102 Inform = 8,
103 };
104
108 enum Operation : uint8_t
109 {
112 };
113
117 enum Flag : uint16_t
118 {
119 BroadcastFlag = 0x8000,
120 };
121
125 enum Overload : uint8_t
126 {
129 };
130
138 ssize_t serialize (const DhcpPacket& packet, char* data, size_t maxSize) const
139 {
140 if ((packet.op != BootRequest) && (packet.op != BootReply))
141 {
143 return -1;
144 }
145
146 char* cur = data;
147 const char* end = data + maxSize;
148 bool ok = true;
149
150 uint8_t head[4] = {packet.op, _ethernet, ETH_ALEN, 0};
151 ok &= writeBytes (cur, end, head, sizeof (head));
152
153 uint32_t id = htonl (packet.id);
154 ok &= writeBytes (cur, end, &id, sizeof (id));
155
156 uint16_t secs = htons (packet.secs);
157 ok &= writeBytes (cur, end, &secs, sizeof (secs));
158
159 uint16_t flags = htons (packet.flags);
160 ok &= writeBytes (cur, end, &flags, sizeof (flags));
161
162 ok &= writeAddress (cur, end, packet.client);
163 ok &= writeAddress (cur, end, packet.your);
164 ok &= writeAddress (cur, end, packet.server);
165 ok &= writeAddress (cur, end, packet.gateway);
166
167 char chaddr[_chaddrSize] = {};
168 ::memcpy (chaddr, packet.hardware.addr (), ETH_ALEN);
169 ok &= writeBytes (cur, end, chaddr, sizeof (chaddr));
170
171 char padding[_snameSize + _fileSize] = {};
172 ok &= writeBytes (cur, end, padding, sizeof (padding));
173
174 uint32_t cookie = htonl (magicCookie);
175 ok &= writeBytes (cur, end, &cookie, sizeof (cookie));
176
177 if (!ok || (serialize (packet.options, cur, end) == -1))
178 {
179 return -1;
180 }
181
182 const size_t written = static_cast<size_t> (cur - data);
183 if (written < minMsgSize)
184 {
185 const char pad[minMsgSize] = {};
186 if (!writeBytes (cur, end, pad, minMsgSize - written))
187 {
188 return -1;
189 }
190 }
191
192 return cur - data;
193 }
194
202 int deserialize (DhcpPacket& packet, const char* data, size_t size) const
203 {
204 packet.options.clear ();
205
206 const char* cur = data;
207 const char* end = data + size;
208
209 uint8_t head[4] = {};
210 if (!readBytes (cur, end, head, sizeof (head)))
211 {
212 return -1;
213 }
214
215 packet.op = head[0];
216 if (((packet.op != BootRequest) && (packet.op != BootReply)) || (head[1] != _ethernet) ||
217 (head[2] != ETH_ALEN))
218 {
220 return -1;
221 }
222
223 uint32_t id = 0;
224 uint16_t secs = 0, flags = 0;
225
226 if (!readBytes (cur, end, &id, sizeof (id)) || !readBytes (cur, end, &secs, sizeof (secs)) ||
227 !readBytes (cur, end, &flags, sizeof (flags)))
228 {
229 return -1;
230 }
231
232 packet.id = ntohl (id);
233 packet.secs = ntohs (secs);
234 packet.flags = ntohs (flags);
235
236 if (!readAddress (cur, end, packet.client) || !readAddress (cur, end, packet.your) ||
237 !readAddress (cur, end, packet.server) || !readAddress (cur, end, packet.gateway))
238 {
239 return -1;
240 }
241
242 uint8_t chaddr[_chaddrSize] = {};
243 if (!readBytes (cur, end, chaddr, sizeof (chaddr)))
244 {
245 return -1;
246 }
247
248 packet.hardware = MacAddress (chaddr, ETH_ALEN);
249
250 char sname[_snameSize] = {}, file[_fileSize] = {};
251 uint32_t cookie = 0;
252
253 if (!readBytes (cur, end, sname, sizeof (sname)) || !readBytes (cur, end, file, sizeof (file)) ||
254 !readBytes (cur, end, &cookie, sizeof (cookie)))
255 {
256 return -1;
257 }
258
259 if (ntohl (cookie) != magicCookie)
260 {
262 return -1;
263 }
264
265 if (deserialize (packet.options, cur, end) == -1)
266 {
267 return -1;
268 }
269
270 const uint8_t* overload = packet.options.getIf<uint8_t> (DhcpOption::OptionOverload);
271 if (overload != nullptr)
272 {
273 if ((*overload & FileOverload) && (deserialize (packet.options, file, file + sizeof (file)) == -1))
274 {
275 return -1;
276 }
277
278 if ((*overload & SnameOverload) && (deserialize (packet.options, sname, sname + sizeof (sname)) == -1))
279 {
280 return -1;
281 }
282 }
283
284 return 0;
285 }
286
288 static constexpr uint32_t magicCookie = 0x63825363;
289
291 static constexpr size_t headerSize = 240;
292
294 static constexpr size_t minMsgSize = 300;
295
297 static constexpr size_t maxOptionSize = 255;
298
299 protected:
307 int serialize (const DhcpOption& options, char*& cur, const char* end) const;
308
316 int deserialize (DhcpOption& options, const char* cur, const char* end) const;
317
326 static bool writeHead (char*& cur, const char* end, uint8_t code, size_t size);
327
335 static bool writeAddress (char*& cur, const char* end, const IpAddress& address)
336 {
337 struct in_addr addr = {};
338
339 if (address.family () == AF_INET)
340 {
341 ::memcpy (&addr, address.addr (), sizeof (addr));
342 }
343
344 return writeBytes (cur, end, &addr, sizeof (addr));
345 }
346
354 static bool readAddress (const char*& cur, const char* end, IpAddress& address)
355 {
356 struct in_addr addr = {};
357
358 if (!readBytes (cur, end, &addr, sizeof (addr)))
359 {
360 return false;
361 }
362
363 address = IpAddress (&addr, sizeof (addr));
364
365 return true;
366 }
367
369 static constexpr uint8_t _ethernet = 1;
370
372 static constexpr size_t _chaddrSize = 16;
373
375 static constexpr size_t _snameSize = 64;
376
378 static constexpr size_t _fileSize = 128;
379 };
380}
381
382#endif
DHCP message codec.
Definition dhcp_message.hpp:88
Operation
DHCP operation codes.
Definition dhcp_message.hpp:109
@ BootReply
Definition dhcp_message.hpp:111
@ BootRequest
Definition dhcp_message.hpp:110
static constexpr uint32_t magicCookie
magic cookie introducing the option field.
Definition dhcp_message.hpp:288
Overload
option overload values.
Definition dhcp_message.hpp:126
@ SnameOverload
Definition dhcp_message.hpp:128
@ FileOverload
Definition dhcp_message.hpp:127
ssize_t serialize(const DhcpPacket &packet, char *data, size_t maxSize) const
serialize a DHCP message into a buffer.
Definition dhcp_message.hpp:138
MessageType
DHCP message types, RFC 2132 section 9.6.
Definition dhcp_message.hpp:94
@ Request
Definition dhcp_message.hpp:97
@ Nak
Definition dhcp_message.hpp:100
@ Discover
Definition dhcp_message.hpp:95
@ Ack
Definition dhcp_message.hpp:99
@ Decline
Definition dhcp_message.hpp:98
@ Offer
Definition dhcp_message.hpp:96
@ Inform
Definition dhcp_message.hpp:102
@ Release
Definition dhcp_message.hpp:101
static constexpr size_t _fileSize
size of the boot file name field.
Definition dhcp_message.hpp:378
static bool writeHead(char *&cur, const char *end, uint8_t code, size_t size)
write an option header into a buffer.
Definition dhcp_message.cpp:40
Flag
message flags.
Definition dhcp_message.hpp:118
@ BroadcastFlag
Definition dhcp_message.hpp:119
static constexpr size_t _snameSize
size of the server name field.
Definition dhcp_message.hpp:375
static constexpr size_t _chaddrSize
size of the client hardware address field.
Definition dhcp_message.hpp:372
int deserialize(DhcpPacket &packet, const char *data, size_t size) const
deserialize a DHCP message from a buffer.
Definition dhcp_message.hpp:202
static constexpr size_t minMsgSize
smallest message a BOOTP implementation accepts, RFC 951 and RFC 1542 section 2.1.
Definition dhcp_message.hpp:294
static constexpr size_t maxOptionSize
biggest payload a single option can carry, its length field is one octet.
Definition dhcp_message.hpp:297
static constexpr size_t headerSize
size of the fixed part of a DHCP message, magic cookie included.
Definition dhcp_message.hpp:291
static constexpr uint8_t _ethernet
hardware address type of an Ethernet link.
Definition dhcp_message.hpp:369
static bool writeAddress(char *&cur, const char *end, const IpAddress &address)
write an IPv4 address into a buffer.
Definition dhcp_message.hpp:335
static bool readAddress(const char *&cur, const char *end, IpAddress &address)
read an IPv4 address from a buffer.
Definition dhcp_message.hpp:354
DHCP option list.
Definition dhcp_option.hpp:64
@ OptionOverload
Definition dhcp_option.hpp:123
const T * getIf(uint8_t code) const
get the value identified by code if it is present and holds the requested type.
Definition dhcp_option.hpp:246
void clear()
remove all elements from the list.
Definition dhcp_option.hpp:339
IPv6, IPv4 address class.
Definition ip_address.hpp:52
MAC address class.
Definition mac_address.hpp:47
const uint8_t * addr() const
get the internal MAC address array address.
Definition mac_address.cpp:164
Definition acceptor.hpp:32
bool readBytes(const char *&cur, const char *end, void *out, size_t size) noexcept
read bytes from a buffer.
Definition utils.hpp:276
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195
bool writeBytes(char *&cur, const char *end, const void *in, size_t size) noexcept
write bytes to a buffer.
Definition utils.hpp:298
DHCP message.
Definition dhcp_message.hpp:46
uint16_t flags
message flags.
Definition dhcp_message.hpp:75
MacAddress hardware
client hardware address, carried by the message itself.
Definition dhcp_message.hpp:54
IpAddress client
client IP address, set when the client already owns a lease.
Definition dhcp_message.hpp:57
uint8_t op
operation code.
Definition dhcp_message.hpp:78
MacAddress src
link layer source address, set by the transport.
Definition dhcp_message.hpp:48
IpAddress your
IP address the server assigns to the client.
Definition dhcp_message.hpp:60
DhcpOption options
message options.
Definition dhcp_message.hpp:81
uint16_t secs
seconds elapsed since the client started the acquisition.
Definition dhcp_message.hpp:72
MacAddress dest
link layer destination address, set by the transport.
Definition dhcp_message.hpp:51
IpAddress gateway
IP address of the relay agent the message went through.
Definition dhcp_message.hpp:66
IpAddress server
IP address of the next server to use at boot time.
Definition dhcp_message.hpp:63
uint32_t id
transaction identifier.
Definition dhcp_message.hpp:69
overload resolution.
Definition traits.hpp:38
IpAddress address
Definition tcp_acceptor_test.cpp:35