option_vendor.cc 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright (C) 2013, 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <dhcp/dhcp4.h>
  16. #include <dhcp/dhcp6.h>
  17. #include <dhcp/option_vendor.h>
  18. using namespace isc::dhcp;
  19. OptionVendor::OptionVendor(Option::Universe u, const uint32_t vendor_id)
  20. :Option(u, u==Option::V4?DHO_VIVSO_SUBOPTIONS:D6O_VENDOR_OPTS), vendor_id_(vendor_id) {
  21. }
  22. OptionVendor::OptionVendor(Option::Universe u, OptionBufferConstIter begin,
  23. OptionBufferConstIter end)
  24. :Option(u, u==Option::V4?DHO_VIVSO_SUBOPTIONS:D6O_VENDOR_OPTS), vendor_id_(0) {
  25. unpack(begin, end);
  26. }
  27. void OptionVendor::pack(isc::util::OutputBuffer& buf) {
  28. packHeader(buf);
  29. // Store vendor-id
  30. buf.writeUint32(vendor_id_);
  31. // The format is slightly different for v4
  32. if (universe_ == Option::V4) {
  33. // Calculate and store data-len as follows:
  34. // data-len = total option length - header length
  35. // - enterprise id field length - data-len field size
  36. buf.writeUint8(len() - getHeaderLen() -
  37. sizeof(uint32_t) - sizeof(uint8_t));
  38. }
  39. packOptions(buf);
  40. }
  41. void OptionVendor::unpack(OptionBufferConstIter begin,
  42. OptionBufferConstIter end) {
  43. if (distance(begin, end) < sizeof(uint32_t)) {
  44. isc_throw(OutOfRange, "Truncated vendor-specific information option"
  45. << ", length=" << distance(begin, end));
  46. }
  47. vendor_id_ = isc::util::readUint32(&(*begin), distance(begin, end));
  48. OptionBuffer vendor_buffer(begin +4, end);
  49. if (universe_ == Option::V6) {
  50. LibDHCP::unpackVendorOptions6(vendor_id_, vendor_buffer, options_);
  51. } else {
  52. LibDHCP::unpackVendorOptions4(vendor_id_, vendor_buffer, options_);
  53. }
  54. }
  55. uint16_t OptionVendor::len() {
  56. uint16_t length = getHeaderLen();
  57. length += sizeof(uint32_t); // Vendor-id field
  58. // Data-len field exists in DHCPv4 vendor options only
  59. if (universe_ == Option::V4) {
  60. length += sizeof(uint8_t); // data-len
  61. }
  62. // length of all suboptions
  63. for (OptionCollection::iterator it = options_.begin();
  64. it != options_.end();
  65. ++it) {
  66. length += (*it).second->len();
  67. }
  68. return (length);
  69. }