option_vendor.cc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Copyright (C) 2013-2015 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. #include <config.h>
  7. #include <dhcp/dhcp4.h>
  8. #include <dhcp/dhcp6.h>
  9. #include <dhcp/option_vendor.h>
  10. #include <sstream>
  11. using namespace isc::dhcp;
  12. OptionVendor::OptionVendor(Option::Universe u, const uint32_t vendor_id)
  13. :Option(u, u==Option::V4?DHO_VIVSO_SUBOPTIONS:D6O_VENDOR_OPTS), vendor_id_(vendor_id) {
  14. }
  15. OptionVendor::OptionVendor(Option::Universe u, OptionBufferConstIter begin,
  16. OptionBufferConstIter end)
  17. :Option(u, u==Option::V4?DHO_VIVSO_SUBOPTIONS:D6O_VENDOR_OPTS), vendor_id_(0) {
  18. unpack(begin, end);
  19. }
  20. void OptionVendor::pack(isc::util::OutputBuffer& buf) const {
  21. packHeader(buf);
  22. // Store vendor-id
  23. buf.writeUint32(vendor_id_);
  24. // The format is slightly different for v4
  25. if (universe_ == Option::V4) {
  26. // Calculate and store data-len as follows:
  27. // data-len = total option length - header length
  28. // - enterprise id field length - data-len field size
  29. buf.writeUint8(dataLen());
  30. }
  31. packOptions(buf);
  32. }
  33. void OptionVendor::unpack(OptionBufferConstIter begin,
  34. OptionBufferConstIter end) {
  35. if (distance(begin, end) < sizeof(uint32_t)) {
  36. isc_throw(OutOfRange, "Truncated vendor-specific information option"
  37. << ", length=" << distance(begin, end));
  38. }
  39. vendor_id_ = isc::util::readUint32(&(*begin), distance(begin, end));
  40. OptionBuffer vendor_buffer(begin + 4, end);
  41. if (universe_ == Option::V6) {
  42. LibDHCP::unpackVendorOptions6(vendor_id_, vendor_buffer, options_);
  43. } else {
  44. LibDHCP::unpackVendorOptions4(vendor_id_, vendor_buffer, options_);
  45. }
  46. }
  47. uint16_t OptionVendor::len() const {
  48. uint16_t length = getHeaderLen();
  49. length += sizeof(uint32_t); // Vendor-id field
  50. // Data-len field exists in DHCPv4 vendor options only
  51. if (universe_ == Option::V4) {
  52. length += sizeof(uint8_t); // data-len
  53. }
  54. // length of all suboptions
  55. for (OptionCollection::const_iterator it = options_.begin();
  56. it != options_.end();
  57. ++it) {
  58. length += (*it).second->len();
  59. }
  60. return (length);
  61. }
  62. uint8_t
  63. OptionVendor::dataLen() const {
  64. // Calculate and store data-len as follows:
  65. // data-len = total option length - header length
  66. // - enterprise id field length - data-len field size
  67. return (len() - getHeaderLen() - sizeof(uint32_t) - sizeof(uint8_t));
  68. }
  69. std::string
  70. OptionVendor::toText(int indent) const {
  71. std::stringstream output;
  72. output << headerToText(indent) << ": "
  73. << getVendorId() << " (uint32)";
  74. // For the DHCPv4 there is one more field.
  75. if (getUniverse() == Option::V4) {
  76. output << " " << static_cast<int>(dataLen()) << " (uint8)";
  77. }
  78. // Append suboptions.
  79. output << suboptionsToText(indent + 2);
  80. return (output.str());
  81. }