Kea 1.5.0
option_custom.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2018 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>
8#include <dhcp/libdhcp++.h>
10#include <dhcp/option_custom.h>
11#include <util/encode/hex.h>
12
13using namespace isc::asiolink;
14
15namespace isc {
16namespace dhcp {
17
19 Universe u)
20 : Option(u, def.getCode(), OptionBuffer()),
21 definition_(def) {
23 createBuffers();
24}
25
27 Universe u,
28 const OptionBuffer& data)
29 : Option(u, def.getCode(), data.begin(), data.end()),
30 definition_(def) {
32 createBuffers(getData());
33}
34
36 Universe u,
39 : Option(u, def.getCode(), first, last),
40 definition_(def) {
42 createBuffers(getData());
43}
44
47 return (cloneInternal<OptionCustom>());
48}
49
50void
52 checkArrayType();
53
54 if ((address.isV4() && definition_.getType() != OPT_IPV4_ADDRESS_TYPE) ||
55 (address.isV6() && definition_.getType() != OPT_IPV6_ADDRESS_TYPE)) {
56 isc_throw(BadDataTypeCast, "invalid address specified "
57 << address << ". Expected a valid IPv"
58 << (definition_.getType() == OPT_IPV4_ADDRESS_TYPE ?
59 "4" : "6") << " address.");
60 }
61
62 OptionBuffer buf;
64 buffers_.push_back(buf);
65}
66
67void
68OptionCustom::addArrayDataField(const std::string& value) {
69 checkArrayType();
70
73 OptionBuffer buf;
74 OptionDataTypeUtil::writeTuple(value, lft, buf);
75 buffers_.push_back(buf);
76}
77
78void
80 checkArrayType();
81
82 OptionBuffer buf;
84 buffers_.push_back(buf);
85}
86
87void
89 checkArrayType();
90
91 OptionBuffer buf;
93 buffers_.push_back(buf);
94}
95
96void
98 const asiolink::IOAddress& prefix) {
99 checkArrayType();
100
101 if (definition_.getType() != OPT_IPV6_PREFIX_TYPE) {
102 isc_throw(BadDataTypeCast, "IPv6 prefix can be specified only for"
103 " an option comprising an array of IPv6 prefix values");
104 }
105
106 OptionBuffer buf;
107 OptionDataTypeUtil::writePrefix(prefix_len, prefix, buf);
108 buffers_.push_back(buf);
109}
110
111void
112OptionCustom::addArrayDataField(const PSIDLen& psid_len, const PSID& psid) {
113 checkArrayType();
114
115 if (definition_.getType() != OPT_PSID_TYPE) {
116 isc_throw(BadDataTypeCast, "PSID value can be specified onlu for"
117 " an option comprising an array of PSID length / value"
118 " tuples");
119 }
120
121 OptionBuffer buf;
122 OptionDataTypeUtil::writePsid(psid_len, psid, buf);
123 buffers_.push_back(buf);
124}
125
126void
127OptionCustom::checkIndex(const uint32_t index) const {
128 if (index >= buffers_.size()) {
129 isc_throw(isc::OutOfRange, "specified data field index " << index
130 << " is out of range.");
131 }
132}
133
134void
135OptionCustom::createBuffer(OptionBuffer& buffer,
136 const OptionDataType data_type) const {
137 // For data types that have a fixed size we can use the
138 // utility function to get the buffer's size.
139 size_t data_size = OptionDataTypeUtil::getDataTypeLen(data_type);
140
141 // For variable data sizes the utility function returns zero.
142 // It is ok for string values because the default string
143 // is 'empty'. However for FQDN the empty value is not valid
144 // so we initialize it to '.'. For prefix there is a prefix
145 // length fixed field.
146 if (data_size == 0) {
147 if (data_type == OPT_FQDN_TYPE) {
149
150 } else if (data_type == OPT_IPV6_PREFIX_TYPE) {
153 buffer);
154 }
155 } else {
156 // At this point we can resize the buffer. Note that
157 // for string values we are setting the empty buffer
158 // here.
159 buffer.resize(data_size);
160 }
161}
162
163void
164OptionCustom::createBuffers() {
165 definition_.validate();
166
167 std::vector<OptionBuffer> buffers;
168
169 OptionDataType data_type = definition_.getType();
170 // This function is called when an empty data buffer has been
171 // passed to the constructor. In such cases values for particular
172 // data fields will be set using modifier functions but for now
173 // we need to initialize a set of buffers that are specified
174 // for an option by its definition. Since there is no data yet,
175 // we are going to fill these buffers with default values.
176 if (data_type == OPT_RECORD_TYPE) {
177 // For record types we need to iterate over all data fields
178 // specified in option definition and create corresponding
179 // buffers for each of them.
181 definition_.getRecordFields();
182
183 for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
184 field != fields.end(); ++field) {
185 OptionBuffer buf;
186 createBuffer(buf, *field);
187 // We have the buffer with default value prepared so we
188 // add it to the set of buffers.
189 buffers.push_back(buf);
190 }
191 } else if (!definition_.getArrayType() &&
192 data_type != OPT_EMPTY_TYPE) {
193 // For either 'empty' options we don't have to create any buffers
194 // for obvious reason. For arrays we also don't create any buffers
195 // yet because the set of fields that belong to the array is open
196 // ended so we can't allocate required buffers until we know how
197 // many of them are needed.
198 // For non-arrays we have a single value being held by the option
199 // so we have to allocate exactly one buffer.
200 OptionBuffer buf;
201 createBuffer(buf, data_type);
202 // Add a buffer that we have created and leave.
203 buffers.push_back(buf);
204 }
205 // The 'swap' is used here because we want to make sure that we
206 // don't touch buffers_ until we successfully allocate all
207 // buffers to be stored there.
208 std::swap(buffers, buffers_);
209}
210
211size_t
212OptionCustom::bufferLength(const OptionDataType data_type, bool in_array,
213 OptionBuffer::const_iterator begin,
214 OptionBuffer::const_iterator end) const {
215 // For fixed-size data type such as boolean, integer, even
216 // IP address we can use the utility function to get the required
217 // buffer size.
218 size_t data_size = OptionDataTypeUtil::getDataTypeLen(data_type);
219
220 // For variable size types (e.g. string) the function above will
221 // return 0 so we need to do a runtime check of the length.
222 if (data_size == 0) {
223 // FQDN is a special data type as it stores variable length data
224 // but the data length is encoded in the buffer. The easiest way
225 // to obtain the length of the data is to read the FQDN. The
226 // utility function will return the size of the buffer on success.
227 if (data_type == OPT_FQDN_TYPE) {
228 std::string fqdn =
230 // The size of the buffer holding an FQDN is always
231 // 1 byte larger than the size of the string
232 // representation of this FQDN.
233 data_size = fqdn.size() + 1;
234 } else if (!definition_.getArrayType() &&
235 ((data_type == OPT_BINARY_TYPE) ||
236 (data_type == OPT_STRING_TYPE))) {
237 // In other case we are dealing with string or binary value
238 // which size can't be determined. Thus we consume the
239 // remaining part of the buffer for it. Note that variable
240 // size data can be laid at the end of the option only and
241 // that the validate() function in OptionDefinition object
242 // should have checked wheter it is a case for this option.
243 data_size = std::distance(begin, end);
244 } else if (data_type == OPT_IPV6_PREFIX_TYPE) {
245 // The size of the IPV6 prefix type is determined as
246 // one byte (which is the size of the prefix in bits)
247 // followed by the prefix bits (right-padded with
248 // zeros to the nearest octet boundary)
249 if ((begin == end) && !in_array)
250 return 0;
251 PrefixTuple prefix =
253 // Data size comprises 1 byte holding a prefix length and the
254 // prefix length (in bytes) rounded to the nearest byte boundary.
255 data_size = sizeof(uint8_t) + (prefix.first.asUint8() + 7) / 8;
256 } else if (data_type == OPT_TUPLE_TYPE) {
261 std::string value =
263 data_size = value.size();
264 // The size of the buffer holding a tuple is always
265 // 1 or 2 byte larger than the size of the string
266 data_size += getUniverse() == Option::V4 ? 1 : 2;
267 } else {
268 // If we reached the end of buffer we assume that this option is
269 // truncated because there is no remaining data to initialize
270 // an option field.
271 isc_throw(OutOfRange, "option buffer truncated");
272 }
273 }
274
275 return data_size;
276}
277
278void
279OptionCustom::createBuffers(const OptionBuffer& data_buf) {
280 // Check that the option definition is correct as we are going
281 // to use it to split the data_ buffer into set of sub buffers.
282 definition_.validate();
283
284 std::vector<OptionBuffer> buffers;
285 OptionBuffer::const_iterator data = data_buf.begin();
286
287 OptionDataType data_type = definition_.getType();
288 if (data_type == OPT_RECORD_TYPE) {
289 // An option comprises a record of data fields. We need to
290 // get types of these data fields to allocate enough space
291 // for each buffer.
293 definition_.getRecordFields();
294
295 // Go over all data fields within a record.
296 for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
297 field != fields.end(); ++field) {
298 size_t data_size = bufferLength(*field, false,
299 data, data_buf.end());
300
301 // Our data field requires that there is a certain chunk of
302 // data left in the buffer. If not, option is truncated.
303 if (std::distance(data, data_buf.end()) < data_size) {
304 isc_throw(OutOfRange, "option buffer truncated");
305 }
306
307 // Store the created buffer.
308 buffers.push_back(OptionBuffer(data, data + data_size));
309 // Proceed to the next data field.
310 data += data_size;
311 }
312
313 // Get extra buffers when the last field is an array.
314 if (definition_.getArrayType()) {
315 while (data != data_buf.end()) {
316 // Code copied from the standard array case
317 size_t data_size = bufferLength(fields.back(), true,
318 data, data_buf.end());
319 assert(data_size > 0);
320 if (std::distance(data, data_buf.end()) < data_size) {
321 break;
322 }
323 buffers.push_back(OptionBuffer(data, data + data_size));
324 data += data_size;
325 }
326 }
327
328 // Unpack suboptions if any.
329 else if (data != data_buf.end() && !getEncapsulatedSpace().empty()) {
330 unpackOptions(OptionBuffer(data, data_buf.end()));
331 }
332
333 } else if (data_type != OPT_EMPTY_TYPE) {
334 // If data_type value is other than OPT_RECORD_TYPE, our option is
335 // empty (have no data at all) or it comprises one or more
336 // data fields of the same type. The type of those fields
337 // is held in the data_type variable so let's use it to determine
338 // a size of buffers.
339 size_t data_size = OptionDataTypeUtil::getDataTypeLen(data_type);
340 // The check below will fail if the input buffer is too short
341 // for the data size being held by this option.
342 // Note that data_size returned by getDataTypeLen may be zero
343 // if variable length data is being held by the option but
344 // this will not cause this check to throw exception.
345 if (std::distance(data, data_buf.end()) < data_size) {
346 isc_throw(OutOfRange, "option buffer truncated");
347 }
348 // For an array of values we are taking different path because
349 // we have to handle multiple buffers.
350 if (definition_.getArrayType()) {
351 while (data != data_buf.end()) {
352 data_size = bufferLength(data_type, true, data, data_buf.end());
353 // We don't perform other checks for data types that can't be
354 // used together with array indicator such as strings, empty field
355 // etc. This is because OptionDefinition::validate function should
356 // have checked this already. Thus data_size must be greater than
357 // zero.
358 assert(data_size > 0);
359 // Get chunks of data and store as a collection of buffers.
360 // Truncate any remaining part which length is not divisible by
361 // data_size. Note that it is ok to truncate the data if and only
362 // if the data buffer is long enough to keep at least one value.
363 // This has been checked above already.
364 if (std::distance(data, data_buf.end()) < data_size) {
365 break;
366 }
367 buffers.push_back(OptionBuffer(data, data + data_size));
368 data += data_size;
369 }
370 } else {
371 // For non-arrays the data_size can be zero because
372 // getDataTypeLen returns zero for variable size data types
373 // such as strings. Simply take whole buffer.
374 data_size = bufferLength(data_type, false, data, data_buf.end());
375 if ((data_size > 0) && (std::distance(data, data_buf.end()) >= data_size)) {
376 buffers.push_back(OptionBuffer(data, data + data_size));
377 data += data_size;
378 } else {
379 isc_throw(OutOfRange, "option buffer truncated");
380 }
381
382 // Unpack suboptions if any.
383 if (data != data_buf.end() && !getEncapsulatedSpace().empty()) {
384 unpackOptions(OptionBuffer(data, data_buf.end()));
385 }
386 }
387 } else {
388 // Unpack suboptions if any.
389 if (data != data_buf.end() && !getEncapsulatedSpace().empty()) {
390 unpackOptions(OptionBuffer(data, data_buf.end()));
391 }
392 }
393 // If everything went ok we can replace old buffer set with new ones.
394 std::swap(buffers_, buffers);
395}
396
397std::string
398OptionCustom::dataFieldToText(const OptionDataType data_type,
399 const uint32_t index) const {
400 std::ostringstream text;
401
402 // Get the value of the data field.
403 switch (data_type) {
404 case OPT_BINARY_TYPE:
405 text << util::encode::encodeHex(readBinary(index));
406 break;
407 case OPT_BOOLEAN_TYPE:
408 text << (readBoolean(index) ? "true" : "false");
409 break;
410 case OPT_INT8_TYPE:
411 text << static_cast<int>(readInteger<int8_t>(index));
412 break;
413 case OPT_INT16_TYPE:
414 text << readInteger<int16_t>(index);
415 break;
416 case OPT_INT32_TYPE:
417 text << readInteger<int32_t>(index);
418 break;
419 case OPT_UINT8_TYPE:
420 text << static_cast<unsigned>(readInteger<uint8_t>(index));
421 break;
422 case OPT_UINT16_TYPE:
423 text << readInteger<uint16_t>(index);
424 break;
425 case OPT_UINT32_TYPE:
426 text << readInteger<uint32_t>(index);
427 break;
430 text << readAddress(index);
431 break;
432 case OPT_FQDN_TYPE:
433 text << "\"" << readFqdn(index) << "\"";
434 break;
435 case OPT_TUPLE_TYPE:
436 text << "\"" << readTuple(index) << "\"";
437 break;
438 case OPT_STRING_TYPE:
439 text << "\"" << readString(index) << "\"";
440 break;
441 case OPT_PSID_TYPE:
442 {
443 PSIDTuple t = readPsid(index);
444 text << "len=" << t.first.asUnsigned() << ",psid=" << t.second.asUint16();
445 }
446 default:
447 ;
448 }
449
450 // Append data field type in brackets.
451 text << " (" << OptionDataTypeUtil::getDataTypeName(data_type) << ")";
452
453 return (text.str());
454}
455
456void
458
459 // Pack DHCP header (V4 or V6).
460 packHeader(buf);
461
462 // Write data from buffers.
463 for (std::vector<OptionBuffer>::const_iterator it = buffers_.begin();
464 it != buffers_.end(); ++it) {
465 // In theory the createBuffers function should have taken
466 // care that there are no empty buffers added to the
467 // collection but it is almost always good to make sure.
468 if (!it->empty()) {
469 buf.writeData(&(*it)[0], it->size());
470 }
471 }
472
473 // Write suboptions.
474 packOptions(buf);
475}
476
477
479OptionCustom::readAddress(const uint32_t index) const {
480 checkIndex(index);
481
482 // The address being read can be either IPv4 or IPv6. The decision
483 // is made based on the buffer length. If it holds 4 bytes it is IPv4
484 // address, if it holds 16 bytes it is IPv6.
485 if (buffers_[index].size() == asiolink::V4ADDRESS_LEN) {
486 return (OptionDataTypeUtil::readAddress(buffers_[index], AF_INET));
487 } else if (buffers_[index].size() == asiolink::V6ADDRESS_LEN) {
488 return (OptionDataTypeUtil::readAddress(buffers_[index], AF_INET6));
489 } else {
490 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
491 << " IP address. Invalid buffer length "
492 << buffers_[index].size() << ".");
493 }
494}
495
496void
498 const uint32_t index) {
499 checkIndex(index);
500
501 if ((address.isV4() && buffers_[index].size() != V4ADDRESS_LEN) ||
502 (address.isV6() && buffers_[index].size() != V6ADDRESS_LEN)) {
503 isc_throw(BadDataTypeCast, "invalid address specified "
504 << address << ". Expected a valid IPv"
505 << (buffers_[index].size() == V4ADDRESS_LEN ? "4" : "6")
506 << " address.");
507 }
508
509 OptionBuffer buf;
511 std::swap(buf, buffers_[index]);
512}
513
514const OptionBuffer&
515OptionCustom::readBinary(const uint32_t index) const {
516 checkIndex(index);
517 return (buffers_[index]);
518}
519
520void
522 const uint32_t index) {
523 checkIndex(index);
524 buffers_[index] = buf;
525}
526
527std::string
528OptionCustom::readTuple(const uint32_t index) const {
529 checkIndex(index);
532 return (OptionDataTypeUtil::readTuple(buffers_[index], lft));
533}
534
535void
537 const uint32_t index) const {
538 checkIndex(index);
539 OptionDataTypeUtil::readTuple(buffers_[index], tuple);
540}
541
542void
543OptionCustom::writeTuple(const std::string& value, const uint32_t index) {
544 checkIndex(index);
545
546 buffers_[index].clear();
549 OptionDataTypeUtil::writeTuple(value, lft, buffers_[index]);
550}
551
552void
553OptionCustom::writeTuple(const OpaqueDataTuple& value, const uint32_t index) {
554 checkIndex(index);
555
556 buffers_[index].clear();
557 OptionDataTypeUtil::writeTuple(value, buffers_[index]);
558}
559
560bool
561OptionCustom::readBoolean(const uint32_t index) const {
562 checkIndex(index);
563 return (OptionDataTypeUtil::readBool(buffers_[index]));
564}
565
566void
567OptionCustom::writeBoolean(const bool value, const uint32_t index) {
568 checkIndex(index);
569
570 buffers_[index].clear();
571 OptionDataTypeUtil::writeBool(value, buffers_[index]);
572}
573
574std::string
575OptionCustom::readFqdn(const uint32_t index) const {
576 checkIndex(index);
577 return (OptionDataTypeUtil::readFqdn(buffers_[index]));
578}
579
580void
581OptionCustom::writeFqdn(const std::string& fqdn, const uint32_t index) {
582 checkIndex(index);
583
584 // Create a temporary buffer where the FQDN will be written.
585 OptionBuffer buf;
586 // Try to write to the temporary buffer rather than to the
587 // buffers_ member directly guarantees that we don't modify
588 // (clear) buffers_ until we are sure that the provided FQDN
589 // is valid.
591 // If we got to this point it means that the FQDN is valid.
592 // We can move the contents of the temporary buffer to the
593 // target buffer.
594 std::swap(buffers_[index], buf);
595}
596
598OptionCustom::readPrefix(const uint32_t index) const {
599 checkIndex(index);
600 return (OptionDataTypeUtil::readPrefix(buffers_[index]));
601}
602
603void
605 const IOAddress& prefix,
606 const uint32_t index) {
607 checkIndex(index);
608
609 OptionBuffer buf;
610 OptionDataTypeUtil::writePrefix(prefix_len, prefix, buf);
611 // If there are no errors while writing PSID to a buffer, we can
612 // replace the current buffer with a new buffer.
613 std::swap(buffers_[index], buf);
614}
615
616
618OptionCustom::readPsid(const uint32_t index) const {
619 checkIndex(index);
620 return (OptionDataTypeUtil::readPsid(buffers_[index]));
621}
622
623void
624OptionCustom::writePsid(const PSIDLen& psid_len, const PSID& psid,
625 const uint32_t index) {
626 checkIndex(index);
627
628 OptionBuffer buf;
629 OptionDataTypeUtil::writePsid(psid_len, psid, buf);
630 // If there are no errors while writing PSID to a buffer, we can
631 // replace the current buffer with a new buffer.
632 std::swap(buffers_[index], buf);
633}
634
635
636std::string
637OptionCustom::readString(const uint32_t index) const {
638 checkIndex(index);
639 return (OptionDataTypeUtil::readString(buffers_[index]));
640}
641
642void
643OptionCustom::writeString(const std::string& text, const uint32_t index) {
644 checkIndex(index);
645
646 // Let's clear a buffer as we want to replace the value of the
647 // whole buffer. If we fail to clear the buffer the data will
648 // be appended.
649 buffers_[index].clear();
650 // If the text value is empty we can leave because the buffer
651 // is already empty.
652 if (!text.empty()) {
653 OptionDataTypeUtil::writeString(text, buffers_[index]);
654 }
655}
656
657void
660 initialize(begin, end);
661}
662
663uint16_t
665 // The length of the option is a sum of option header ...
666 size_t length = getHeaderLen();
667
668 // ... lengths of all buffers that hold option data ...
669 for (std::vector<OptionBuffer>::const_iterator buf = buffers_.begin();
670 buf != buffers_.end(); ++buf) {
671 length += buf->size();
672 }
673
674 // ... and lengths of all suboptions
675 for (OptionCollection::const_iterator it = options_.begin();
676 it != options_.end();
677 ++it) {
678 length += (*it).second->len();
679 }
680
681 return (static_cast<uint16_t>(length));
682}
683
685 const OptionBufferConstIter last) {
686 setData(first, last);
687
688 // Chop the data_ buffer into set of buffers that represent
689 // option fields data.
690 createBuffers(getData());
691}
692
693std::string OptionCustom::toText(int indent) const {
694 std::stringstream output;
695
696 output << headerToText(indent) << ":";
697
698 OptionDataType data_type = definition_.getType();
699 if (data_type == OPT_RECORD_TYPE) {
701 definition_.getRecordFields();
702
703 // For record types we iterate over fields defined in
704 // option definition and match the appropriate buffer
705 // with them.
706 for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
707 field != fields.end(); ++field) {
708 output << " " << dataFieldToText(*field, std::distance(fields.begin(),
709 field));
710 }
711
712 // If the last record field is an array iterate on extra buffers
713 if (definition_.getArrayType()) {
714 for (unsigned int i = fields.size(); i < getDataFieldsNum(); ++i) {
715 output << " " << dataFieldToText(fields.back(), i);
716 }
717 }
718 } else {
719 // For non-record types we iterate over all buffers
720 // and print the data type set globally for an option
721 // definition. We take the same code path for arrays
722 // and non-arrays as they only differ in such a way that
723 // non-arrays have just single data field.
724 for (unsigned int i = 0; i < getDataFieldsNum(); ++i) {
725 output << " " << dataFieldToText(definition_.getType(), i);
726 }
727 }
728
729 // Append suboptions.
730 output << suboptionsToText(indent + 2);
731
732 return (output.str());
733}
734
735} // end of isc::dhcp namespace
736} // end of isc namespace
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
Exception to be thrown when cast to the data type was unsuccessful.
Represents a single instance of the opaque data preceded by length.
LengthFieldType
Size of the length field in the tuple.
std::string readString(const uint32_t index=0) const
Read a buffer as string value.
bool readBoolean(const uint32_t index=0) const
Read a buffer as boolean value.
virtual uint16_t len() const
Returns length of the complete option (data length + DHCPv4/DHCPv6 option header)
std::string readTuple(const uint32_t index=0) const
Read a buffer as length and string tuple.
void writeFqdn(const std::string &fqdn, const uint32_t index=0)
Write an FQDN into a buffer.
std::string readFqdn(const uint32_t index=0) const
Read a buffer as FQDN.
void writePrefix(const PrefixLen &prefix_len, const asiolink::IOAddress &prefix, const uint32_t index=0)
Write prefix length and value into a buffer.
virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end)
Parses received buffer.
void writeAddress(const asiolink::IOAddress &address, const uint32_t index=0)
Write an IP address into a buffer.
void initialize(const OptionBufferConstIter first, const OptionBufferConstIter last)
Sets content of this option from buffer.
const OptionBuffer & readBinary(const uint32_t index=0) const
Read a buffer as binary data.
PrefixTuple readPrefix(const uint32_t index=0) const
Read a buffer as variable length prefix.
void writePsid(const PSIDLen &psid_len, const PSID &psid, const uint32_t index=0)
Write PSID length / value into a buffer.
void writeBoolean(const bool value, const uint32_t index=0)
Write a boolean value into a buffer.
asiolink::IOAddress readAddress(const uint32_t index=0) const
Read a buffer as IP address.
PSIDTuple readPsid(const uint32_t index=0) const
Read a buffer as a PSID length / value tuple.
void writeString(const std::string &text, const uint32_t index=0)
Write a string value into a buffer.
void writeBinary(const OptionBuffer &buf, const uint32_t index=0)
Write binary data into a buffer.
void addArrayDataField(const asiolink::IOAddress &address)
Create new buffer and set its value as an IP address.
virtual OptionPtr clone() const
Copies this option and returns a pointer to the copy.
void writeTuple(const std::string &value, const uint32_t index=0)
Write a length and string tuple into a buffer.
virtual std::string toText(int indent=0) const
Returns string representation of the option.
OptionCustom(const OptionDefinition &def, Universe u)
Constructor, used for options to be sent.
uint32_t getDataFieldsNum() const
Return a number of the data fields.
virtual void pack(isc::util::OutputBuffer &buf) const
Writes DHCP option in a wire format to a buffer.
static PrefixTuple readPrefix(const std::vector< uint8_t > &buf)
Read prefix from a buffer.
static asiolink::IOAddress readAddress(const std::vector< uint8_t > &buf, const short family)
Read IPv4 or IPv6 address from a buffer.
static void writeFqdn(const std::string &fqdn, std::vector< uint8_t > &buf, const bool downcase=false)
Append FQDN into a buffer.
static void writePrefix(const PrefixLen &prefix_len, const asiolink::IOAddress &prefix, std::vector< uint8_t > &buf)
Append prefix into a buffer.
static const std::string & getDataTypeName(const OptionDataType data_type)
Return option data type name from the data type enumerator.
static int getDataTypeLen(const OptionDataType data_type)
Get data type buffer length.
static std::string readFqdn(const std::vector< uint8_t > &buf)
Read FQDN from a buffer as a string value.
static std::string readTuple(const std::vector< uint8_t > &buf, OpaqueDataTuple::LengthFieldType lengthfieldtype)
Read length and string tuple from a buffer.
static void writeAddress(const asiolink::IOAddress &address, std::vector< uint8_t > &buf)
Append IPv4 or IPv6 address to a buffer.
static PSIDTuple readPsid(const std::vector< uint8_t > &buf)
Read PSID length / value tuple from a buffer.
static void writePsid(const PSIDLen &psid_len, const PSID &psid, std::vector< uint8_t > &buf)
Append PSID length/value into a buffer.
static void writeString(const std::string &value, std::vector< uint8_t > &buf)
Write UTF8-encoded string into a buffer.
static void writeTuple(const std::string &value, OpaqueDataTuple::LengthFieldType lengthfieldtype, std::vector< uint8_t > &buf)
Append length and string tuple to a buffer.
static void writeBool(const bool value, std::vector< uint8_t > &buf)
Append boolean value into a buffer.
static bool readBool(const std::vector< uint8_t > &buf)
Read boolean value from a buffer.
static std::string readString(const std::vector< uint8_t > &buf)
Read string value from a buffer.
Base class representing a DHCP option definition.
OptionDataType getType() const
Return option data type.
std::vector< OptionDataType >::const_iterator RecordFieldsConstIter
Const iterator for record data fields.
const RecordFieldsCollection & getRecordFields() const
Return list of record fields.
void validate() const
Check if the option definition is valid.
std::vector< OptionDataType > RecordFieldsCollection
List of fields within the record.
std::string getEncapsulatedSpace() const
Return name of the encapsulated option space.
bool getArrayType() const
Return array type indicator.
std::string headerToText(const int indent=0, const std::string &type_name="") const
Returns option header in the textual format.
Definition: option.cc:294
std::string suboptionsToText(const int indent=0) const
Returns collection of suboptions in the textual format.
Definition: option.cc:313
std::string getEncapsulatedSpace() const
Returns the name of the option space encapsulated by this option.
Definition: option.h:381
void setEncapsulatedSpace(const std::string &encapsulated_space)
Sets the name of the option space encapsulated by this option.
Definition: option.h:374
virtual const OptionBuffer & getData() const
Returns pointer to actual data.
Definition: option.h:268
virtual uint16_t getHeaderLen() const
Returns length of header (2 for v4, 4 for v6)
Definition: option.cc:328
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:67
void unpackOptions(const OptionBuffer &buf)
Builds a collection of sub options from the buffer.
Definition: option.cc:156
void packOptions(isc::util::OutputBuffer &buf) const
Store sub options in a buffer.
Definition: option.cc:137
OptionCollection options_
collection for storing suboptions
Definition: option.h:521
Universe getUniverse() const
returns option universe (V4 or V6)
Definition: option.h:190
void packHeader(isc::util::OutputBuffer &buf) const
Store option's header in a buffer.
Definition: option.cc:117
Encapsulates PSID length.
Encapsulates PSID value.
Encapsulates prefix length.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:547
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
std::pair< PSIDLen, PSID > PSIDTuple
Defines a pair of PSID length / value.
OptionDataType
Data types of DHCP option fields.
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
Definition: option.h:31
std::pair< PrefixLen, asiolink::IOAddress > PrefixTuple
Defines a pair of prefix length / value.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:25
boost::shared_ptr< Option > OptionPtr
Definition: option.h:38
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
Definition: base_n.cc:461
Defines the logger used by the top-level component of kea-dhcp-ddns.