option6_addrlst.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright (C) 2011 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 <stdint.h>
  15. #include <arpa/inet.h>
  16. #include <sstream>
  17. #include "exceptions/exceptions.h"
  18. #include "asiolink/io_address.h"
  19. #include "dhcp/libdhcp.h"
  20. #include "dhcp/option6_addrlst.h"
  21. #include "dhcp/dhcp6.h"
  22. using namespace std;
  23. using namespace isc;
  24. using namespace isc::dhcp;
  25. using namespace isc::asiolink;
  26. Option6AddrLst::Option6AddrLst(unsigned short type,
  27. std::vector<isc::asiolink::IOAddress>& addrs)
  28. :Option(V6, type) {
  29. addrs_ = addrs;
  30. }
  31. Option6AddrLst::Option6AddrLst(unsigned short type,
  32. isc::asiolink::IOAddress addr)
  33. :Option(V6, type) {
  34. addrs_.push_back(addr);
  35. }
  36. Option6AddrLst::Option6AddrLst(unsigned short type,
  37. boost::shared_array<char> buf,
  38. unsigned int buf_len,
  39. unsigned int offset,
  40. unsigned int option_len)
  41. :Option(V6, type) {
  42. unpack(buf, buf_len, offset, option_len);
  43. }
  44. void
  45. Option6AddrLst::setAddress(isc::asiolink::IOAddress addr) {
  46. addrs_.clear();
  47. addrs_.push_back(addr);
  48. }
  49. void
  50. Option6AddrLst::setAddresses(std::vector<isc::asiolink::IOAddress>& addrs) {
  51. addrs_ = addrs;
  52. }
  53. unsigned int
  54. Option6AddrLst::pack(boost::shared_array<char> buf,
  55. unsigned int buf_len,
  56. unsigned int offset) {
  57. if (len() > buf_len) {
  58. isc_throw(OutOfRange, "Failed to pack IA option: len=" << len()
  59. << ", buffer=" << buf_len << ": too small buffer.");
  60. }
  61. *(uint16_t*)&buf[offset] = htons(type_);
  62. offset += 2;
  63. *(uint16_t*)&buf[offset] = htons(len()-4); // len() returns complete option
  64. // length. len field contains length without 4-byte option header
  65. offset += 2;
  66. for (std::vector<IOAddress>::const_iterator addr=addrs_.begin();
  67. addr!=addrs_.end();
  68. ++addr) {
  69. memcpy(&buf[offset],
  70. addr->getAddress().to_v6().to_bytes().data(),
  71. 16);
  72. offset += 16;
  73. }
  74. return offset;
  75. }
  76. unsigned int
  77. Option6AddrLst::unpack(boost::shared_array<char> buf,
  78. unsigned int buf_len,
  79. unsigned int offset,
  80. unsigned int option_len) {
  81. if (offset+option_len > buf_len) {
  82. isc_throw(OutOfRange, "Option " << type_
  83. << " truncated.");
  84. }
  85. if (option_len%16) {
  86. isc_throw(OutOfRange, "Option " << type_
  87. << " malformed: len=" << option_len
  88. << " is not divisible by 16.");
  89. }
  90. while (option_len > 0) {
  91. addrs_.push_back(IOAddress::from_bytes(AF_INET6, &buf[offset]));
  92. offset += 16;
  93. option_len -= 16;
  94. }
  95. return offset;
  96. }
  97. std::string Option6AddrLst::toText(int indent /* =0 */) {
  98. stringstream tmp;
  99. for (int i=0; i<indent; i++)
  100. tmp << " ";
  101. tmp << "type=" << type_ << " " << addrs_.size() << "addr(s): ";
  102. for (AddrsContainer::const_iterator addr=addrs_.begin();
  103. addr!=addrs_.end();
  104. ++addr) {
  105. tmp << addr->toText() << " ";
  106. }
  107. return tmp.str();
  108. }
  109. unsigned short Option6AddrLst::len() {
  110. return (4 /* DHCPv6 option header len */ + addrs_.size()*16);
  111. }