Commit 209f3964 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[master] Merge branch 'trac3036'

Conflicts:
	src/lib/dhcp/option_definition.cc
	src/lib/dhcp/option_definition.h
parents 57f5c253 aad0b789
......@@ -56,6 +56,7 @@
* - @subpage dhcpv6Session
* - @subpage dhcpv6ConfigParser
* - @subpage dhcpv6ConfigInherit
* - @subpage dhcpv6DDNSIntegration
* - @subpage dhcpv6Other
* - @subpage libdhcp
* - @subpage libdhcpIntro
......
......@@ -5268,6 +5268,9 @@ should include options from the isc option space:
<listitem>
<simpara><ulink url="http://tools.ietf.org/html/rfc3646">RFC 3646</ulink>: Supported option is DNS_SERVERS.</simpara>
</listitem>
<listitem>
<simpara><ulink url="http://tools.ietf.org/html/rfc4704">RFC 4704</ulink>: Supported option is CLIENT_FQDN.</simpara>
</listitem>
</itemizedlist>
</section>
......
......@@ -61,6 +61,7 @@ b10_dhcp6_LDADD = $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp_ddns/libb10-dhcp_ddns.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcpsrv/libb10-dhcpsrv.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
......
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -90,6 +90,81 @@
simple as possible. In fact, currently the code has to call Subnet6->getT1() and
do not implement any fancy inheritance logic.
@section dhcpv6DDNSIntegration DHCPv6 Server Support for the Dynamic DNS Updates
The DHCPv6 server supports processing of the DHCPv6 Client FQDN Option described in
the RFC4704. This Option is sent by the DHCPv6 client to instruct the server to
update the DNS mappings for the acquired lease. A client may send its fully
qualified domain name, a partial name or it may choose that server will generate
the name. In the last case, the client sends an empty domain-name field in the
DHCPv6 Client FQDN Option.
As described in RFC4704, client may choose that the server delegates the forward
DNS update to the client and that the server performs the reverse update only. Current
version of the DHCPv6 server does not support delegation of the forward update
to the client. The implementation of this feature is planned for the future releases.
The b10-dhcp-ddns process is responsible for the actual communication with the DNS
server, i.e. to send DNS Update messages. The b10-dhcp6 module is responsible
for generating so called @ref isc::dhcp_ddns::NameChangeRequest and sending it to the
b10-dhcp-ddns module. The @ref isc::dhcp_ddns::NameChangeRequest object represents changes to the
DNS bindings, related to acquisition, renewal or release of the lease. The bind10-dhcp6
module implements the simple FIFO queue of the NameChangeRequest objects. The module
logic, which processes the incoming DHCPv6 Client FQDN Options puts these requests
into the FIFO queue.
@todo Currently the FIFO queue is not processed after the NameChangeRequests are
generated and added to it. In the future implementation steps it is planned to create
a code which will check if there are any outstanding requests in the queue and
send them to the bind10-dhcp-ddns module when server is idle waiting for DHCP messages.
In the simplest case, when client gets one address from the server, a DHCPv6 server
may generate 0, 1 or 2 NameChangeRequests during single message processing.
Server generates no NameChangeRequests if it is not configured to update DNS
or it rejects the DNS update for any other reason.
Server may generate 1 NameChangeRequests in a situation when a client acquires a
new lease or it releases an existing lease. In the former case, the NameChangeRequest
type is CHG_ADD, which indicates that the bind10-dhcp-ddns module should add a new DNS
binding for the client, and it is assumed that there is no DNS binding for this
client already. In the latter case, the NameChangeRequest type is CHG_REMOVE to
indicate to the bind10-dhcp-ddns module that the existing DNS binding should be removed
from the DNS. The binding consists of the forward and reverse mapping.
A server may only remove the mapping which it had added. Therefore, the lease database
holds an information which updates (no update, reverse only update, forward only update,
both reverse and forward update) have been performed when the lease was acquired.
Server checks this information to make a decision which mapping it is supposed to
remove when a lease is released.
Server may generate 2 NameChangeRequests in case the client is renewing a lease and
it already has a DNS binding for that lease. Note, that renewal may be triggered
as a result of sending a RENEW message as well as the REQUEST message. In both cases
DHCPv6 server will check if there is an existing lease for the client which has sent
a message, and if there is it will check in the lease database if the DNS Updates had
been performed for this client. If the notion of client's FQDN changes comparing to
the information stored in the lease database, the DHCPv6 has to remove an existing
binding from the DNS and then add a new binding according to the new FQDN information
received from the client. If the FQDN sent in the message which triggered a renewal
doesn't change (comparing to the information in the lease database) the NameChangeRequest
is not generated.
In the more complex scenarios, when server sends multiple IA_NA options, each holding
multiple IAADDR options, server will generate more NameChangeRequests for a single
message being processed. That is 0, 1, 2 for the individual IA_NA. Generation of
the distinct NameChangeRequests for each IADDR is not supported yet.
The DHCPv6 Client FQDN Option comprises "NOS" flags which communicate to the
server what updates (if any), client expects the server to perform. Server
may be configured to obey client's preference or do FQDN processing in a
different way. If the server overrides client's preference it will communicate it
by sending the DHCPv6 Client FQDN Option in its responses to a client, with
appropriate flags set.
@todo Note, that current implementation doesn't allow configuration of the server's behaviour
with respect to DNS Updates. This is planned for the future. The default behaviour is
constituted by the set of constants defined in the (upper part of) dhcp6_srv.cc file.
Once the configuration is implemented, these constants will be removed.
@todo Add section about setting up options and their definitions with bindctl.
@section dhcpv6Other Other DHCPv6 topics
......
......@@ -70,11 +70,48 @@ This informational message is printed every time the IPv6 DHCP server
is started. It indicates what database backend type is being to store
lease and other information.
% DHCP6_DDNS_CREATE_ADD_NAME_CHANGE_REQUEST created name change request: %1
This debug message is logged when the new Name Change Request has been created
to perform the DNS Update, which adds new RRs.
% DHCP6_DDNS_CREATE_REMOVE_NAME_CHANGE_REQUEST created name change request: %1
This debug message is logged when the new Name Change Request has been created
to perform the DNS Update, which removes RRs from the DNS.
% DHCP6_DDNS_LEASE_ASSIGN_FQDN_CHANGE FQDN for the allocated lease: %1 has changed. New values: hostname = %2, reverse mapping = %3, forward mapping = %4
This debug message is logged when FQDN mapping for a particular lease has
been changed by the recent Request message. This mapping will be changed in DNS.
% DHCP6_DDNS_LEASE_RENEW_FQDN_CHANGE FQDN for the renewed lease: %1 has changed.
New values: hostname = %2, reverse mapping = %3, forward mapping = %4
This debug message is logged when FQDN mapping for a particular lease has been
changed by the recent Renew message. This mapping will be changed in DNS.
% DHCP6_DEACTIVATE_INTERFACE deactivate interface %1
This message is printed when DHCPv6 server disables an interface from being
used to receive DHCPv6 traffic. Sockets on this interface will not be opened
by the Interface Manager until interface is enabled.
% DHCP6_DDNS_SEND_FQDN sending DHCPv6 Client FQDN Option to the client: %1
This debug message is logged when server includes an DHCPv6 Client FQDN Option
in its response to the client.
% DHCP6_DDNS_RECEIVE_FQDN received DHCPv6 Client FQDN Option: %1
This debug message is logged when server has found the DHCPv6 Client FQDN Option
sent by a client and started processing it.
% DHCP6_DDNS_REMOVE_EMPTY_HOSTNAME FQDN for the lease being deleted is empty: %1
This error message is issued when a lease being deleted contains an indication
that the DNS Update has been performed for it, but the FQDN is missing for this
lease. This is an indication that someone may have messed up in the lease
database.
% DHCP6_DDNS_REMOVE_INVALID_HOSTNAME FQDN for the lease being deleted has invalid format: %1
This error message is issued when a lease being deleted contains an indication
that the DNS Update has been performed for it, but the FQDN held in the lease
database has invalid format and can't be transformed to the canonical on-wire
format.
% DHCP6_HOOK_BUFFER_RCVD_SKIP received DHCPv6 buffer was dropped because a callout set the skip flag.
This debug message is printed when a callout installed on buffer6_receive
hook point set the skip flag. For this particular hook point, the
......
This diff is collapsed.
......@@ -15,9 +15,11 @@
#ifndef DHCPV6_SRV_H
#define DHCPV6_SRV_H
#include <dhcp_ddns/ncr_msg.h>
#include <dhcp/dhcp6.h>
#include <dhcp/duid.h>
#include <dhcp/option.h>
#include <dhcp/option6_client_fqdn.h>
#include <dhcp/option6_ia.h>
#include <dhcp/option_definition.h>
#include <dhcp/pkt6.h>
......@@ -28,6 +30,7 @@
#include <boost/noncopyable.hpp>
#include <iostream>
#include <queue>
namespace isc {
namespace dhcp {
......@@ -79,7 +82,7 @@ public:
///
/// Main server processing loop. Receives incoming packets, verifies
/// their correctness, generates appropriate answer (if needed) and
/// transmits respones.
/// transmits responses.
///
/// @return true, if being shut down gracefully, fail if experienced
/// critical error.
......@@ -132,7 +135,7 @@ protected:
///
/// Processes received SOLICIT message and verifies that its sender
/// should be served. In particular IA, TA and PD options are populated
/// with to-be assinged addresses, temporary addresses and delegated
/// with to-be assigned addresses, temporary addresses and delegated
/// prefixes, respectively. In the usual 4 message exchange, server is
/// expected to respond with ADVERTISE message. However, if client
/// requests rapid-commit and server supports it, REPLY will be sent
......@@ -148,7 +151,7 @@ protected:
///
/// Processes incoming REQUEST message and verifies that its sender
/// should be served. In particular IA, TA and PD options are populated
/// with assinged addresses, temporary addresses and delegated
/// with assigned addresses, temporary addresses and delegated
/// prefixes, respectively. Uses LeaseMgr to allocate or update existing
/// leases.
///
......@@ -210,14 +213,16 @@ protected:
///
/// @param subnet subnet the client is connected to
/// @param duid client's duid
/// @param question client's message (typically SOLICIT or REQUEST)
/// @param query client's message (typically SOLICIT or REQUEST)
/// @param ia pointer to client's IA_NA option (client's request)
/// @param fqdn A DHCPv6 Client FQDN %Option generated in a response to the
/// FQDN option sent by a client.
/// @return IA_NA option (server's response)
OptionPtr assignIA_NA(const isc::dhcp::Subnet6Ptr& subnet,
const isc::dhcp::DuidPtr& duid,
isc::dhcp::Pkt6Ptr question,
boost::shared_ptr<Option6IA> ia,
const Pkt6Ptr& query);
const isc::dhcp::Pkt6Ptr& query,
Option6IAPtr ia,
const Option6ClientFqdnPtr& fqdn);
/// @brief Renews specific IA_NA option
///
......@@ -229,9 +234,11 @@ protected:
/// @param duid client's duid
/// @param query client's message
/// @param ia IA_NA option that is being renewed
/// @param fqdn DHCPv6 Client FQDN Option included in the server's response
/// @return IA_NA option (server's response)
OptionPtr renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
const Pkt6Ptr& query, boost::shared_ptr<Option6IA> ia);
const Pkt6Ptr& query, boost::shared_ptr<Option6IA> ia,
const Option6ClientFqdnPtr& fqdn);
/// @brief Releases specific IA_NA option
///
......@@ -290,7 +297,94 @@ protected:
///
/// @param question client's message (with requested IA_NA)
/// @param answer server's message (IA_NA options will be added here)
void assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer);
/// @param fqdn an FQDN option generated in a response to the client's
/// FQDN option.
void assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer,
const Option6ClientFqdnPtr& fqdn);
/// @brief Processes Client FQDN Option.
///
/// This function retrieves DHCPv6 Client FQDN %Option (if any) from the
/// packet sent by a client and takes necessary actions upon this option.
/// Received option comprises flags field which controls what DNS updates
/// server should do. Server may override client's preference based on
/// the current configuration. Server indicates that it has overridden
/// the preference by storing DHCPv6 Client Fqdn %Option with the
/// appropriate flags in the response to a client. This option is also
/// used to communicate the client's domain-name which should be sent
/// to the DNS in the update. Again, server may act upon the received
/// domain-name, i.e. if the provided domain-name is partial it should
/// generate the fully qualified domain-name.
///
/// All the logic required to form appropriate answer to the client is
/// held in this function.
///
/// @param question Client's message.
///
/// @return FQDN option produced in the response to the client's message.
Option6ClientFqdnPtr processClientFqdn(const Pkt6Ptr& question);
/// @brief Adds DHCPv6 Client FQDN %Option to the server response.
///
/// This function will add the specified FQDN option into the server's
/// response when FQDN is not NULL and server is either configured to
/// always include the FQDN in the response or client requested it using
/// %Option Request %Option.
/// This function is exception safe.
///
/// @param question A message received from the client.
/// @param [out] answer A server's response where FQDN option will be added.
/// @param fqdn A DHCPv6 Client FQDN %Option to be added to the server's
/// response to a client.
void appendClientFqdn(const Pkt6Ptr& question,
Pkt6Ptr& answer,
const Option6ClientFqdnPtr& fqdn);
/// @brief Creates a number of @c isc::dhcp_ddns::NameChangeRequest objects
/// based on the DHCPv6 Client FQDN %Option.
///
/// The @c isc::dhcp_ddns::NameChangeRequest class encapsulates the request
/// from the DHCPv6 server to the DHCP-DDNS module to perform DNS Update.
/// The FQDN option carries response to the client about DNS updates that
/// server intents to perform for the DNS client. Based on this, the
/// function will create zero or more @c isc::dhcp_ddns::NameChangeRequest
/// objects and store them in the internal queue. Requests created by this
/// function are only adding or updating DNS records. In order to generate
/// requests for DNS records removal, use @c createRemovalNameChangeRequest.
///
/// @todo Add support for multiple IAADDR options in the IA_NA.
///
/// @param answer A message beging sent to the Client.
/// @param fqdn_answer A DHCPv6 Client FQDN %Option which is included in the
/// response message sent to a client.
void createNameChangeRequests(const Pkt6Ptr& answer,
const Option6ClientFqdnPtr& fqdn_answer);
/// @brief Creates a @c isc::dhcp_ddns::NameChangeRequest which requests
/// removal of DNS entries for a particular lease.
///
/// This function should be called upon removal of the lease from the lease
/// database, i.e, when client sent Release or Decline message. It will
/// create a single @c isc::dhcp_ddns::NameChangeRequest which removes the
/// existing DNS records for the lease, which server is responsible for.
/// Note that this function will not remove the entries which server hadn't
/// added. This is the case, when client performs forward DNS update on its
/// own.
///
/// @param lease A lease for which the the removal of corresponding DNS
/// records will be performed.
void createRemovalNameChangeRequest(const Lease6Ptr& lease);
/// @brief Sends all outstanding NameChangeRequests to bind10-d2 module.
///
/// The purpose of this function is to pick all outstanding
/// NameChangeRequests from the FIFO queue and send them to bind10-dhcp-ddns
/// module.
///
/// @todo Currently this function simply removes all requests from the
/// queue but doesn't send them anywhere. In the future, the
/// NameChangeSender will be used to deliver requests to the other module.
void sendNameChangeRequests();
/// @brief Attempts to renew received addresses
///
......@@ -300,7 +394,10 @@ protected:
/// as IA_NA/IAADDR to reply packet.
/// @param renew client's message asking for renew
/// @param reply server's response
void renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply);
/// @param fqdn A DHCPv6 Client FQDN %Option generated in the response to the
/// client's FQDN option.
void renewLeases(const Pkt6Ptr& renew, Pkt6Ptr& reply,
const Option6ClientFqdnPtr& fqdn);
/// @brief Attempts to release received addresses
///
......@@ -385,6 +482,12 @@ private:
/// UDP port number on which server listens.
uint16_t port_;
protected:
/// Holds a list of @c isc::dhcp_ddns::NameChangeRequest objects, which
/// are waiting for sending to b10-dhcp-ddns module.
std::queue<isc::dhcp_ddns::NameChangeRequest> name_change_reqs_;
};
}; // namespace isc::dhcp
......
......@@ -79,6 +79,7 @@ dhcp6_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcp_ddns/libb10-dhcp_ddns.la
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/libb10-dhcpsrv.la
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/hooks/libb10-hooks.la
dhcp6_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
......
This diff is collapsed.
......@@ -102,11 +102,15 @@ public:
using Dhcpv6Srv::processRequest;
using Dhcpv6Srv::processRenew;
using Dhcpv6Srv::processRelease;
using Dhcpv6Srv::processClientFqdn;
using Dhcpv6Srv::createNameChangeRequests;
using Dhcpv6Srv::createRemovalNameChangeRequest;
using Dhcpv6Srv::createStatusCode;
using Dhcpv6Srv::selectSubnet;
using Dhcpv6Srv::sanityCheck;
using Dhcpv6Srv::loadServerID;
using Dhcpv6Srv::writeServerID;
using Dhcpv6Srv::name_change_reqs_;
/// @brief packets we pretend to receive
///
......
......@@ -27,6 +27,7 @@ libb10_dhcp___la_SOURCES += option4_client_fqdn.cc option4_client_fqdn.h
libb10_dhcp___la_SOURCES += option6_ia.cc option6_ia.h
libb10_dhcp___la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
libb10_dhcp___la_SOURCES += option6_addrlst.cc option6_addrlst.h
libb10_dhcp___la_SOURCES += option6_client_fqdn.cc option6_client_fqdn.h
libb10_dhcp___la_SOURCES += option_int.h
libb10_dhcp___la_SOURCES += option_int_array.h
libb10_dhcp___la_SOURCES += option.cc option.h
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <dhcp/dhcp6.h>
#include <dhcp/option6_client_fqdn.h>
#include <dns/labelsequence.h>
#include <util/buffer.h>
#include <util/io_utilities.h>
#include <util/strutil.h>
#include <sstream>
namespace isc {
namespace dhcp {
/// @brief Implements the logic for the Option6ClientFqdn class.
///
/// The purpose of the class is to separate the implementation details
/// of the Option6ClientFqdn class from the interface. This implementation
/// uses b10-libdns classes to process FQDNs. At some point it may be
/// desired to split b10-libdhcp++ from b10-libdns. In such case the
/// implementation of this class may be changed. The declaration of the
/// Option6ClientFqdn class holds the pointer to implementation, so
/// the transition to a different implementation would not affect the
/// header file.
class Option6ClientFqdnImpl {
public:
/// Holds flags carried by the option.
uint8_t flags_;
/// Holds the pointer to a domain name carried in the option.
boost::shared_ptr<isc::dns::Name> domain_name_;
/// Indicates whether domain name is partial or fully qualified.
Option6ClientFqdn::DomainNameType domain_name_type_;
/// @brief Constructor, from domain name.
///
/// @param flags A value of the flags option field.
/// @param domain_name A domain name carried by the option given in the
/// textual format.
/// @param name_type A value which indicates whether domain-name
/// is partial of fully qualified.
Option6ClientFqdnImpl(const uint8_t flags,
const std::string& domain_name,
const Option6ClientFqdn::DomainNameType name_type);
/// @brief Constructor, from wire data.
///
/// @param first An iterator pointing to the begining of the option data
/// in the wire format.
/// @param last An iterator poiting to the end of the option data in the
/// wire format.
Option6ClientFqdnImpl(OptionBufferConstIter first,
OptionBufferConstIter last);
/// @brief Copy constructor.
///
/// @param source An object being copied.
Option6ClientFqdnImpl(const Option6ClientFqdnImpl& source);
/// @brief Assignment operator.
///
/// @param source An object which is being assigned.
Option6ClientFqdnImpl& operator=(const Option6ClientFqdnImpl& source);
/// @brief Set a new domain name for the option.
///
/// @param domain_name A new domain name to be assigned.
/// @param name_type A value which indicates whether the domain-name is
/// partial or fully qualified.
void setDomainName(const std::string& domain_name,
const Option6ClientFqdn::DomainNameType name_type);
/// @brief Check if flags are valid.
///
/// In particular, this function checks if the N and S bits are not
/// set to 1 in the same time.
///
/// @param flags A value carried by the flags field of the option.
/// @param check_mbz A boolean value which indicates if this function should
/// check if the MBZ bits are set (if true). This parameter should be set
/// to false when validating flags in the received message. This is because
/// server should ignore MBZ bits in received messages.
/// @throw InvalidOption6FqdnFlags if flags are invalid.
static void checkFlags(const uint8_t flags, const bool check_mbz);
/// @brief Parse the Option provided in the wire format.
///
/// @param first An iterator pointing to the begining of the option data
/// in the wire format.
/// @param last An iterator poiting to the end of the option data in the
/// wire format.
void parseWireData(OptionBufferConstIter first,
OptionBufferConstIter last);
};
Option6ClientFqdnImpl::
Option6ClientFqdnImpl(const uint8_t flags,
const std::string& domain_name,
// cppcheck 1.57 complains that const enum value is not
// passed by reference. Note that it accepts the non-const
// enum to be passed by value. In both cases it is
// unnecessary to pass the enum by reference.
// cppcheck-suppress passedByValue
const Option6ClientFqdn::DomainNameType name_type)
: flags_(flags),
domain_name_(),
domain_name_type_(name_type) {
// Check if flags are correct. Also check if MBZ bits are set.
checkFlags(flags_, true);
// Set domain name. It may throw an exception if domain name has wrong
// format.
setDomainName(domain_name, name_type);
}
Option6ClientFqdnImpl::Option6ClientFqdnImpl(OptionBufferConstIter first,
OptionBufferConstIter last) {
parseWireData(first, last);
// Verify that flags value was correct. Do not check if MBZ bits are
// set because we should ignore those bits in received message.
checkFlags(flags_, false);
}
Option6ClientFqdnImpl::
Option6ClientFqdnImpl(const Option6ClientFqdnImpl& source)
: flags_(source.flags_),
domain_name_(),
domain_name_type_(source.domain_name_type_) {
if (source.domain_name_) {
domain_name_.reset(new isc::dns::Name(*source.domain_name_));
}
}
Option6ClientFqdnImpl&
// This assignment operator handles assignment to self, it copies all
// required values.
// cppcheck-suppress operatorEqToSelf
Option6ClientFqdnImpl::operator=(const Option6ClientFqdnImpl& source) {
if (source.domain_name_) {
domain_name_.reset(new isc::dns::Name(*source.domain_name_));
} else {
domain_name_.reset();
}
// This assignment should be exception safe.
flags_ = source.flags_;
domain_name_type_ = source.domain_name_type_;
return (*this);
}
void
Option6ClientFqdnImpl::
setDomainName(const std::string& domain_name,
// cppcheck 1.57 complains that const enum value is not
// passed by reference. Note that it accepts the non-const
// enum to be passed by value. In both cases it is
// unnecessary to pass the enum by reference.
// cppcheck-suppress passedByValue
const Option6ClientFqdn::DomainNameType name_type) {
// domain-name must be trimmed. Otherwise, string comprising spaces only
// would be treated as a fully qualified name.
std::string name = isc::util::str::trim(domain_name);
if (name.empty()) {
if (name_type == Option6ClientFqdn::FULL) {
isc_throw(InvalidOption6FqdnDomainName,
"fully qualified domain-name must not be empty"
<< " when setting new domain-name for DHCPv6 Client"
<< " FQDN Option");
}
// The special case when domain-name is empty is marked by setting the
// pointer to the domain-name object to NULL.
domain_name_.reset();
} else {
try {
domain_name_.reset(new isc::dns::Name(name, true));
domain_name_type_ = name_type;
} catch (const Exception& ex) {
isc_throw(InvalidOption6FqdnDomainName, "invalid domain-name value '"
<< domain_name << "' when setting new domain-name for"
<< " DHCPv6 Client FQDN Option");
}
}
}
void
Option6ClientFqdnImpl::checkFlags(const uint8_t flags, const bool check_mbz) {
// The Must Be Zero (MBZ) bits must not be set.
if (check_mbz && ((flags & ~Option6ClientFqdn::FLAG_MASK) != 0)) {
isc_throw(InvalidOption6FqdnFlags,
"invalid DHCPv6 Client FQDN Option flags: 0x"
<< std::hex << static_cast<int>(flags) << std::dec);
}
// According to RFC 4704, section 4.1. if the N bit is 1, the S bit
// MUST be 0. Checking it here.
if ((flags & (Option6ClientFqdn::FLAG_N | Option6ClientFqdn::FLAG_S))
== (Option6ClientFqdn::FLAG_N | Option6ClientFqdn::FLAG_S)) {
isc_throw(InvalidOption6FqdnFlags,
"both N and S flag of the DHCPv6 Client FQDN Option are set."
<< " According to RFC 4704, if the N bit is 1 the S bit"
<< " MUST be 0");
}
}