diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
commit | f5f56e1a1c4d9e9496fcb9d81131066a964ccd23 (patch) | |
tree | 49e44c6f87febed37efb953ab5485aa49f6481a7 /src/lib/dhcp/option6_status_code.cc | |
parent | Initial commit. (diff) | |
download | isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.tar.xz isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.zip |
Adding upstream version 2.4.1.upstream/2.4.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/dhcp/option6_status_code.cc')
-rw-r--r-- | src/lib/dhcp/option6_status_code.cc | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/lib/dhcp/option6_status_code.cc b/src/lib/dhcp/option6_status_code.cc new file mode 100644 index 0000000..8e70919 --- /dev/null +++ b/src/lib/dhcp/option6_status_code.cc @@ -0,0 +1,218 @@ +// Copyright (C) 2015-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/dhcp4.h> +#include <dhcp/dhcp6.h> +#include <dhcp/option6_status_code.h> +#include <dhcp/option_data_types.h> +#include <util/io_utilities.h> +#include <iterator> +#include <sstream> + +using namespace isc; +using namespace isc::dhcp; + +namespace { + +/// @brief Minimum length of the option (when status message is empty). +const size_t OPTION6_STATUS_CODE_MIN_LEN = sizeof(uint16_t); +const size_t OPTION4_SLP_SERVICE_SCOPEMIN_LEN = sizeof(uint8_t); + +}; // end of anonymous namespace + +namespace isc { +namespace dhcp { + +Option6StatusCode::Option6StatusCode(const uint16_t status_code, + const std::string& status_message) + : Option(Option::V6, D6O_STATUS_CODE), + status_code_(status_code), status_message_(status_message) { +} + +Option6StatusCode::Option6StatusCode(OptionBufferConstIter begin, + OptionBufferConstIter end) + : Option(Option::V6, D6O_STATUS_CODE), + status_code_(STATUS_Success), status_message_() { + + // Parse data + unpack(begin, end); +} + +OptionPtr +Option6StatusCode::clone() const { + return (cloneInternal<Option6StatusCode>()); +} + +void +Option6StatusCode::pack(isc::util::OutputBuffer& buf, bool) const { + // Pack option header. + packHeader(buf); + // Write numeric status code. + buf.writeUint16(getStatusCode()); + // If there is any status message, write it. + if (!status_message_.empty()) { + buf.writeData(&status_message_[0], status_message_.size()); + } + + // Status code has no options, so leave here. +} + +void +Option6StatusCode::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) { + // Make sure that the option is not truncated. + if (std::distance(begin, end) < OPTION6_STATUS_CODE_MIN_LEN) { + isc_throw(OutOfRange, "Status Code option (" + << D6O_STATUS_CODE << ") truncated"); + } + + status_code_ = util::readUint16(&(*begin), std::distance(begin, end)); + begin += sizeof(uint16_t); + + status_message_.assign(begin, end); +} + +uint16_t +Option6StatusCode::len() const { + return (getHeaderLen() + sizeof(uint16_t) + status_message_.size()); +} + +std::string +Option6StatusCode::toText(int indent) const { + std::ostringstream output; + output << headerToText(indent) << ": " << dataToText(); + + return (output.str()); +} + +std::string +Option6StatusCode::dataToText() const { + std::ostringstream output; + // Add status code name and numeric status code. + output << getStatusCodeName() << "(" << getStatusCode() << ") "; + + // Include status message in quotes if status code is + // non-empty. + if (!status_message_.empty()) { + output << "\"" << status_message_ << "\""; + + } else { + output << "(no status message)"; + } + + return (output.str()); +} + +std::string +Option6StatusCode::getStatusCodeName() const { + switch (getStatusCode()) { + case STATUS_Success: + return ("Success"); + case STATUS_UnspecFail: + return ("UnspecFail"); + case STATUS_NoAddrsAvail: + return ("NoAddrsAvail"); + case STATUS_NoBinding: + return ("NoBinding"); + case STATUS_NotOnLink: + return ("NotOnLink"); + case STATUS_UseMulticast: + return ("UseMulticast"); + case STATUS_NoPrefixAvail: + return ("NoPrefixAvail"); + case STATUS_UnknownQueryType: + return ("UnknownQueryType"); + case STATUS_MalformedQuery: + return ("MalformedQuery"); + case STATUS_NotConfigured: + return ("NotConfigured"); + case STATUS_NotAllowed: + return ("NotAllowed"); + default: + ; + } + return ("(unknown status code)"); +} + +Option4SlpServiceScope::Option4SlpServiceScope(const bool mandatory_flag, + const std::string& scope_list) + : Option(Option::V4, DHO_SERVICE_SCOPE), + mandatory_flag_(mandatory_flag), scope_list_(scope_list) { +} + +Option4SlpServiceScope::Option4SlpServiceScope(OptionBufferConstIter begin, + OptionBufferConstIter end) + : Option(Option::V4, DHO_SERVICE_SCOPE), + mandatory_flag_(false), scope_list_() { + + // Parse data + unpack(begin, end); +} + +OptionPtr +Option4SlpServiceScope::clone() const { + return (cloneInternal<Option4SlpServiceScope>()); +} + +void +Option4SlpServiceScope::pack(isc::util::OutputBuffer& buf, bool check) const { + // Pack option header. + packHeader(buf, check); + // Write mandatory flag. + buf.writeUint8(static_cast<uint8_t>(getMandatoryFlag() ? 1 : 0)); + // If there is any scope list, write it. + if (!scope_list_.empty()) { + buf.writeData(&scope_list_[0], scope_list_.size()); + } + + // SLP service scope has no options, so leave here. +} + +void +Option4SlpServiceScope::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) { + // Make sure that the option is not truncated. + if (std::distance(begin, end) < OPTION4_SLP_SERVICE_SCOPEMIN_LEN) { + isc_throw(OutOfRange, "SLP Service Scope option (" + << DHO_SERVICE_SCOPE << ") truncated"); + } + + if (*begin == 1) { + mandatory_flag_ = true; + } else if (*begin == 0) { + mandatory_flag_ = false; + } else { + isc_throw(BadDataTypeCast, "unable to read the buffer as boolean" + << " value. Invalid value " << static_cast<int>(*begin)); + } + begin += sizeof(uint8_t); + + scope_list_.assign(begin, end); +} + +uint16_t +Option4SlpServiceScope::len() const { + return (getHeaderLen() + sizeof(uint8_t) + scope_list_.size()); +} + +std::string +Option4SlpServiceScope::toText(int indent) const { + std::ostringstream output; + output << headerToText(indent) << ": " << dataToText(); + + return (output.str()); +} + +std::string +Option4SlpServiceScope::dataToText() const { + std::ostringstream output; + output << "mandatory:" << getMandatoryFlag(); + output << ", scope-list:\"" << scope_list_ << "\""; + return (output.str()); +} + +} // end of namespace isc::dhcp +} // end of namespace isc |