option6_addrlst.cc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright (C) 2011-2016 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 <asiolink/io_address.h>
  8. #include <dhcp/dhcp6.h>
  9. #include <dhcp/libdhcp++.h>
  10. #include <dhcp/option6_addrlst.h>
  11. #include <exceptions/exceptions.h>
  12. #include <util/io_utilities.h>
  13. #include <sstream>
  14. #include <arpa/inet.h>
  15. #include <stdint.h>
  16. using namespace std;
  17. using namespace isc;
  18. using namespace isc::dhcp;
  19. using namespace isc::asiolink;
  20. using namespace isc::util;
  21. namespace isc {
  22. namespace dhcp {
  23. Option6AddrLst::Option6AddrLst(uint16_t type, const AddressContainer& addrs)
  24. :Option(V6, type), addrs_(addrs) {
  25. }
  26. Option6AddrLst::Option6AddrLst(uint16_t type, const isc::asiolink::IOAddress& addr)
  27. :Option(V6, type), addrs_(1,addr) {
  28. }
  29. Option6AddrLst::Option6AddrLst(uint16_t type, OptionBufferConstIter begin,
  30. OptionBufferConstIter end)
  31. :Option(V6, type) {
  32. unpack(begin, end);
  33. }
  34. OptionPtr
  35. Option6AddrLst::clone() const {
  36. return (cloneInternal<Option6AddrLst>());
  37. }
  38. void
  39. Option6AddrLst::setAddress(const isc::asiolink::IOAddress& addr) {
  40. if (!addr.isV6()) {
  41. isc_throw(BadValue, "Can't store non-IPv6 address in Option6AddrLst option");
  42. }
  43. addrs_.clear();
  44. addrs_.push_back(addr);
  45. }
  46. void
  47. Option6AddrLst::setAddresses(const AddressContainer& addrs) {
  48. addrs_ = addrs;
  49. }
  50. void Option6AddrLst::pack(isc::util::OutputBuffer& buf) const {
  51. buf.writeUint16(type_);
  52. // len() returns complete option length.
  53. // len field contains length without 4-byte option header
  54. buf.writeUint16(len() - getHeaderLen());
  55. for (AddressContainer::const_iterator addr=addrs_.begin();
  56. addr!=addrs_.end(); ++addr) {
  57. if (!addr->isV6()) {
  58. isc_throw(isc::BadValue, addr->toText()
  59. << " is not an IPv6 address");
  60. }
  61. // If an address is IPv6 address it should have assumed
  62. // length of V6ADDRESS_LEN.
  63. buf.writeData(&addr->toBytes()[0], V6ADDRESS_LEN);
  64. }
  65. }
  66. void Option6AddrLst::unpack(OptionBufferConstIter begin,
  67. OptionBufferConstIter end) {
  68. if ((distance(begin, end) % V6ADDRESS_LEN) != 0) {
  69. isc_throw(OutOfRange, "Option " << type_
  70. << " malformed: len=" << distance(begin, end)
  71. << " is not divisible by 16.");
  72. }
  73. while (begin != end) {
  74. addrs_.push_back(IOAddress::fromBytes(AF_INET6, &(*begin)));
  75. begin += V6ADDRESS_LEN;
  76. }
  77. }
  78. std::string Option6AddrLst::toText(int indent) const {
  79. stringstream output;
  80. output << headerToText(indent) << ":";
  81. for (AddressContainer::const_iterator addr = addrs_.begin();
  82. addr != addrs_.end(); ++addr) {
  83. output << " " << *addr;
  84. }
  85. return (output.str());
  86. }
  87. uint16_t Option6AddrLst::len() const {
  88. return (OPTION6_HDR_LEN + addrs_.size() * V6ADDRESS_LEN);
  89. }
  90. } // end of namespace isc::dhcp
  91. } // end of namespace isc