Kea 3.1.1
pkt4.cc
Go to the documentation of this file.
1// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
9#include <dhcp/dhcp4.h>
10#include <dhcp/libdhcp++.h>
11#include <dhcp/option_int.h>
12#include <dhcp/pkt4.h>
13#include <util/str.h>
15
16#include <algorithm>
17#include <iostream>
18#include <sstream>
19
20using namespace std;
21using namespace isc::dhcp;
22using namespace isc::asiolink;
23using namespace isc::util::str;
24
25namespace {
26
28const IOAddress DEFAULT_ADDRESS("0.0.0.0");
29}
30
31namespace isc {
32namespace dhcp {
33
34Pkt4::Pkt4(uint8_t msg_type, uint32_t transid)
35 : Pkt(transid, DEFAULT_ADDRESS, DEFAULT_ADDRESS, DHCP4_SERVER_PORT, DHCP4_CLIENT_PORT),
36 op_(DHCPTypeToBootpType(msg_type)), hwaddr_(new HWAddr()), hops_(0), secs_(0), flags_(0),
37 ciaddr_(DEFAULT_ADDRESS), yiaddr_(DEFAULT_ADDRESS), siaddr_(DEFAULT_ADDRESS),
38 giaddr_(DEFAULT_ADDRESS) {
39 memset(sname_, 0, MAX_SNAME_LEN);
40 memset(file_, 0, MAX_FILE_LEN);
41
42 setType(msg_type);
43}
44
45Pkt4::Pkt4(const uint8_t* data, size_t len)
46 : Pkt(data, len, DEFAULT_ADDRESS, DEFAULT_ADDRESS, DHCP4_SERVER_PORT, DHCP4_CLIENT_PORT),
47 op_(BOOTREQUEST), hwaddr_(new HWAddr()), hops_(0), secs_(0), flags_(0),
48 ciaddr_(DEFAULT_ADDRESS), yiaddr_(DEFAULT_ADDRESS), siaddr_(DEFAULT_ADDRESS),
49 giaddr_(DEFAULT_ADDRESS) {
50
51 if (len < DHCPV4_PKT_HDR_LEN) {
52 isc_throw(OutOfRange, "Truncated DHCPv4 packet (len=" << len
53 << ") received, at least " << DHCPV4_PKT_HDR_LEN
54 << " is expected.");
55 }
56 memset(sname_, 0, MAX_SNAME_LEN);
57 memset(file_, 0, MAX_FILE_LEN);
58}
59
60size_t
62 size_t length = DHCPV4_PKT_HDR_LEN; // DHCPv4 header
63
64 // ... and sum of lengths of all options
65 for (auto const& it : options_) {
66 length += it.second->len();
67 }
68
69 return (length);
70}
71
72void
74 if (!hwaddr_) {
75 isc_throw(InvalidOperation, "Can't build Pkt4 packet. HWAddr not set.");
76 }
77
78 // This object is necessary to restore the packet options after performing
79 // splitOptions4 when function scope ends. It creates a container of option
80 // clones which are split and packed.
81 ScopedPkt4OptionsCopy scoped_options(*this);
82
83 // Clear the output buffer to make sure that consecutive calls to pack()
84 // will not result in concatenation of multiple packet copies.
85 buffer_out_.clear();
86
87 try {
88 size_t hw_len = hwaddr_->hwaddr_.size();
89
90 buffer_out_.writeUint8(op_);
91 buffer_out_.writeUint8(hwaddr_->htype_);
92 buffer_out_.writeUint8(hw_len < MAX_CHADDR_LEN ?
93 hw_len : MAX_CHADDR_LEN);
94 buffer_out_.writeUint8(hops_);
95 buffer_out_.writeUint32(transid_);
96 buffer_out_.writeUint16(secs_);
97 buffer_out_.writeUint16(flags_);
98 buffer_out_.writeUint32(ciaddr_.toUint32());
99 buffer_out_.writeUint32(yiaddr_.toUint32());
100 buffer_out_.writeUint32(siaddr_.toUint32());
101 buffer_out_.writeUint32(giaddr_.toUint32());
102
103 if ((hw_len > 0) && (hw_len <= MAX_CHADDR_LEN)) {
104 // write up to 16 bytes of the hardware address (CHADDR field is 16
105 // bytes long in DHCPv4 message).
106 buffer_out_.writeData(&hwaddr_->hwaddr_[0],
107 (hw_len < MAX_CHADDR_LEN ?
108 hw_len : MAX_CHADDR_LEN) );
109 hw_len = MAX_CHADDR_LEN - hw_len;
110 } else {
111 hw_len = MAX_CHADDR_LEN;
112 }
113
114 // write (len) bytes of padding
115 if (hw_len > 0) {
116 vector<uint8_t> zeros(hw_len, 0);
117 buffer_out_.writeData(&zeros[0], hw_len);
118 }
119
120 buffer_out_.writeData(sname_, MAX_SNAME_LEN);
121 buffer_out_.writeData(file_, MAX_FILE_LEN);
122
123 // write DHCP magic cookie
124 buffer_out_.writeUint32(DHCP_OPTIONS_COOKIE);
125
128 ManagedScopedOptionsCopyContainer m_scoped_options;
129
130 // The RFC3396 adds support for long options split over multiple options
131 // using the same code.
132 // The long options are split in multiple CustomOption instances which
133 // hold the data. As a result, the option type of the newly created
134 // options will differ from the ones instantiated by the
135 // @ref OptionDefinition::optionFactory. At this stage the server should
136 // not do anything useful with the options beside packing.
138
139 // Call packOptions4() with parameter,"top", true. This invokes
140 // logic to emit the message type option first.
142
143 // add END option that indicates end of options
144 // (End option is very simple, just a 255 octet)
145 buffer_out_.writeUint8(DHO_END);
146 } catch(const Exception& e) {
147 // An exception is thrown and message will be written to Logger
149 }
150}
151
152void
154 // input buffer (used during message reception)
155 isc::util::InputBuffer buffer_in(&data_[0], data_.size());
156
157 if (buffer_in.getLength() < DHCPV4_PKT_HDR_LEN) {
158 isc_throw(OutOfRange, "Received truncated DHCPv4 packet (len="
159 << buffer_in.getLength() << " received, at least "
160 << DHCPV4_PKT_HDR_LEN << "is expected");
161 }
162
163 op_ = buffer_in.readUint8();
164 uint8_t htype = buffer_in.readUint8();
165 uint8_t hlen = buffer_in.readUint8();
166 hops_ = buffer_in.readUint8();
167 transid_ = buffer_in.readUint32();
168 secs_ = buffer_in.readUint16();
169 flags_ = buffer_in.readUint16();
170 ciaddr_ = IOAddress(buffer_in.readUint32());
171 yiaddr_ = IOAddress(buffer_in.readUint32());
172 siaddr_ = IOAddress(buffer_in.readUint32());
173 giaddr_ = IOAddress(buffer_in.readUint32());
174
175 vector<uint8_t> hw_addr(MAX_CHADDR_LEN, 0);
176 buffer_in.readVector(hw_addr, MAX_CHADDR_LEN);
177 buffer_in.readData(sname_, MAX_SNAME_LEN);
178 buffer_in.readData(file_, MAX_FILE_LEN);
179
180 hw_addr.resize(hlen);
181
182 hwaddr_ = HWAddrPtr(new HWAddr(hw_addr, htype));
183
184 if (buffer_in.getLength() == buffer_in.getPosition()) {
185 // this is *NOT* DHCP packet. It does not have any DHCPv4 options. In
186 // particular, it does not have magic cookie, a 4 byte sequence that
187 // differentiates between DHCP and RFC 951 BOOTP packets.
188 isc_throw(InvalidOperation, "Received BOOTP packet without vendor information extensions.");
189 }
190
191 if (buffer_in.getLength() - buffer_in.getPosition() < 4) {
192 // there is not enough data to hold magic DHCP cookie
193 isc_throw(Unexpected, "Truncated or no DHCP packet.");
194 }
195
196 uint32_t magic = buffer_in.readUint32();
197 if (magic != DHCP_OPTIONS_COOKIE) {
198 isc_throw(Unexpected, "Invalid or missing DHCP magic cookie");
199 }
200
201 size_t opts_len = buffer_in.getLength() - buffer_in.getPosition();
202 vector<uint8_t> opts_buffer;
203
204 // Use readVector because a function which parses option requires
205 // a vector as an input.
206 buffer_in.readVector(opts_buffer, opts_len);
207
208 size_t offset = LibDHCP::unpackOptions4(opts_buffer, DHCP4_OPTION_SPACE, options_, deferred_options_, false);
209
210 // If offset is not equal to the size and there is no DHO_END,
211 // then something is wrong here. We either parsed past input
212 // buffer (bug in our code) or we haven't parsed everything
213 // (received trailing garbage or truncated option).
214 //
215 // Invoking Jon Postel's law here: be conservative in what you send, and be
216 // liberal in what you accept. There's no easy way to log something from
217 // libdhcp++ library, so we just choose to be silent about remaining
218 // bytes. We also need to quell compiler warning about unused offset
219 // variable.
220 //
221 // if ((offset != size) && (opts_buffer[offset] != DHO_END)) {
222 // isc_throw(BadValue, "Received DHCPv6 buffer of size " << size
223 // << ", were able to parse " << offset << " bytes.");
224 // }
225 (void)offset;
226
227 // Kea supports multiple vendor options so it needs to split received and
228 // fused options in multiple OptionVendor instances.
230
231 // No need to call check() here. There are thorough tests for this
232 // later (see Dhcp4Srv::accept()). We want to drop the packet later,
233 // so we'll be able to log more detailed drop reason.
234}
235
236uint8_t Pkt4::getType() const {
238 if (!generic) {
239 return (DHCP_NOTYPE);
240 }
241
242 // Check if Message Type is specified as OptionInt<uint8_t>
243 boost::shared_ptr<OptionInt<uint8_t> > type_opt =
244 boost::dynamic_pointer_cast<OptionInt<uint8_t> >(generic);
245 if (type_opt) {
246 return (type_opt->getValue());
247 }
248
249 // Try to use it as generic option
250 return (generic->getUint8());
251}
252
253void Pkt4::setType(uint8_t dhcp_type) {
255 if (opt) {
256
257 // There is message type option already, update it. It seems that
258 // we do have two types of objects representing message-type option.
259 // It would be more preferable to use only one type, but there's no
260 // easy way to enforce it.
261 //
262 // One is an instance of the Option class. It stores type in
263 // Option::data_, so Option::setUint8() and Option::getUint8() can be
264 // used. The other one is an instance of OptionInt<uint8_t> and
265 // it stores message type as integer, hence
266 // OptionInt<uint8_t>::getValue() and OptionInt<uint8_t>::setValue()
267 // should be used.
268 boost::shared_ptr<OptionInt<uint8_t> > type_opt =
269 boost::dynamic_pointer_cast<OptionInt<uint8_t> >(opt);
270 if (type_opt) {
271 type_opt->setValue(dhcp_type);
272 } else {
273 opt->setUint8(dhcp_type);
274 }
275 } else {
276 // There is no message type option yet, add it
278 dhcp_type));
279 addOption(opt);
280 }
281}
282
283const char*
284Pkt4::getName(const uint8_t type) {
285 static const char* DHCPDISCOVER_NAME = "DHCPDISCOVER";
286 static const char* DHCPOFFER_NAME = "DHCPOFFER";
287 static const char* DHCPREQUEST_NAME = "DHCPREQUEST";
288 static const char* DHCPDECLINE_NAME = "DHCPDECLINE";
289 static const char* DHCPACK_NAME = "DHCPACK";
290 static const char* DHCPNAK_NAME = "DHCPNAK";
291 static const char* DHCPRELEASE_NAME = "DHCPRELEASE";
292 static const char* DHCPINFORM_NAME = "DHCPINFORM";
293 static const char* DHCPLEASEQUERY_NAME = "DHCPLEASEQUERY";
294 static const char* DHCPLEASEUNASSIGNED_NAME = "DHCPLEASEUNASSIGNED";
295 static const char* DHCPLEASEUNKNOWN_NAME = "DHCPLEASEUNKNOWN";
296 static const char* DHCPLEASEACTIVE_NAME = "DHCPLEASEACTIVE";
297 static const char* DHCPBULKLEASEQUERY_NAME = "DHCPBULKLEASEQUERY";
298 static const char* DHCPLEASEQUERYDONE_NAME = "DHCPLEASEQUERYDONE";
299 static const char* DHCPLEASEQUERYSTATUS_NAME = "DHCPLEASEQUERYSTATUS";
300 static const char* DHCPTLS_NAME = "DHCPTLS";
301 static const char* UNKNOWN_NAME = "UNKNOWN";
302
303 switch (type) {
304 case DHCPDISCOVER:
305 return (DHCPDISCOVER_NAME);
306
307 case DHCPOFFER:
308 return (DHCPOFFER_NAME);
309
310 case DHCPREQUEST:
311 return (DHCPREQUEST_NAME);
312
313 case DHCPDECLINE:
314 return (DHCPDECLINE_NAME);
315
316 case DHCPACK:
317 return (DHCPACK_NAME);
318
319 case DHCPNAK:
320 return (DHCPNAK_NAME);
321
322 case DHCPRELEASE:
323 return (DHCPRELEASE_NAME);
324
325 case DHCPINFORM:
326 return (DHCPINFORM_NAME);
327
328 case DHCPLEASEQUERY:
329 return (DHCPLEASEQUERY_NAME);
330
332 return (DHCPLEASEUNASSIGNED_NAME);
333
334 case DHCPLEASEUNKNOWN:
335 return (DHCPLEASEUNKNOWN_NAME);
336
337 case DHCPLEASEACTIVE:
338 return (DHCPLEASEACTIVE_NAME);
339
341 return (DHCPBULKLEASEQUERY_NAME);
342
344 return (DHCPLEASEQUERYDONE_NAME);
345
347 return (DHCPLEASEQUERYSTATUS_NAME);
348
349 case DHCPTLS:
350 return (DHCPTLS_NAME);
351
352 default:
353 ;
354 }
355 return (UNKNOWN_NAME);
356}
357
358const char*
360 // getType() is now exception safe. Even if there's no option 53 (message
361 // type), it now returns 0 rather than throw. getName() is able to handle
362 // 0 and unknown message types.
363 return (Pkt4::getName(getType()));
364}
365
366std::string
368
371 std::string suffix;
372 ClientIdPtr client_id;
374 if (client_opt) {
375 try {
376 client_id = ClientIdPtr(new ClientId(client_opt->getData()));
377 } catch (...) {
378 // ClientId may throw if the client-id is too short.
379 suffix = " (malformed client-id)";
380 }
381 }
382
383 std::ostringstream label;
384 try {
385 label << makeLabel(hwaddr_, client_id, transid_);
386 } catch (...) {
387 // This should not happen with the current code, but we may add extra
388 // sanity checks in the future that would possibly throw if
389 // the hwaddr length is 0.
390 label << " (malformed hw address)";
391 }
392
393 label << suffix;
394
395 return (label.str());
396}
397
398std::string
399Pkt4::makeLabel(const HWAddrPtr& hwaddr, const ClientIdPtr& client_id,
400 const uint32_t transid) {
401 // Create label with HW address and client identifier.
402 stringstream label;
403 label << makeLabel(hwaddr, client_id);
404
405 // Append transaction id.
406 label << ", tid=0x" << hex << transid << dec;
407
408 return (label.str());
409}
410
411std::string
412Pkt4::makeLabel(const HWAddrPtr& hwaddr, const ClientIdPtr& client_id) {
413 stringstream label;
414 label << "[" << (hwaddr ? hwaddr->toText() : "no hwaddr info")
415 << "], cid=[" << (client_id ? client_id->toText() : "no info")
416 << "]";
417
418 return (label.str());
419}
420
421std::string
422Pkt4::toText(bool verbose /* = false */) const {
423 stringstream tmp;
424
425 // First print the basics
426 tmp << "local_address=" << local_addr_ << ":" << local_port_
427 << ", remote_address=" << remote_addr_ << ":" << remote_port_ << "," << endl;
428
429 tmp << "msg_type=";
430
431 // Try to obtain message type.
432 uint8_t msg_type = getType();
433 if (msg_type != DHCP_NOTYPE) {
434 tmp << getName(msg_type) << " (" << static_cast<int>(msg_type) << ")";
435 } else {
436 // Message Type option is missing.
437 tmp << "(missing)";
438 }
439
440 tmp << ", trans_id=0x" << hex << transid_ << dec;
441
442 if (verbose) {
443 tmp << ", secs=" << secs_;
444 tmp << ", flags=0x" << hex << flags_;
445 if (!ciaddr_.isV4Zero()) {
446 tmp << ", ciaddr=" << ciaddr_.toText();
447 }
448
449 if (!yiaddr_.isV4Zero()) {
450 tmp << ", yiaddr=" << yiaddr_.toText();
451 }
452
453 if (!siaddr_.isV4Zero()) {
454 tmp << ", siaddr=" << siaddr_.toText();
455 }
456
457 if (!giaddr_.isV4Zero()) {
458 tmp << ", giaddr=" << giaddr_.toText();
459 }
460
461 auto sname_dump = printOrDump(getSname(), 32);
462 if (!sname_dump.empty()) {
463 tmp << ", sname=[" << sname_dump << "]";
464 }
465
466 auto file_dump = printOrDump(getFile(), 32);
467 if (!file_dump.empty()) {
468 tmp << ", file=[" << file_dump << "]";
469 }
470 }
471
472 if (!options_.empty()) {
473 tmp << "," << endl << "options:";
474 for (auto const& opt : options_) {
475 try {
476 tmp << endl << opt.second->toText(2);
477 } catch (...) {
478 tmp << "(unknown)" << endl;
479 }
480 }
481
482 } else {
483 tmp << "," << endl << "message contains no options";
484 }
485
486 return (tmp.str());
487}
488
489void
490Pkt4::setHWAddr(uint8_t htype, uint8_t hlen,
491 const std::vector<uint8_t>& mac_addr) {
492 setHWAddrMember(htype, hlen, mac_addr, hwaddr_);
493}
494
495void
497 if (!addr) {
498 isc_throw(BadValue, "Setting DHCPv4 chaddr field to NULL"
499 << " is forbidden");
500 }
501 hwaddr_ = addr;
502}
503
504void
505Pkt4::setHWAddrMember(const uint8_t htype, const uint8_t hlen,
506 const std::vector<uint8_t>& mac_addr,
507 HWAddrPtr& hw_addr) {
510 if (hlen > MAX_CHADDR_LEN) {
511 isc_throw(OutOfRange, "Hardware address (len=" << static_cast<uint32_t>(hlen)
512 << ") too long. Max " << MAX_CHADDR_LEN << " supported.");
513
514 } else if (mac_addr.empty() && (hlen > 0) ) {
515 isc_throw(OutOfRange, "Invalid HW Address specified");
516 }
517
521 hw_addr.reset(new HWAddr(mac_addr, htype));
522}
523
524void
525Pkt4::setLocalHWAddr(const uint8_t htype, const uint8_t hlen,
526 const std::vector<uint8_t>& mac_addr) {
527 setHWAddrMember(htype, hlen, mac_addr, local_hwaddr_);
528}
529
530void
532 if (!addr) {
533 isc_throw(BadValue, "Setting local HW address to NULL is"
534 << " forbidden.");
535 }
536 local_hwaddr_ = addr;
537}
538
539void
540Pkt4::setSname(const uint8_t* sname, size_t snameLen /*= MAX_SNAME_LEN*/) {
541 if (snameLen > MAX_SNAME_LEN) {
542 isc_throw(OutOfRange, "sname field (len=" << snameLen
543 << ") too long, Max " << MAX_SNAME_LEN << " supported.");
544
545 } else if (sname == NULL) {
546 isc_throw(InvalidParameter, "Invalid sname specified");
547 }
548
549 std::copy(sname, (sname + snameLen), sname_);
550 if (snameLen < MAX_SNAME_LEN) {
551 std::fill((sname_ + snameLen), (sname_ + MAX_SNAME_LEN), 0);
552 }
553
554 // No need to store snameLen as any empty space is filled with 0s
555}
556
557void
558Pkt4::setFile(const uint8_t* file, size_t fileLen /*= MAX_FILE_LEN*/) {
559 if (fileLen > MAX_FILE_LEN) {
560 isc_throw(OutOfRange, "file field (len=" << fileLen
561 << ") too long, Max " << MAX_FILE_LEN << " supported.");
562
563 } else if (file == NULL) {
564 isc_throw(InvalidParameter, "Invalid file name specified");
565 }
566
567 std::copy(file, (file + fileLen), file_);
568 if (fileLen < MAX_FILE_LEN) {
569 std::fill((file_ + fileLen), (file_ + MAX_FILE_LEN), 0);
570 }
571
572 // No need to store fileLen as any empty space is filled with 0s
573}
574
575uint8_t
576// cppcheck-suppress unusedFunction
577Pkt4::DHCPTypeToBootpType(uint8_t dhcpType) {
578 switch (dhcpType) {
579 case DHCPDISCOVER:
580 case DHCPREQUEST:
581 case DHCPDECLINE:
582 case DHCPRELEASE:
583 case DHCPINFORM:
584 case DHCPLEASEQUERY:
586 return (BOOTREQUEST);
587
588 case DHCPACK:
589 case DHCPNAK:
590 case DHCPOFFER:
592 case DHCPLEASEUNKNOWN:
593 case DHCPLEASEACTIVE:
595 return (BOOTREPLY);
596
597 default:
598 isc_throw(OutOfRange, "Invalid message type: "
599 << static_cast<int>(dhcpType) );
600 }
601}
602
603uint8_t
605 if (!hwaddr_) {
606 return (HTYPE_UNDEFINED);
607 }
608 return (hwaddr_->htype_);
609}
610
611uint8_t
613 if (!hwaddr_) {
614 return (0);
615 }
616 uint8_t len = hwaddr_->hwaddr_.size();
617 return (len <= MAX_CHADDR_LEN ? len : MAX_CHADDR_LEN);
618}
619
620void
622 // Check for uniqueness (DHCPv4 options must be unique)
623 if (getNonCopiedOption(opt->getType())) {
624 isc_throw(BadValue, "Option " << opt->getType()
625 << " already present in this message.");
626 }
627
628 Pkt::addOption(opt);
629}
630
631bool
633 return (!giaddr_.isV4Zero() && !giaddr_.isV4Bcast());
634}
635
636std::string
638 std::ostringstream label;
639 label << "hwaddr=";
640 hwaddr_ ? label << hwaddr_->toText(false) : label << "(undefined)";
641 return (label.str());
642}
643
644} // end of namespace isc::dhcp
645} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
A generic exception that is thrown when an unexpected error condition occurs.
Holds Client identifier or client IPv4 address.
Definition duid.h:222
static size_t unpackOptions4(const OptionBuffer &buf, const std::string &option_space, isc::dhcp::OptionCollection &options, std::list< uint16_t > &deferred, bool flexible_pad_end=false)
Parses provided buffer as DHCPv4 options and creates Option objects.
Definition libdhcp++.cc:471
static void extendVendorOptions4(isc::dhcp::OptionCollection &options)
Extend vendor options from fused options in multiple OptionVendor or OptionVendorClass options and ad...
Definition libdhcp++.cc:817
static void packOptions4(isc::util::OutputBuffer &buf, const isc::dhcp::OptionCollection &options, bool top=false, bool check=true)
Stores DHCPv4 options in a buffer.
static bool splitOptions4(isc::dhcp::OptionCollection &options, ScopedOptionsCopyContainer &scopedOptions, uint32_t used=0)
Split long options in multiple options with the same option code (RFC3396).
Forward declaration to OptionInt.
Definition option_int.h:49
virtual void addOption(const OptionPtr &opt)
Add an option.
Definition pkt4.cc:621
virtual void unpack()
Parses on-wire form of DHCPv4 packet.
Definition pkt4.cc:153
std::list< uint16_t > deferred_options_
Definition pkt4.h:508
HWAddrPtr hwaddr_
link-layer address and hardware information represents 3 fields: htype (hardware type,...
Definition pkt4.h:523
const char * getName() const
Returns name of the DHCP message.
Definition pkt4.cc:359
HWAddrPtr local_hwaddr_
local HW address (dst if receiving packet, src if sending packet)
Definition pkt4.h:505
static const size_t MAX_CHADDR_LEN
length of the CHADDR field in DHCPv4 message
Definition pkt4.h:41
void setLocalHWAddr(const uint8_t htype, const uint8_t hlen, const std::vector< uint8_t > &mac_addr)
Sets local HW address.
Definition pkt4.cc:525
std::string getHWAddrLabel() const
Returns text representation of the hardware address.
Definition pkt4.cc:637
uint8_t DHCPTypeToBootpType(uint8_t dhcpType)
converts DHCP message type to BOOTP op type
Definition pkt4.cc:577
std::string getLabel() const
Returns text representation of the primary packet identifiers.
Definition pkt4.cc:367
virtual void pack()
Prepares on-wire format of DHCPv4 packet.
Definition pkt4.cc:73
isc::asiolink::IOAddress giaddr_
giaddr field (32 bits): Gateway IP address
Definition pkt4.h:544
uint8_t file_[MAX_FILE_LEN]
file field (128 bytes)
Definition pkt4.h:550
uint8_t op_
message operation code
Definition pkt4.h:517
uint8_t hops_
Number of relay agents traversed.
Definition pkt4.h:526
const OptionBuffer getFile() const
Returns file field.
Definition pkt4.h:281
const OptionBuffer getSname() const
Returns sname field.
Definition pkt4.h:266
void setSname(const uint8_t *sname, size_t sname_len)
Sets sname field.
Definition pkt4.cc:540
Pkt4(uint8_t msg_type, uint32_t transid)
Constructor, used in replying to a message.
Definition pkt4.cc:34
uint8_t getHlen() const
Returns hlen field.
Definition pkt4.cc:612
static const size_t DHCPV4_PKT_HDR_LEN
specifies DHCPv4 packet header length (fixed part)
Definition pkt4.h:50
bool isRelayed() const
Checks if a DHCPv4 message has been relayed.
Definition pkt4.cc:632
void setFile(const uint8_t *file, size_t file_len)
Sets file field.
Definition pkt4.cc:558
static const size_t MAX_SNAME_LEN
length of the SNAME field in DHCPv4 message
Definition pkt4.h:44
static std::string makeLabel(const HWAddrPtr &hwaddr, const ClientIdPtr &client_id, const uint32_t transid)
Returns text representation of the given packet identifiers.
Definition pkt4.cc:399
uint8_t getType() const
Returns DHCP message type (e.g.
Definition pkt4.cc:236
void setType(uint8_t type)
Sets DHCP message type (e.g.
Definition pkt4.cc:253
isc::asiolink::IOAddress siaddr_
siaddr field (32 bits): next server IP address in boot process(e.g.TFTP)
Definition pkt4.h:541
size_t len()
Returns the size of the required buffer to build the packet.
Definition pkt4.cc:61
uint16_t secs_
elapsed (number of seconds since beginning of transmission)
Definition pkt4.h:529
isc::asiolink::IOAddress ciaddr_
ciaddr field (32 bits): Client's IP address
Definition pkt4.h:535
std::string toText(bool verbose=false) const
Returns text representation of the packet.
Definition pkt4.cc:422
isc::asiolink::IOAddress yiaddr_
yiaddr field (32 bits): Client's IP address ("your"), set by server
Definition pkt4.h:538
uint8_t sname_[MAX_SNAME_LEN]
sname field (64 bytes)
Definition pkt4.h:547
void setHWAddr(uint8_t htype, uint8_t hlen, const std::vector< uint8_t > &mac_addr)
Sets hardware address.
Definition pkt4.cc:490
uint8_t getHtype() const
Returns htype field.
Definition pkt4.cc:604
static const char * getName(const uint8_t type)
Returns name of the DHCP message for a given type number.
Definition pkt4.cc:284
uint16_t flags_
flags
Definition pkt4.h:532
static const size_t MAX_FILE_LEN
length of the FILE field in DHCPv4 message
Definition pkt4.h:47
isc::asiolink::IOAddress remote_addr_
Remote IP address.
Definition pkt.h:947
uint16_t local_port_
local TDP or UDP port
Definition pkt.h:950
uint32_t transid_
Transaction-id (32 bits for v4, 24 bits for v6)
Definition pkt.h:925
isc::asiolink::IOAddress local_addr_
Local IP (v4 or v6) address.
Definition pkt.h:941
OptionBuffer data_
Unparsed data (in received packets).
Definition pkt.h:415
uint16_t remote_port_
remote TCP or UDP port
Definition pkt.h:953
isc::dhcp::OptionCollection options_
Collection of options present in this message.
Definition pkt.h:813
isc::util::OutputBuffer buffer_out_
Output buffer (used during message transmission)
Definition pkt.h:963
Pkt(uint32_t transid, const isc::asiolink::IOAddress &local_addr, const isc::asiolink::IOAddress &remote_addr, uint16_t local_port, uint16_t remote_port)
Constructor.
Definition pkt.cc:24
OptionPtr getNonCopiedOption(const uint16_t type) const
Returns the first option of specified type without copying.
Definition pkt.cc:62
virtual void addOption(const OptionPtr &opt)
Adds an option to this packet.
Definition pkt.cc:57
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition buffer.h:81
void readVector(std::vector< uint8_t > &data, size_t len)
Read specified number of bytes as a vector.
Definition buffer.h:262
uint32_t readUint32()
Read an unsigned 32-bit integer in network byte order from the buffer, and return it.
Definition buffer.h:196
size_t getPosition() const
Return the current read position.
Definition buffer.h:101
uint8_t readUint8()
Read an unsigned 8-bit integer from the buffer and return it.
Definition buffer.h:138
size_t getLength() const
Return the length of the data stored in the buffer.
Definition buffer.h:96
void readData(void *data, size_t len)
Read data of the specified length from the buffer and copy it to the caller supplied buffer.
Definition buffer.h:226
uint16_t readUint16()
Read an unsigned 16-bit integer in network byte order from the buffer, and return it.
Definition buffer.h:166
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
ScopedPktOptionsCopy< Pkt4 > ScopedPkt4OptionsCopy
A pointer to a ScopedPktOptionsCopy object instantiated using Pkt4.
Definition libdhcp++.h:26
@ DHO_DHCP_MESSAGE_TYPE
Definition dhcp4.h:122
@ DHO_DHCP_CLIENT_IDENTIFIER
Definition dhcp4.h:130
@ DHO_END
Definition dhcp4.h:229
@ BOOTREQUEST
Definition dhcp4.h:46
@ BOOTREPLY
Definition dhcp4.h:47
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition hwaddr.h:154
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
Definition duid.h:216
@ DHCPLEASEQUERYSTATUS
Definition dhcp4.h:251
@ DHCPTLS
Definition dhcp4.h:252
@ DHCPREQUEST
Definition dhcp4.h:237
@ DHCPLEASEQUERYDONE
Definition dhcp4.h:249
@ DHCPLEASEUNKNOWN
Definition dhcp4.h:246
@ DHCPOFFER
Definition dhcp4.h:236
@ DHCPLEASEACTIVE
Definition dhcp4.h:247
@ DHCPLEASEQUERY
Definition dhcp4.h:244
@ DHCPDECLINE
Definition dhcp4.h:238
@ DHCPNAK
Definition dhcp4.h:240
@ DHCPRELEASE
Definition dhcp4.h:241
@ DHCPLEASEUNASSIGNED
Definition dhcp4.h:245
@ DHCPDISCOVER
Definition dhcp4.h:235
@ DHCPBULKLEASEQUERY
Definition dhcp4.h:248
@ DHCP_NOTYPE
Message Type option missing.
Definition dhcp4.h:234
@ DHCPINFORM
Definition dhcp4.h:242
@ DHCPACK
Definition dhcp4.h:239
@ HTYPE_UNDEFINED
not specified or undefined
Definition dhcp4.h:55
boost::shared_ptr< Option > OptionPtr
Definition option.h:37
std::string printOrDump(const std::vector< uint8_t > &data, size_t max_dump)
Outputs the contents of a vector as either a string printable characters or a hex dump.
Definition str.cc:351
Defines the logger used by the top-level component of kea-lfc.
#define DHCP4_OPTION_SPACE
global std option spaces
Hardware type that represents information from DHCPv4 packet.
Definition hwaddr.h:20
ScopedOptionsCopyContainer scoped_options_
The container.
Definition libdhcp++.h:49