2017-07-10 17:56:07 +02:00
|
|
|
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
|
2015-06-02 17:37:24 +02:00
|
|
|
//
|
2015-12-15 21:37:34 +01:00
|
|
|
// 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/.
|
2015-06-02 17:37:24 +02:00
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2017-07-10 17:56:07 +02:00
|
|
|
#include <dhcp/dhcp4.h>
|
2015-06-02 17:37:24 +02:00
|
|
|
#include <dhcp/dhcp6.h>
|
|
|
|
#include <dhcp/option6_status_code.h>
|
2017-07-10 17:56:07 +02:00
|
|
|
#include <dhcp/option_data_types.h>
|
2015-06-02 17:37:24 +02:00
|
|
|
#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);
|
2017-09-22 00:37:54 +02:00
|
|
|
const size_t OPTION4_SLP_SERVICE_SCOPEMIN_LEN = sizeof(uint8_t);
|
2015-06-02 17:37:24 +02:00
|
|
|
|
|
|
|
}; // 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_() {
|
|
|
|
|
2017-09-22 00:37:54 +02:00
|
|
|
// Parse data
|
2015-06-02 17:37:24 +02:00
|
|
|
unpack(begin, end);
|
|
|
|
}
|
|
|
|
|
2016-06-24 13:32:39 +02:00
|
|
|
OptionPtr
|
|
|
|
Option6StatusCode::clone() const {
|
|
|
|
return (cloneInternal<Option6StatusCode>());
|
|
|
|
}
|
|
|
|
|
2015-06-02 17:37:24 +02:00
|
|
|
void
|
2022-05-06 00:16:48 +03:00
|
|
|
Option6StatusCode::pack(isc::util::OutputBuffer& buf, bool) const {
|
2015-06-02 17:37:24 +02:00
|
|
|
// 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
|
2016-06-24 10:31:55 +02:00
|
|
|
Option6StatusCode::len() const {
|
2015-06-02 17:37:24 +02:00
|
|
|
return (getHeaderLen() + sizeof(uint16_t) + status_message_.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string
|
2016-06-24 10:31:55 +02:00
|
|
|
Option6StatusCode::toText(int indent) const {
|
2015-06-02 17:37:24 +02:00
|
|
|
std::ostringstream output;
|
2015-06-09 13:58:43 +02:00
|
|
|
output << headerToText(indent) << ": " << dataToText();
|
2015-06-02 17:37:24 +02:00
|
|
|
|
|
|
|
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)");
|
|
|
|
}
|
|
|
|
|
2017-07-10 17:56:07 +02:00
|
|
|
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_() {
|
|
|
|
|
2017-09-22 00:37:54 +02:00
|
|
|
// Parse data
|
2017-07-10 17:56:07 +02:00
|
|
|
unpack(begin, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
OptionPtr
|
|
|
|
Option4SlpServiceScope::clone() const {
|
|
|
|
return (cloneInternal<Option4SlpServiceScope>());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-05-06 00:16:48 +03:00
|
|
|
Option4SlpServiceScope::pack(isc::util::OutputBuffer& buf, bool check) const {
|
2017-07-10 17:56:07 +02:00
|
|
|
// Pack option header.
|
2022-05-06 00:16:48 +03:00
|
|
|
packHeader(buf, check);
|
2017-07-10 17:56:07 +02:00
|
|
|
// 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));
|
|
|
|
}
|
2017-09-22 00:37:54 +02:00
|
|
|
begin += sizeof(uint8_t);
|
2017-07-10 17:56:07 +02:00
|
|
|
|
|
|
|
scope_list_.assign(begin, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t
|
|
|
|
Option4SlpServiceScope::len() const {
|
2017-10-06 13:07:09 +02:00
|
|
|
return (getHeaderLen() + sizeof(uint8_t) + scope_list_.size());
|
2017-07-10 17:56:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2015-06-02 17:37:24 +02:00
|
|
|
} // end of namespace isc::dhcp
|
|
|
|
} // end of namespace isc
|