<row><entry>streettalk-server</entry><entry>75</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
<row><entry>streettalk-directory-assistance-server</entry><entry>76</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
<row><entry>user-class</entry><entry>77</entry><entry>binary</entry><entry>false</entry><entry>false</entry></row>
+<row><entry>slp-service-scope</entry><entry>79</entry><entry>record (boolean, string)</entry><entry>false</entry><entry>false</entry></row>
<!-- The Client FQDN option value is not explicitly configured.
It is a part of the DDNS/D2 configuration
<row><entry>fqdn</entry><entry>81</entry><entry>record</entry><entry>false</entry><entry>true</entry></row>
DHO_STDASERVER = 76,
DHO_USER_CLASS = 77,
// DHO_DIRECTORY_AGENT = 78,
-// DHO_SERVICE_SCOPE = 79,
+ DHO_SERVICE_SCOPE = 79,
// DHO_RAPID_COMMIT = 80,
DHO_FQDN = 81,
DHO_DHCP_AGENT_OPTIONS = 82,
-// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2017 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
#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>
/// @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(bool);
}; // end of anonymous namespace
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) const {
+ // Pack option header.
+ packHeader(buf);
+ // 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(bool);
+
+ scope_list_.assign(begin, end);
+}
+
+uint16_t
+Option4SlpServiceScope::len() const {
+ return (getHeaderLen() + sizeof(bool) + 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
-// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2017 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
};
+/// The SLP Service Scope option has a similar layout...
+
+class Option4SlpServiceScope;
+
+/// @brief Pointer to the @c isc::dhcp::Option4SlpServiceScope.
+typedef boost::shared_ptr<Option4SlpServiceScope> Option4SlpServiceScopePtr;
+
+/// @brief This class represents SLP Service Scope option (79) from RFC2610.
+class Option4SlpServiceScope: public Option {
+public:
+ /// @brief Constructor, used for options constructed (during transmission).
+ ///
+ /// @param mandatory_flag Mandatory flag.
+ /// @param scope_list Textual scope list, may be empty
+ Option4SlpServiceScope(const bool mandatory_flag, const std::string& scope_list);
+
+ /// @brief Constructor, used for received options.
+ ///
+ /// @throw OutOfRange if specified option is truncated
+ ///
+ /// @param begin Iterator to first byte of option data
+ /// @param end Iterator to end of option data (first byte after option end).
+ Option4SlpServiceScope(OptionBufferConstIter begin, OptionBufferConstIter end);
+
+ /// @brief Copies this option and returns a pointer to the copy.
+ virtual OptionPtr clone() const;
+
+ /// @brief Writes option in wire-format.
+ ///
+ /// Writes option in wire-format to buf, returns pointer to first unused
+ /// byte after stored option.
+ ///
+ /// @param [out] buf Pointer to the output buffer.
+ virtual void pack(isc::util::OutputBuffer& buf) const;
+
+ /// @brief Parses received buffer.
+ ///
+ /// @param begin Iterator to first byte of option data
+ /// @param end Iterator to end of option data (first byte after option end)
+ virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
+
+ /// @brief Returns total length of the option.
+ ///
+ /// The returned length is a sum of the option header and data fields.
+ virtual uint16_t len() const;
+
+ /// @brief Returns textual representation of the option.
+ ///
+ /// @param indent Number of spaces before printing text.
+ virtual std::string toText(int indent = 0) const;
+
+ /// @brief Returns textual representation of the option data.
+ ///
+ /// This method returns only the status code and the status
+ /// message. It excludes the option header.
+ std::string dataToText() const;
+
+ /// @brief Returns mandatory flag
+ bool getMandatoryFlag() const {
+ return (mandatory_flag_);
+ }
+
+ /// @brief Sets new mandatory flag.
+ ///
+ /// @param status_code New numeric status code.
+ void setMandatoryFlag(const bool mandatory_flag) {
+ mandatory_flag_ = mandatory_flag;
+ }
+
+ /// @brief Returns scope list.
+ const std::string& getScopeList() const {
+ return (scope_list_);
+ }
+
+ /// @brief Sets new scope list.
+ ///
+ /// @param scope_list New scope list (empty string is allowed).
+ void setScopeList(std::string& scope_list) {
+ scope_list_ = scope_list;
+ }
+
+private:
+
+ /// @brief Mandatory flag.
+ bool mandatory_flag_;
+
+ /// @brief Scope list.
+ std::string scope_list_;
+
+};
+
} // isc::dhcp namespace
} // isc namespace
(record_fields_[1] == OPT_STRING_TYPE));
}
+bool
+OptionDefinition::haveServiceScopeFormat() const {
+ return (haveType(OPT_RECORD_TYPE) &&
+ (record_fields_.size() == 2) &&
+ (record_fields_[0] == OPT_BOOLEAN_TYPE) &&
+ (record_fields_[1] == OPT_STRING_TYPE));
+}
+
bool
OptionDefinition::haveOpaqueDataTuplesFormat() const {
return (haveType(OPT_TUPLE_TYPE) && getArrayType());
return (OptionPtr(new Option6PDExclude(begin, end)));
}
} else {
- if ((getCode() == DHO_FQDN) && haveFqdn4Format()) {
+ if ((getCode() == DHO_SERVICE_SCOPE) && haveServiceScopeFormat()) {
+ return (OptionPtr(new Option4SlpServiceScope(begin, end)));
+ } else if ((getCode() == DHO_FQDN) && haveFqdn4Format()) {
return (OptionPtr(new Option4ClientFqdn(begin, end)));
} else if (haveCompressedFqdnListFormat()) {
return (factoryFqdnList(Option::V4, begin, end));
/// @return true if option has the format of DHCPv6 Vendor Class option.
bool haveVendorClass6Format() const;
+ /// @brief Check if option has format of the SLP Service Scope
+ /// %Option.
+ ///
+ /// The scope list in the SLP Service Scope option is optional
+ /// (i.e., as the error message in the DHCPv6 Status code option).
+ ///
+ /// @return true if option has the format of SLP Service Scope %Option.
+ bool haveServiceScopeFormat() const;
+
/// @brief Check if the option has format of DHCPv6 Status Code option.
///
/// @return true if option has the format of DHCPv6 Status code option.
#define NO_RECORD_DEF 0, 0
#endif
+// SLP Service Scope option.
+//
+// The scope list is optional.
+RECORD_DECL(SERVICE_SCOPE_RECORDS, OPT_BOOLEAN_TYPE, OPT_STRING_TYPE);
+
// fqdn option record fields.
//
// Note that the flags field indicates the type of domain
{ "streettalk-server", DHO_STREETTALK_SERVER, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
{ "streettalk-directory-assistance-server", DHO_STDASERVER, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
{ "user-class", DHO_USER_CLASS, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
+ { "slp-service-scope", DHO_SERVICE_SCOPE, OPT_RECORD_TYPE, false,
+ RECORD_DEF(SERVICE_SCOPE_RECORDS), "" },
{ "fqdn", DHO_FQDN, OPT_RECORD_TYPE, false, RECORD_DEF(FQDN_RECORDS), "" },
{ "dhcp-agent-options", DHO_DHCP_AGENT_OPTIONS,
OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "dhcp-agent-options-space" },
LibDhcpTest::testStdOptionDefs4(DHO_USER_CLASS, begin, end,
typeid(Option));
+ LibDhcpTest::testStdOptionDefs4(DHO_SERVICE_SCOPE, begin, end,
+ typeid(Option4SlpServiceScope));
+
+ // Check also with empty scope list
+ LibDhcpTest::testStdOptionDefs4(DHO_SERVICE_SCOPE, begin, begin + 1,
+ typeid(Option4SlpServiceScope));
+
LibDhcpTest::testStdOptionDefs4(DHO_FQDN, begin, begin + 3,
typeid(Option4ClientFqdn));