Commit fef265b2 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰

[master] Merge branch 'trac2984' (additional DHCPv6 hooks)

Conflicts:
	ChangeLog
	src/bin/dhcp6/dhcp6_srv.cc
parents 10d9ff6b 540dd044
655. [func] tmark
656. [func] tomek
Additional hooks (buffer6_receive, lease6_renew,
lease6_release, buffer6_send) added to the DHCPv6 server.
(Trac #2984, git 540dd0449121094a56f294c500c2ed811f6016b6)
655. [func] tmark
Added D2UpdateMgr class to b10-dhcp-ddns. This class is the b10-dhcp-ddns
task master, instantiating and supervising transactions that carry out the
DNS updates needed to fulfill the requests (NameChangeRequests) received
from b10-dhcp-ddns clients (e.g. DHCP servers).
(Trac #3059 git d72675617d6b60e3eb6160305738771f015849ba)
(Trac #3059 git d72675617d6b60e3eb6160305738771f015849ba)
654. [bug] stephen
Always clear "skip" flag before calling any callouts on a hook.
......@@ -61,7 +66,7 @@
(Trac #3054, git 0f845ed94f462dee85b67f056656b2a197878b04)
645. [func] tomek
Added initial set of hooks (pk4_receive, subnet4_select,
Added initial set of hooks (pkt4_receive, subnet4_select,
lease4_select, pkt4_send) to the DHCPv6 server.
(Trac #2994, git be65cfba939a6a7abd3c93931ce35c33d3e8247b)
......@@ -82,7 +87,7 @@
(Trac #3056, git 92ebabdbcf6168666b03d7f7fbb31f899be39322)
642. [func] tomek
Added initial set of hooks (pk6_receive, subnet6_select,
Added initial set of hooks (pkt6_receive, subnet6_select,
lease6_select, pkt6_send) to the DHCPv6 server.
(Trac #2995, git d6de376f97313ba40fef989e4a437d184fdf70cc)
......
......@@ -49,20 +49,46 @@ The following list is ordered by appearance of specific hook points during
packet processing. Hook points that are not specific to packet processing
(e.g. lease expiration) will be added to the end of this list.
@subsection dhcpv6HooksBuffer6Receive buffer6_receive
- @b Arguments:
- name: @b query6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
- @b Description: This callout is executed when an incoming DHCPv6
packet is received and the data stored in a buffer. The sole argument -
query6 - contains a pointer to an isc::dhcp::Pkt6 object that contains
the received information stored in the data_ field. Basic information
like protocol, source/destination addresses and ports are set, but
the contents of the buffer have not yet been parsed. That means that
the options_ field (that will eventually contain a list of objects
representing the received options) is empty, so none of the methods
that operate on it (e.g., getOption()) will work. The primary purpose
of this early call is to offer the ability to modify incoming packets
in their raw form. Unless you need to access to the raw data, it is
usually better to install your callout on the pkt6_receive hook point.
- <b>Skip flag action</b>: If any callout sets the skip flag, the
server will assume that the callout parsed the buffer and added then
necessary option objects to the options_ field; the server will not
do any parsing. If the callout sets the skip flag but does not parse
the buffer, the server will most probably drop the packet due to
the absence of mandatory options. If you want to drop the packet,
see the description of the skip flag in the pkt6_receive hook point.
@subsection dhcpv6HooksPkt6Receive pkt6_receive
- @b Arguments:
- name: @b query6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when an incoming DHCPv6
- @b Description: This callout is executed when an incoming DHCPv6
packet is received and its content is parsed. The sole argument -
query6 - contains a pointer to an isc::dhcp::Pkt6 object that contains
all information regarding incoming packet, including its source and
destination addresses, interface over which it was received, a list
destination addresses, the interface over which it was received, a list
of all options present within and relay information. All fields of
the Pkt6 object can be modified at this time, except data_. (data_
contains the incoming packet as raw buffer. By the time this hook is
reached, that information has already parsed and is available though
reached, that information has already been parsed and is available though
other fields in the Pkt6 object. For this reason, it doesn't make
sense to modify it.)
......@@ -77,7 +103,7 @@ packet processing. Hook points that are not specific to packet processing
- name: @b subnet6, type: isc::dhcp::Subnet6Ptr, direction: <b>in/out</b>
- name: @b subnet6collection, type: const isc::dhcp::Subnet6Collection *, direction: <b>in</b>
- @b Description: this callout is executed when a subnet is being
- @b Description: This callout is executed when a subnet is being
selected for the incoming packet. All parameters, addresses and
prefixes will be assigned from that subnet. A callout can select a
different subnet if it wishes so, the list of all subnets currently
......@@ -89,14 +115,14 @@ packet processing. Hook points that are not specific to packet processing
will continue, but will be severely limited (i.e. only global options
will be assigned).
@subsection dhcpv6HooksLeaseSelect lease6_select
@subsection dhcpv6HooksLease6Select lease6_select
- @b Arguments:
- name: @b subnet6, type: isc::dhcp::Subnet6Ptr, direction: <b>in</b>
- name: @b fake_allocation, type: bool, direction: <b>in</b>
- name: @b lease6, type: isc::dhcp::Lease6Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed after the server engine
- @b Description: This callout is executed after the server engine
has selected a lease for client's request but before the lease
has been inserted into the database. Any modifications made to the
isc::dhcp::Lease6 object will be stored in the lease's record in the
......@@ -115,24 +141,98 @@ packet processing. Hook points that are not specific to packet processing
Packet processing will continue and the client may get other addresses
or prefixes if it requested more than one address and/or prefix.
@subsection dhcpv6HooksLease6Renew lease6_renew
- @b Arguments:
- name: @b query6, type: isc::dhcp::PktPtr, direction: <b>in</b>
- name: @b lease6, type: isc::dhcp::Lease6Ptr, direction: <b>in/out</b>
- name: @b ia_na, type: boost::shared_ptr<Option6IA>, direction: <b>in/out</b>
- @b Description: This callout is executed when the server engine is
about to renew an existing lease. The client's request is provided as
the query6 argument and the existing lease with the appropriate fields
already modified is given in the lease6 argument. The final argument,
ia_na, is the IA_NA option that will be sent back to the client.
Callouts installed on the lease6_renew may modify the content of
the lease6 object. Care should be taken however, as that modified
information will be written to the database without any further
checking. \n\n Although the envisaged usage assumes modification of T1,
T2, preferred and valid lifetimes only, other parameters associated
with the lease may be modified as well. The only exception is the addr_
field, which must not be modified as it is used by the database to
select the existing lease to be updated. Care should also be taken to
modify the ia_na argument to match any changes in the lease6 argument.
If a client sends more than one IA_NA option, callouts will be called
separately for each IA_NA instance. The callout will be called only
when the update is valid, i.e. conditions such as an invalid addresses
or invalid iaid renewal attempts will not trigger this hook point.
- <b>Skip flag action</b>: If any callout installed on 'lease6_renew'
sets the skip flag, the server will not renew the lease. Under these
circumstances, the callout should modify the ia_na argument to reflect
this fact; otherwise the client will think the lease was renewed and continue
to operate under this assumption.
@subsection dhcpv6HooksLease6Release lease6_release
- @b Arguments:
- name: @b query6, type: isc::dhcp::PktPtr, direction: <b>in</b>
- name: @b lease6, type: isc::dhcp::Lease6Ptr, direction: <b>in/out</b>
- @b Description: This callout is executed when the server engine is
about to release an existing lease. The client's request is provided
as the query6 argument and the existing lease is given in the lease6
argument. Although the lease6 structure may be modified, it doesn't
make sense to do so as it will be destroyed immediately the callouts
finish execution.
- <b>Skip flag action</b>: If any callout installed on 'lease6_release'
sets the skip flag, the server will not delete the lease, which will
remain in the database until it expires. However, the server will send out
the response back to the client as if it did.
@subsection dhcpv6HooksPkt6Send pkt6_send
- @b Arguments:
- name: @b response6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when server's response
- @b Description: This callout is executed when server's response
is about to be send back to the client. The sole argument - response6 -
contains a pointer to an isc::dhcp::Pkt6 object that contains the
packet, with set source and destination addresses, interface over which
it will be send, list of all options and relay information. All fields
of the Pkt6 object can be modified at this time, except bufferOut_.
(This is scratch space used for constructing the packet after all
pkt6_send callouts are complete, so any changes to that field will
be overwritten.)
of the Pkt6 object can be modified at this time. It should be noted that
unless the callout sets the skip flag (see below), anything placed in the
bufferOut_ field will be overwritten when the callout returns.
(bufferOut_ is scratch space used for constructing the packet.)
- <b>Skip flag action</b>: If any callout sets the skip flag, the server
will assume that the callout did pack the transaction-id, message type and
option objects into the bufferOut_ field and will skip packing part.
Note that if the callout sets skip flag, but did not prepare the
output buffer, the server will send a zero sized message that will be
ignored by the client. If you want to drop the packet, please see
skip flag in the buffer6_send hook point.
@subsection dhcpv6HooksBuffer6Send buffer6_send
- @b Arguments:
- name: @b response6, type: isc::dhcp::Pkt6Ptr, direction: <b>in/out</b>
- <b>Skip flag action</b>: if any callout sets the skip flag, the server
- @b Description: This callout is executed when server's response is
assembled into binary form and is about to be send back to the
client. The sole argument - response6 - contains a pointer to an
isc::dhcp::Pkt6 object that contains the packet, with set source and
destination addresses, interface over which it will be sent, list of
all options and relay information. All options are already encoded
in bufferOut_ field. It doesn't make sense to modify anything but the
contents of bufferOut_ at this time (although if it is a requirement
to modify that data, it will probably be found easier to modify the
option objects in a callout attached to the pkt6_send hook).
- <b>Skip flag action</b>: If any callout sets the skip flag, the server
will drop this response packet. However, the original request packet
from a client was processed, so server's state was most likely changed
from a client has been processed, so server's state has most likely changed
(e.g. lease was allocated). Setting this flag merely stops the change
being communicated to the client.
......
......@@ -75,22 +75,50 @@ 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_HOOK_PACKET_RCVD_SKIP received DHCPv6 packet was dropped, because a callout set skip flag.
% 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
setting of the flag by a callout instructs the server to drop the packet.
% DHCP6_HOOK_BUFFER_SEND_SKIP prepared DHCPv6 response 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
setting of the flag by a callout instructs the server to drop the packet.
Server completed all the processing (e.g. may have assigned, updated
or released leases), but the response will not be send to the client.
% DHCP6_HOOK_LEASE6_RENEW_SKIP DHCPv6 lease was not renewed because a callout set the skip flag.
This debug message is printed when a callout installed on lease6_renew
hook point set the skip flag. For this particular hook point, the setting
of the flag by a callout instructs the server to not renew a lease. If
client requested renewal of multiples leases (by sending multiple IA
options), the server will skip the renewal of the one in question and
will proceed with other renewals as usual.
% DHCP6_HOOK_LEASE6_RELEASE_SKIP DHCPv6 lease was not released because a callout set the skip flag.
This debug message is printed when a callout installed on lease6_release
hook point set the skip flag. For this particular hook point, the
setting of the flag by a callout instructs the server to not release
a lease. If client requested release of multiples leases (by sending
multiple IA options), the server will retains this particular lease and
will proceed with other renewals as usual.
% DHCP6_HOOK_PACKET_RCVD_SKIP received DHCPv6 packet was dropped because a callout set the skip flag.
This debug message is printed when a callout installed on the pkt6_receive
hook point sets the skip flag. For this particular hook point, the
hook point set the skip flag. For this particular hook point, the
setting of the flag by a callout instructs the server to drop the packet.
% DHCP6_HOOK_PACKET_SEND_SKIP prepared DHCPv6 response was not sent, because a callout set skip flag.
% DHCP6_HOOK_PACKET_SEND_SKIP prepared DHCPv6 response was not sent because a callout set the skip flag.
This debug message is printed when a callout installed on the pkt6_send
hook point sets the skip flag. For this particular hook point, the setting
hook point set the skip flag. For this particular hook point, the setting
of the flag by a callout instructs the server to drop the packet. This
effectively means that the client will not get any response, even though
the server processed client's request and acted on it (e.g. possibly
allocated a lease).
% DHCP6_HOOK_SUBNET6_SELECT_SKIP no subnet was selected, because a callout set skip flag.
% DHCP6_HOOK_SUBNET6_SELECT_SKIP no subnet was selected because a callout set the skip flag.
This debug message is printed when a callout installed on the
subnet6_select hook point sets the skip flag. For this particular hook
subnet6_select hook point set the skip flag. For this particular hook
point, the setting of the flag instructs the server not to choose a
subnet, an action that severely limits further processing; the server
will be only able to offer global options - no addresses or prefixes
......@@ -165,6 +193,11 @@ This error is output if the IPv6 DHCP server fails to send an assembled
DHCP message to a client. The reason for the error is included in the
message.
% DHCP6_PACK_FAIL failed to assemble response correctly
This error is output if the server failed to assemble the data to be
returned to the client into a valid packet. The reason is most likely
to be to a programming error: please raise a bug report.
% DHCP6_PARSER_COMMIT_EXCEPTION parser failed to commit changes
On receipt of message containing details to a change of the IPv6 DHCP
server configuration, a set of parsers were successfully created, but one
......@@ -339,6 +372,12 @@ to a misconfiguration of the server. The packet processing will continue, but
the response will only contain generic configuration parameters and no
addresses or prefixes.
% DHCP6_UNKNOWN_MSG_RECEIVED received unknown message (type %d) on interface %2
This debug message is printed when server receives a message of unknown type.
That could either mean missing functionality or invalid or broken relay or client.
The list of formally defined message types is available here:
www.iana.org/assignments/dhcpv6-parameters.
% DHCP6_UNKNOWN_RELEASE received RELEASE from unknown client (duid=%1, iaid=%2)
This warning message is printed when client attempts to release a lease,
but no such lease is known by the server. See DHCP6_UNKNOWN_RENEW for
......
This diff is collapsed.
......@@ -227,11 +227,11 @@ protected:
///
/// @param subnet subnet the sender belongs to
/// @param duid client's duid
/// @param question client's message
/// @param query client's message
/// @param ia IA_NA option that is being renewed
/// @return IA_NA option (server's response)
OptionPtr renewIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
Pkt6Ptr question, boost::shared_ptr<Option6IA> ia);
const Pkt6Ptr& query, boost::shared_ptr<Option6IA> ia);
/// @brief Releases specific IA_NA option
///
......@@ -246,11 +246,11 @@ protected:
/// release process fails.
///
/// @param duid client's duid
/// @param question client's message
/// @param query client's message
/// @param general_status a global status (it may be updated in case of errors)
/// @param ia IA_NA option that is being renewed
/// @return IA_NA option (server's response)
OptionPtr releaseIA_NA(const DuidPtr& duid, Pkt6Ptr question,
OptionPtr releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
int& general_status,
boost::shared_ptr<Option6IA> ia);
......@@ -383,11 +383,6 @@ private:
/// @return a callout handle to be used in hooks related to said packet
isc::hooks::CalloutHandlePtr getCalloutHandle(const Pkt6Ptr& pkt);
/// Indexes for registered hook points
int hook_index_pkt6_receive_;
int hook_index_subnet6_select_;
int hook_index_pkt6_send_;
/// UDP port number on which server listens.
uint16_t port_;
};
......
......@@ -49,6 +49,8 @@ TESTS += dhcp6_unittests
dhcp6_unittests_SOURCES = dhcp6_unittests.cc
dhcp6_unittests_SOURCES += dhcp6_srv_unittest.cc
dhcp6_unittests_SOURCES += hooks_unittest.cc
dhcp6_unittests_SOURCES += dhcp6_test_utils.h
dhcp6_unittests_SOURCES += ctrl_dhcp6_srv_unittest.cc
dhcp6_unittests_SOURCES += config_parser_unittest.cc
dhcp6_unittests_SOURCES += ../dhcp6_srv.h ../dhcp6_srv.cc
......
This diff is collapsed.
// 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.
/// @file dhcp6_test_utils.h
///
/// @brief This file contains utility classes used for DHCPv6 server testing
#include <gtest/gtest.h>
#include <dhcp/pkt6.h>
#include <dhcp/option6_ia.h>
#include <dhcp/option6_iaaddr.h>
#include <dhcp/option_int_array.h>
#include <dhcp/option_custom.h>
#include <dhcp/iface_mgr.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/lease_mgr.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcp6/dhcp6_srv.h>
#include <hooks/hooks_manager.h>
#include <config/ccsession.h>
#include <list>
using namespace isc::dhcp;
using namespace isc::config;
using namespace isc::data;
using namespace isc::hooks;
using namespace isc::asiolink;
using namespace isc::util;
using namespace isc::hooks;
namespace isc {
namespace test {
/// @brief "naked" Dhcpv6Srv class that exposes internal members
class NakedDhcpv6Srv: public isc::dhcp::Dhcpv6Srv {
public:
NakedDhcpv6Srv(uint16_t port) : Dhcpv6Srv(port) {
// Open the "memfile" database for leases
std::string memfile = "type=memfile";
LeaseMgrFactory::create(memfile);
}
/// @brief fakes packet reception
/// @param timeout ignored
///
/// The method receives all packets queued in receive
/// queue, one after another. Once the queue is empty,
/// it initiates the shutdown procedure.
///
/// See fake_received_ field for description
virtual isc::dhcp::Pkt6Ptr receivePacket(int /*timeout*/) {
// If there is anything prepared as fake incoming
// traffic, use it
if (!fake_received_.empty()) {
Pkt6Ptr pkt = fake_received_.front();
fake_received_.pop_front();
return (pkt);
}
// If not, just trigger shutdown and
// return immediately
shutdown();
return (Pkt6Ptr());
}
/// @brief fake packet sending
///
/// Pretend to send a packet, but instead just store
/// it in fake_send_ list where test can later inspect
/// server's response.
virtual void sendPacket(const Pkt6Ptr& pkt) {
fake_sent_.push_back(pkt);
}
/// @brief adds a packet to fake receive queue
///
/// See fake_received_ field for description
void fakeReceive(const Pkt6Ptr& pkt) {
fake_received_.push_back(pkt);
}
virtual ~NakedDhcpv6Srv() {
// Close the lease database
LeaseMgrFactory::destroy();
}
using Dhcpv6Srv::processSolicit;
using Dhcpv6Srv::processRequest;
using Dhcpv6Srv::processRenew;
using Dhcpv6Srv::processRelease;
using Dhcpv6Srv::createStatusCode;
using Dhcpv6Srv::selectSubnet;
using Dhcpv6Srv::sanityCheck;
using Dhcpv6Srv::loadServerID;
using Dhcpv6Srv::writeServerID;
/// @brief packets we pretend to receive
///
/// Instead of setting up sockets on interfaces that change between OSes, it
/// is much easier to fake packet reception. This is a list of packets that
/// we pretend to have received. You can schedule new packets to be received
/// using fakeReceive() and NakedDhcpv6Srv::receivePacket() methods.
std::list<Pkt6Ptr> fake_received_;
std::list<Pkt6Ptr> fake_sent_;
};
static const char* DUID_FILE = "server-id-test.txt";
// test fixture for any tests requiring blank/empty configuration
// serves as base class for additional tests
class NakedDhcpv6SrvTest : public ::testing::Test {
public:
NakedDhcpv6SrvTest() : rcode_(-1) {
// it's ok if that fails. There should not be such a file anyway
unlink(DUID_FILE);
const IfaceMgr::IfaceCollection& ifaces = IfaceMgr::instance().getIfaces();
// There must be some interface detected
if (ifaces.empty()) {
// We can't use ASSERT in constructor
ADD_FAILURE() << "No interfaces detected.";
}
valid_iface_ = ifaces.begin()->getName();
}
// Generate IA_NA option with specified parameters
boost::shared_ptr<Option6IA> generateIA(uint32_t iaid, uint32_t t1, uint32_t t2) {
boost::shared_ptr<Option6IA> ia =
boost::shared_ptr<Option6IA>(new Option6IA(D6O_IA_NA, iaid));
ia->setT1(t1);
ia->setT2(t2);
return (ia);
}
/// @brief generates interface-id option, based on text
///
/// @param iface_id textual representation of the interface-id content
///
/// @return pointer to the option object
OptionPtr generateInterfaceId(const std::string& iface_id) {
OptionBuffer tmp(iface_id.begin(), iface_id.end());
return OptionPtr(new Option(Option::V6, D6O_INTERFACE_ID, tmp));
}
// Generate client-id option
OptionPtr generateClientId(size_t duid_size = 32) {
OptionBuffer clnt_duid(duid_size);
for (int i = 0; i < duid_size; i++) {
clnt_duid[i] = 100 + i;
}
duid_ = DuidPtr(new DUID(clnt_duid));
return (OptionPtr(new Option(Option::V6, D6O_CLIENTID,
clnt_duid.begin(),
clnt_duid.begin() + duid_size)));
}
// Checks if server response (ADVERTISE or REPLY) includes proper server-id.
void checkServerId(const Pkt6Ptr& rsp, const OptionPtr& expected_srvid) {
// check that server included its server-id
OptionPtr tmp = rsp->getOption(D6O_SERVERID);
EXPECT_EQ(tmp->getType(), expected_srvid->getType() );
ASSERT_EQ(tmp->len(), expected_srvid->len() );
EXPECT_TRUE(tmp->getData() == expected_srvid->getData());
}
// Checks if server response (ADVERTISE or REPLY) includes proper client-id.
void checkClientId(const Pkt6Ptr& rsp, const OptionPtr& expected_clientid) {
// check that server included our own client-id
OptionPtr tmp = rsp->getOption(D6O_CLIENTID);
ASSERT_TRUE(tmp);
EXPECT_EQ(expected_clientid->getType(), tmp->getType());
ASSERT_EQ(expected_clientid->len(), tmp->len());
// check that returned client-id is valid
EXPECT_TRUE(expected_clientid->getData() == tmp->getData());
}
// Checks if server response is a NAK
void checkNakResponse(const Pkt6Ptr& rsp, uint8_t expected_message_type,
uint32_t expected_transid,
uint16_t expected_status_code) {
// Check if we get response at all
checkResponse(rsp, expected_message_type, expected_transid);
// Check that IA_NA was returned
OptionPtr option_ia_na = rsp->getOption(D6O_IA_NA);
ASSERT_TRUE(option_ia_na);
// check that the status is no address available
boost::shared_ptr<Option6IA> ia = boost::dynamic_pointer_cast<Option6IA>(option_ia_na);
ASSERT_TRUE(ia);
checkIA_NAStatusCode(ia, expected_status_code);
}
// Checks that server rejected IA_NA, i.e. that it has no addresses and
// that expected status code really appears there. In some limited cases
// (reply to RELEASE) it may be used to verify positive case, where
// IA_NA response is expected to not include address.
//
// Status code indicates type of error encountered (in theory it can also
// indicate success, but servers typically don't send success status
// as this is the default result and it saves bandwidth)
void checkIA_NAStatusCode(const boost::shared_ptr<Option6IA>& ia,
uint16_t expected_status_code) {
// Make sure there is no address assigned.
EXPECT_FALSE(ia->getOption(D6O_IAADDR));
// T1, T2 should be zeroed
EXPECT_EQ(0, ia->getT1());
EXPECT_EQ(0, ia->getT2());
OptionCustomPtr status =
boost::dynamic_pointer_cast<OptionCustom>(ia->getOption(D6O_STATUS_CODE));
// It is ok to not include status success as this is the default behavior
if (expected_status_code == STATUS_Success && !status) {
return;
}
EXPECT_TRUE(status);
if (status) {
// We don't have dedicated class for status code, so let's just interpret
// first 2 bytes as status. Remainder of the status code option content is
// just a text explanation what went wrong.
EXPECT_EQ(static_cast<uint16_t>(expected_status_code),
status->readInteger<uint16_t>(0));
}
}
void checkMsgStatusCode(const Pkt6Ptr& msg, uint16_t expected_status) {
OptionCustomPtr status =
boost::dynamic_pointer_cast<OptionCustom>(msg->getOption(D6O_STATUS_CODE));
// It is ok to not include status success as this is the default behavior
if (expected_status == STATUS_Success && !status) {
return;
}
EXPECT_TRUE(status);
if (status) {
// We don't have dedicated class for status code, so let's just interpret
// first 2 bytes as status. Remainder of the status code option content is
// just a text explanation what went wrong.
EXPECT_EQ(static_cast<uint16_t>(expected_status),
status->readInteger<uint16_t>(0));
}
}
// Basic checks for generated response (message type and transaction-id).
void checkResponse(const Pkt6Ptr& rsp, uint8_t expected_message_type,
uint32_t expected_transid) {
ASSERT_TRUE(rsp);
EXPECT_EQ(expected_message_type, rsp->getType());
EXPECT_EQ(expected_transid, rsp->getTransid());
}
virtual ~NakedDhcpv6SrvTest() {
// Let's clean up if there is such a file.
unlink(DUID_FILE);
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts(
"buffer6_receive");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts(
"buffer6_send");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts(
"lease6_renew");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts(
"lease6_release");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts(
"pkt6_receive");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts(
"pkt6_send");
HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts(
"subnet6_select");
};
// A DUID used in most tests (typically as client-id)
DuidPtr duid_;
int rcode_;
ConstElementPtr comment_;