summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcp/option_string.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dhcp/option_string.cc')
-rw-r--r--src/lib/dhcp/option_string.cc115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/lib/dhcp/option_string.cc b/src/lib/dhcp/option_string.cc
new file mode 100644
index 0000000..5f1d0d4
--- /dev/null
+++ b/src/lib/dhcp/option_string.cc
@@ -0,0 +1,115 @@
+// Copyright (C) 2013-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 <dhcp/option_string.h>
+#include <util/strutil.h>
+#include <sstream>
+
+namespace isc {
+namespace dhcp {
+
+OptionString::OptionString(const Option::Universe u, const uint16_t type,
+ const std::string& value)
+ : Option(u, type) {
+ // Try to assign the provided string value. This will throw exception
+ // if the provided value is empty.
+ setValue(value);
+}
+
+OptionString::OptionString(const Option::Universe u, const uint16_t type,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end)
+ : Option(u, type) {
+ // Decode the data. This will throw exception if the buffer is
+ // truncated.
+ unpack(begin, end);
+}
+
+OptionPtr
+OptionString::clone() const {
+ return (cloneInternal<OptionString>());
+}
+
+std::string
+OptionString::getValue() const {
+ const OptionBuffer& data = getData();
+ return (std::string(data.begin(), data.end()));
+}
+
+void
+OptionString::setValue(const std::string& value) {
+ // Sanity check that the string value is at least one byte long.
+ // This is a requirement for all currently defined options which
+ // carry a string value.
+ if (value.empty()) {
+ isc_throw(isc::OutOfRange, "string value carried by the option '"
+ << getType() << "' must not be empty");
+ }
+
+ // Trim off any trailing nuls.
+ auto begin = value.begin();
+ auto end = util::str::seekTrimmed(begin, value.end(), 0x0);
+
+ if (std::distance(begin, end) == 0) {
+ isc_throw(isc::OutOfRange, "string value carried by the option '"
+ << getType() << "' contained only nuls");
+ }
+
+ // Now set the value.
+ setData(begin, end);
+}
+
+
+uint16_t
+OptionString::len() const {
+ return (getHeaderLen() + getData().size());
+}
+
+void
+OptionString::pack(isc::util::OutputBuffer& buf, bool check) const {
+ // Pack option header.
+ packHeader(buf, check);
+ // Pack data.
+ const OptionBuffer& data = getData();
+ buf.writeData(&data[0], data.size());
+
+ // That's it. We don't pack any sub-options here, because this option
+ // must not contain sub-options.
+}
+
+void
+OptionString::unpack(OptionBufferConstIter begin,
+ OptionBufferConstIter end) {
+ // Trim off trailing nul(s)
+ end = util::str::seekTrimmed(begin, end, 0x0);
+ if (std::distance(begin, end) == 0) {
+ isc_throw(isc::dhcp::SkipThisOptionError, "failed to parse an option '"
+ << getType() << "' holding string value"
+ << "' was empty or contained only nuls");
+ }
+
+ // Now set the data.
+ setData(begin, end);
+}
+
+std::string
+OptionString::toText(int indent) const {
+ std::ostringstream output;
+ output << headerToText(indent) << ": "
+ << "\"" << getValue() << "\" (string)";
+
+ return (output.str());
+}
+
+std::string
+OptionString::toString() const {
+ return (getValue());
+}
+
+} // end of isc::dhcp namespace
+} // end of isc namespace