summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcp/option6_addrlst.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dhcp/option6_addrlst.cc')
-rw-r--r--src/lib/dhcp/option6_addrlst.cc112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/lib/dhcp/option6_addrlst.cc b/src/lib/dhcp/option6_addrlst.cc
new file mode 100644
index 0000000..a219d7c
--- /dev/null
+++ b/src/lib/dhcp/option6_addrlst.cc
@@ -0,0 +1,112 @@
+// Copyright (C) 2011-2022 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <asiolink/io_address.h>
+#include <dhcp/dhcp6.h>
+#include <dhcp/libdhcp++.h>
+#include <dhcp/option6_addrlst.h>
+#include <exceptions/exceptions.h>
+#include <util/io_utilities.h>
+
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <stdint.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+using namespace isc::util;
+
+namespace isc {
+namespace dhcp {
+
+Option6AddrLst::Option6AddrLst(uint16_t type, const AddressContainer& addrs)
+ : Option(V6, type), addrs_(addrs) {
+}
+
+Option6AddrLst::Option6AddrLst(uint16_t type, const isc::asiolink::IOAddress& addr)
+ : Option(V6, type), addrs_(1,addr) {
+}
+
+Option6AddrLst::Option6AddrLst(uint16_t type, OptionBufferConstIter begin,
+ OptionBufferConstIter end)
+ : Option(V6, type) {
+ unpack(begin, end);
+}
+
+OptionPtr
+Option6AddrLst::clone() const {
+ return (cloneInternal<Option6AddrLst>());
+}
+
+void
+Option6AddrLst::setAddress(const isc::asiolink::IOAddress& addr) {
+ if (!addr.isV6()) {
+ isc_throw(BadValue, "Can't store non-IPv6 address in Option6AddrLst option");
+ }
+
+ addrs_.clear();
+ addrs_.push_back(addr);
+}
+
+void
+Option6AddrLst::setAddresses(const AddressContainer& addrs) {
+ addrs_ = addrs;
+}
+
+void Option6AddrLst::pack(isc::util::OutputBuffer& buf, bool) const {
+ buf.writeUint16(type_);
+
+ // len() returns complete option length.
+ // len field contains length without 4-byte option header
+ buf.writeUint16(len() - getHeaderLen());
+
+ for (AddressContainer::const_iterator addr=addrs_.begin();
+ addr!=addrs_.end(); ++addr) {
+ if (!addr->isV6()) {
+ isc_throw(isc::BadValue, addr->toText()
+ << " is not an IPv6 address");
+ }
+ // If an address is IPv6 address it should have assumed
+ // length of V6ADDRESS_LEN.
+ buf.writeData(&addr->toBytes()[0], V6ADDRESS_LEN);
+ }
+}
+
+void Option6AddrLst::unpack(OptionBufferConstIter begin,
+ OptionBufferConstIter end) {
+ if ((distance(begin, end) % V6ADDRESS_LEN) != 0) {
+ isc_throw(OutOfRange, "Option " << type_
+ << " malformed: len=" << distance(begin, end)
+ << " is not divisible by 16.");
+ }
+ while (begin != end) {
+ addrs_.push_back(IOAddress::fromBytes(AF_INET6, &(*begin)));
+ begin += V6ADDRESS_LEN;
+ }
+}
+
+std::string Option6AddrLst::toText(int indent) const {
+ stringstream output;
+ output << headerToText(indent) << ":";
+
+ for (AddressContainer::const_iterator addr = addrs_.begin();
+ addr != addrs_.end(); ++addr) {
+ output << " " << *addr;
+ }
+ return (output.str());
+}
+
+uint16_t Option6AddrLst::len() const {
+ return (OPTION6_HDR_LEN + addrs_.size() * V6ADDRESS_LEN);
+}
+
+} // end of namespace isc::dhcp
+} // end of namespace isc