2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-03 15:35:17 +00:00

[5443] Checkpoint: updated DHCPv6 (todo hook tests)

This commit is contained in:
Francis Dupont
2017-12-16 00:45:06 +01:00
parent ec9cc33e70
commit 4d759e30e1
8 changed files with 224 additions and 69 deletions

View File

@@ -288,7 +288,7 @@ client's request and acted on it (e.g. possibly allocated a lease).
% DHCP4_HOOK_SUBNET4_SELECT_DROP %1: packet was dropped, because a callout set drop flag % DHCP4_HOOK_SUBNET4_SELECT_DROP %1: packet was dropped, because a callout set drop flag
This debug message is printed when a callout installed on the This debug message is printed when a callout installed on the
subnet4_select hook point sets the drop flag. For this particular hook subnet4_select hook point sets the drop flag. For this particular hook
point, the setting of the flag instructs the server to drop the receive point, the setting of the flag instructs the server to drop the received
packet. The argument specifies the client and transaction identification packet. The argument specifies the client and transaction identification
information. information.

View File

@@ -825,6 +825,7 @@ Dhcpv4Srv::run_one() {
LOG_DEBUG(bad_packet4_logger, DBG_DHCP4_BASIC, LOG_DEBUG(bad_packet4_logger, DBG_DHCP4_BASIC,
DHCP4_PACKET_DROP_0008) DHCP4_PACKET_DROP_0008)
.arg(query->getLabel()); .arg(query->getLabel());
return;
} else { } else {
processPacket(query, rsp); processPacket(query, rsp);
} }

View File

@@ -64,7 +64,9 @@ to the end of this list.
in their raw form. Unless you need to access to the raw data, it is 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. usually better to install your callout on the "pkt6_receive" hook point.
- <b>Next step status</b>: If any callout sets the status to SKIP, the - <b>Next step status</b>: If any callout sets the status to DROP, the server
will drop the packet and start processing the next one.
If any callout sets the status to SKIP, the
server will assume that the callout parsed the buffer and added the server will assume that the callout parsed the buffer and added the
necessary option objects to the @c options_ field; the server will not necessary option objects to the @c options_ field; the server will not
do any parsing. If the callout sets the skip flag but does not parse do any parsing. If the callout sets the skip flag but does not parse
@@ -89,7 +91,7 @@ to the end of this list.
other fields in the Pkt6 object. For this reason, modification of the other fields in the Pkt6 object. For this reason, modification of the
@c data_ field would have no effect.) @c data_ field would have no effect.)
- <b>Next step status</b>: If any callout sets the status to SKIP, the server will - <b>Next step status</b>: If any callout sets the status to SKIP (or DROP), the server will
drop the packet and start processing the next one. The reason for the drop drop the packet and start processing the next one. The reason for the drop
will be logged if logging is set to the appropriate debug level. will be logged if logging is set to the appropriate debug level.
@@ -107,7 +109,9 @@ to the end of this list.
configured being provided as "subnet6collection". The list itself must configured being provided as "subnet6collection". The list itself must
not be modified. not be modified.
- <b>Next step status</b>: If any callout installed on "subnet6_select" - <b>Next step status</b>: If any callout installed on "subnet6_select" sets
the status to DROP, the server will drop the packet and start processing
the next one. If any callout installed on "subnet6_select"
sets the status to SKIP, the server will not select any subnet. Packet processing sets the status to SKIP, the server will not select any subnet. Packet processing
will continue, but will be severely limited. will continue, but will be severely limited.
@@ -258,7 +262,7 @@ to the end of this list.
finish execution. finish execution.
- <b>Next step status</b>: If any callout installed on "lease6_release" - <b>Next step status</b>: If any callout installed on "lease6_release"
sets the status to SKIP, the server will not delete the lease, which will sets the status to SKIP (or DROP), the server will not delete the lease, which will
remain in the database until it expires. However, the server will send out remain in the database until it expires. However, the server will send out
the response back to the client as if it did. the response back to the client as if it did.
@@ -283,8 +287,8 @@ to the end of this list.
and option objects into the @c buffer_out_ field and will skip packing part. and option objects into the @c buffer_out_ field and will skip packing part.
Note that if the callout sets skip flag, but did not prepare the 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 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 ignored by the client. If any callout sets the status to DROP,
skip flag in the "buffer6_send" hook point. the server will drop the prepared response.
@subsection dhcpv6HooksBuffer6Send buffer6_send @subsection dhcpv6HooksBuffer6Send buffer6_send
@@ -302,7 +306,7 @@ to the end of this list.
to modify that data, it will probably be found easier to modify the to modify that data, it will probably be found easier to modify the
option objects in a callout attached to the "pkt6_send" hook). option objects in a callout attached to the "pkt6_send" hook).
- <b>Next step status</b>: If any callout sets the status to SKIP, the server - <b>Next step status</b>: If any callout sets the status to SKIP (or DROP), the server
will drop this response packet. However, the original request packet will drop this response packet. However, the original request packet
from a client has been processed, so server's state has 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 (e.g. lease was allocated). Setting this flag merely stops the change

View File

@@ -246,13 +246,21 @@ A "libreload" command was issued to reload the hooks libraries but for
some reason the reload failed. Other error messages issued from the some reason the reload failed. Other error messages issued from the
hooks framework will indicate the nature of the problem. hooks framework will indicate the nature of the problem.
% DHCP6_HOOK_BUFFER_RCVD_SKIP received buffer from %1 to %2 over interface %3 was dropped because a callout set the skip flag % DHCP6_HOOK_BUFFER_RCVD_DROP received buffer from %1 to %2 over interface %3 was dropped because a callout set the drop flag
This debug message is printed when a callout installed on buffer6_receive This debug message is printed when a callout installed on buffer6_receive
hook point set the skip flag. For this particular hook point, the hook point set the drop flag. For this particular hook point, the
setting of the flag by a callout instructs the server to drop the packet. setting of the flag by a callout instructs the server to drop the packet.
The arguments specify the source and destination address as well as The arguments specify the source and destination address as well as
the name of the interface over which the buffer has been received. the name of the interface over which the buffer has been received.
% DHCP6_HOOK_BUFFER_RCVD_SKIP received buffer from %1 to %2 over interface %3 is not parsed 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
not parse the buffer because it was already parsed by the hook. The
arguments specify the source and destination address as well as the
name of the interface over which the buffer has been received.
% DHCP6_HOOK_BUFFER_SEND_SKIP %1: prepared DHCPv6 response was dropped because a callout set the skip flag % DHCP6_HOOK_BUFFER_SEND_SKIP %1: prepared DHCPv6 response was dropped because a callout set the skip flag
This debug message is printed when a callout installed on buffer6_send This debug message is printed when a callout installed on buffer6_send
hook point set the skip flag. For this particular hook point, the hook point set the skip flag. For this particular hook point, the
@@ -300,15 +308,23 @@ 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 sets the skip flag. For this particular hook point, the
setting of the flag instructs the server to drop the packet. setting of the flag instructs the server to drop the packet.
% DHCP6_HOOK_PACKET_SEND_SKIP %1: prepared DHCPv6 response was not sent because a callout set the skip flag % DHCP6_HOOK_PACKET_SEND_DROP %1: prepared DHCPv6 response was not sent because a callout set the drop flag
This debug message is printed when a callout installed on the pkt6_send This debug message is printed when a callout installed on the pkt6_send
hook point set the skip flag. For this particular hook point, the setting hook point set the drop flag. For this particular hook point, the setting
of the flag by a callout instructs the server to drop the packet. This 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 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 the server processed client's request and acted on it (e.g. possibly
allocated a lease). The argument specifies the client and transaction allocated a lease). The argument specifies the client and transaction
identification information. identification information.
% DHCP6_HOOK_PACKET_SEND_SKIP %1: prepared DHCPv6 response is not built because a callout set the skip flag
This debug message is printed when a callout installed on the
pkt6_send hook point set the skip flag. For this particular hook
point, the setting of the flag by a callout instructs the server to
not build the wire data (pack) because it was already done by the
book. The argument specifies the client and transaction identification
information.
% DHCP6_HOOK_SUBNET6_SELECT_SKIP %1: no subnet was selected because a callout set the skip flag % DHCP6_HOOK_SUBNET6_SELECT_SKIP %1: no subnet was selected because a callout set the skip flag
This debug message is printed when a callout installed on the This debug message is printed when a callout installed on the
subnet6_select hook point set the skip flag. For this particular hook subnet6_select hook point set the skip flag. For this particular hook
@@ -318,6 +334,13 @@ will be only able to offer global options - no addresses or prefixes
will be assigned. The argument holds the client and transaction will be assigned. The argument holds the client and transaction
identification information. identification information.
% DHCP6_HOOK_SUBNET6_SELECT_DROP %1: packet was dropped because a callout set the drop flag
This debug message is printed when a callout installed on the
subnet6_select hook point set the drop flag. For this particular hook
point, the setting of the flag instructs the server to drop the
received packet. The argument holds the client and transaction
identification information.
% DHCP6_INIT_FAIL failed to initialize Kea server: %1 % DHCP6_INIT_FAIL failed to initialize Kea server: %1
The server has failed to establish communication with the rest of Kea, The server has failed to establish communication with the rest of Kea,
failed to read JSON configuration file or encountered any other critical failed to read JSON configuration file or encountered any other critical

View File

@@ -296,8 +296,10 @@ Dhcpv6Srv::testUnicast(const Pkt6Ptr& pkt) const {
} }
void void
Dhcpv6Srv::initContext(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx) { Dhcpv6Srv::initContext(const Pkt6Ptr& pkt,
ctx.subnet_ = selectSubnet(pkt); AllocEngine::ClientContext6& ctx,
bool& drop) {
ctx.subnet_ = selectSubnet(pkt, drop);
ctx.duid_ = pkt->getClientId(), ctx.duid_ = pkt->getClientId(),
ctx.fwd_dns_update_ = false; ctx.fwd_dns_update_ = false;
ctx.rev_dns_update_ = false; ctx.rev_dns_update_ = false;
@@ -306,6 +308,11 @@ Dhcpv6Srv::initContext(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx) {
ctx.callout_handle_ = getCalloutHandle(pkt); ctx.callout_handle_ = getCalloutHandle(pkt);
ctx.hwaddr_ = getMAC(pkt); ctx.hwaddr_ = getMAC(pkt);
if (drop) {
// Caller will immediately drop the packet so simply return now.
return;
}
// Collect host identifiers if host reservations enabled. The identifiers // Collect host identifiers if host reservations enabled. The identifiers
// are stored in order of preference. The server will use them in that // are stored in order of preference. The server will use them in that
// order to search for host reservations. // order to search for host reservations.
@@ -473,6 +480,7 @@ void Dhcpv6Srv::run_one() {
LOG_DEBUG(bad_packet6_logger, DBG_DHCP6_DETAIL_DATA, LOG_DEBUG(bad_packet6_logger, DBG_DHCP6_DETAIL_DATA,
DHCP6_PACKET_DROP_DHCP_DISABLED) DHCP6_PACKET_DROP_DHCP_DISABLED)
.arg(query->getLabel()); .arg(query->getLabel());
return;
} else { } else {
processPacket(query, rsp); processPacket(query, rsp);
} }
@@ -505,14 +513,13 @@ void Dhcpv6Srv::run_one() {
// Callouts decided to skip the next processing step. The next // Callouts decided to skip the next processing step. The next
// processing step would to parse the packet, so skip at this // processing step would to parse the packet, so skip at this
// stage means drop. // stage means drop.
if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) { if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
(callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
LOG_DEBUG(hooks_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_BUFFER_SEND_SKIP) LOG_DEBUG(hooks_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_BUFFER_SEND_SKIP)
.arg(rsp->getLabel()); .arg(rsp->getLabel());
return; return;
} }
/// @todo: Add support for DROP status
callout_handle->getArgument("response6", rsp); callout_handle->getArgument("response6", rsp);
} }
@@ -562,7 +569,20 @@ Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp) {
skip_unpack = true; skip_unpack = true;
} }
/// @todo: Add support for DROP status. // Callouts decided to drop the received packet
// The response (rsp) is null so the caller (run_one) will
// immediately return too.
if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
LOG_DEBUG(hooks_logger, DBG_DHCP6_DETAIL, DHCP6_HOOK_BUFFER_RCVD_DROP)
.arg(query->getRemoteAddr().toText())
.arg(query->getLocalAddr().toText())
.arg(query->getIface());
// Increase the statistic of dropped packets.
StatsMgr::instance().addValue("pkt6-receive-drop",
static_cast<int64_t>(1));
return;
}
callout_handle->getArgument("query6", query); callout_handle->getArgument("query6", query);
} }
@@ -648,14 +668,16 @@ Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp) {
// Callouts decided to skip the next processing step. The next // Callouts decided to skip the next processing step. The next
// processing step would to process the packet, so skip at this // processing step would to process the packet, so skip at this
// stage means drop. // stage means drop.
if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) { if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
(callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
LOG_DEBUG(hooks_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_PACKET_RCVD_SKIP) LOG_DEBUG(hooks_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_PACKET_RCVD_SKIP)
.arg(query->getLabel()); .arg(query->getLabel());
// Increase the statistic of dropped packets.
StatsMgr::instance().addValue("pkt6-receive-drop",
static_cast<int64_t>(1));
return; return;
} }
/// @todo: Add support for DROP status.
callout_handle->getArgument("query6", query); callout_handle->getArgument("query6", query);
} }
@@ -807,7 +829,13 @@ Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp) {
skip_pack = true; skip_pack = true;
} }
/// @todo: Add support for DROP status /// Callouts decided to drop the packet.
if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
LOG_DEBUG(hooks_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_PACKET_SEND_DROP)
.arg(rsp->getLabel());
rsp.reset();
return;
}
} }
if (!skip_pack) { if (!skip_pack) {
@@ -1114,7 +1142,7 @@ Dhcpv6Srv::sanityCheck(const Pkt6Ptr& pkt, RequirementLevel clientid,
} }
Subnet6Ptr Subnet6Ptr
Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) { Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question, bool& drop) {
// Initialize subnet selector with the values used to select the subnet. // Initialize subnet selector with the values used to select the subnet.
SubnetSelector selector; SubnetSelector selector;
selector.iface_name_ = question->getIface(); selector.iface_name_ = question->getIface();
@@ -1174,7 +1202,14 @@ Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) {
return (Subnet6Ptr()); return (Subnet6Ptr());
} }
/// @todo: Add support for DROP status. // Callouts decided to drop the packet. It is a superset of the
// skip case so no subnet will be selected.
if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
LOG_DEBUG(hooks_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_SUBNET6_SELECT_DROP)
.arg(question->getLabel());
drop = true;
return (Subnet6Ptr());
}
// Use whatever subnet was specified by the callout // Use whatever subnet was specified by the callout
callout_handle->getArgument("subnet6", subnet); callout_handle->getArgument("subnet6", subnet);
@@ -2257,13 +2292,12 @@ Dhcpv6Srv::releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
// Callouts decided to skip the next processing step. The next // Callouts decided to skip the next processing step. The next
// processing step would to send the packet, so skip at this // processing step would to send the packet, so skip at this
// stage means "drop response". // stage means "drop response".
if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) { if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
(callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
skip = true; skip = true;
LOG_DEBUG(hooks_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_LEASE6_RELEASE_NA_SKIP) LOG_DEBUG(hooks_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_LEASE6_RELEASE_NA_SKIP)
.arg(query->getLabel()); .arg(query->getLabel());
} }
/// @todo: Add support for DROP status
} }
// Ok, we've passed all checks. Let's release this address. // Ok, we've passed all checks. Let's release this address.
@@ -2473,7 +2507,13 @@ Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx; AllocEngine::ClientContext6 ctx;
initContext(solicit, ctx); bool drop = false;
initContext(solicit, ctx, drop);
// Stop here if initContext decided to drop the packet.
if (drop) {
return (Pkt6Ptr());
}
Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, solicit->getTransid())); Pkt6Ptr response(new Pkt6(DHCPV6_ADVERTISE, solicit->getTransid()));
@@ -2522,7 +2562,13 @@ Dhcpv6Srv::processRequest(const Pkt6Ptr& request) {
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx; AllocEngine::ClientContext6 ctx;
initContext(request, ctx); bool drop = false;
initContext(request, ctx, drop);
// Stop here if initContext decided to drop the packet.
if (drop) {
return (Pkt6Ptr());
}
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, request->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, request->getTransid()));
@@ -2552,7 +2598,13 @@ Dhcpv6Srv::processRenew(const Pkt6Ptr& renew) {
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx; AllocEngine::ClientContext6 ctx;
initContext(renew, ctx); bool drop = false;
initContext(renew, ctx, drop);
// Stop here if initContext decided to drop the packet.
if (drop) {
return (Pkt6Ptr());
}
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, renew->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, renew->getTransid()));
@@ -2582,7 +2634,13 @@ Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind) {
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx; AllocEngine::ClientContext6 ctx;
initContext(rebind, ctx); bool drop = false;
initContext(rebind, ctx, drop);
// Stop here if initContext decided to drop the packet.
if (drop) {
return (Pkt6Ptr());
}
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, rebind->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, rebind->getTransid()));
@@ -2612,7 +2670,14 @@ Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) {
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx; AllocEngine::ClientContext6 ctx;
initContext(confirm, ctx); bool drop = false;
initContext(confirm, ctx, drop);
// Stop here if initContext decided to drop the packet.
if (drop) {
return (Pkt6Ptr());
}
setReservedClientClasses(confirm, ctx); setReservedClientClasses(confirm, ctx);
// Get IA_NAs from the Confirm. If there are none, the message is // Get IA_NAs from the Confirm. If there are none, the message is
@@ -2705,7 +2770,14 @@ Dhcpv6Srv::processRelease(const Pkt6Ptr& release) {
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx; AllocEngine::ClientContext6 ctx;
initContext(release, ctx); bool drop = false;
initContext(release, ctx, drop);
// Stop here if initContext decided to drop the packet.
if (drop) {
return (Pkt6Ptr());
}
setReservedClientClasses(release, ctx); setReservedClientClasses(release, ctx);
Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, release->getTransid())); Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, release->getTransid()));
@@ -2734,7 +2806,14 @@ Dhcpv6Srv::processDecline(const Pkt6Ptr& decline) {
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx; AllocEngine::ClientContext6 ctx;
initContext(decline, ctx); bool drop = false;
initContext(decline, ctx, drop);
// Stop here if initContext decided to drop the packet.
if (drop) {
return (Pkt6Ptr());
}
setReservedClientClasses(decline, ctx); setReservedClientClasses(decline, ctx);
// Copy client options (client-id, also relay information if present) // Copy client options (client-id, also relay information if present)
@@ -3015,7 +3094,14 @@ Dhcpv6Srv::processInfRequest(const Pkt6Ptr& inf_request) {
// Let's create a simplified client context here. // Let's create a simplified client context here.
AllocEngine::ClientContext6 ctx; AllocEngine::ClientContext6 ctx;
initContext(inf_request, ctx); bool drop = false;
initContext(inf_request, ctx, drop);
// Stop here if initContext decided to drop the packet.
if (drop) {
return (Pkt6Ptr());
}
setReservedClientClasses(inf_request, ctx); setReservedClientClasses(inf_request, ctx);
// Create a Reply packet, with the same trans-id as the client's. // Create a Reply packet, with the same trans-id as the client's.

View File

@@ -313,8 +313,9 @@ protected:
/// @brief Selects a subnet for a given client's packet. /// @brief Selects a subnet for a given client's packet.
/// ///
/// @param question client's message /// @param question client's message
/// @param drop if it is true the packet will be dropped
/// @return selected subnet (or NULL if no suitable subnet was found) /// @return selected subnet (or NULL if no suitable subnet was found)
isc::dhcp::Subnet6Ptr selectSubnet(const Pkt6Ptr& question); isc::dhcp::Subnet6Ptr selectSubnet(const Pkt6Ptr& question, bool& drop);
/// @brief Processes IA_NA option (and assigns addresses if necessary). /// @brief Processes IA_NA option (and assigns addresses if necessary).
/// ///
@@ -688,7 +689,10 @@ protected:
/// ///
/// @param pkt pointer to a packet for which context will be created. /// @param pkt pointer to a packet for which context will be created.
/// @param [out] ctx reference to context object to be initialized. /// @param [out] ctx reference to context object to be initialized.
void initContext(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx); /// @param [out] drop if it is true the packet will be dropped.
void initContext(const Pkt6Ptr& pkt,
AllocEngine::ClientContext6& ctx,
bool& drop);
/// @brief this is a prefix added to the content of vendor-class option /// @brief this is a prefix added to the content of vendor-class option
/// ///

View File

@@ -628,19 +628,23 @@ TEST_F(ClassifyTest, clientClassifySubnet) {
// This discover does not belong to foo class, so it will not // This discover does not belong to foo class, so it will not
// be serviced // be serviced
EXPECT_FALSE(srv_.selectSubnet(sol)); bool drop = false;
EXPECT_FALSE(srv_.selectSubnet(sol, drop));
EXPECT_FALSE(drop);
// Let's add the packet to bar class and try again. // Let's add the packet to bar class and try again.
sol->addClass("bar"); sol->addClass("bar");
// Still not supported, because it belongs to wrong class. // Still not supported, because it belongs to wrong class.
EXPECT_FALSE(srv_.selectSubnet(sol)); EXPECT_FALSE(srv_.selectSubnet(sol, drop));
EXPECT_FALSE(drop);
// Let's add it to matching class. // Let's add it to matching class.
sol->addClass("foo"); sol->addClass("foo");
// This time it should work // This time it should work
EXPECT_TRUE(srv_.selectSubnet(sol)); EXPECT_TRUE(srv_.selectSubnet(sol, drop));
EXPECT_FALSE(drop);
} }
// Tests whether a packet with custom vendor-class (not erouter or docsis) // Tests whether a packet with custom vendor-class (not erouter or docsis)
@@ -733,12 +737,15 @@ TEST_F(ClassifyTest, relayOverrideAndClientClass) {
// subnet[0], even though the relay-ip matches. It should be accepted in // subnet[0], even though the relay-ip matches. It should be accepted in
// subnet[1], because the subnet matches and there are no class // subnet[1], because the subnet matches and there are no class
// requirements. // requirements.
EXPECT_TRUE(subnet2 == srv_.selectSubnet(sol)); bool drop = false;
EXPECT_TRUE(subnet2 == srv_.selectSubnet(sol, drop));
EXPECT_FALSE(drop);
// Now let's add this packet to class foo and recheck. This time it should // Now let's add this packet to class foo and recheck. This time it should
// be accepted in the first subnet, because both class and relay-ip match. // be accepted in the first subnet, because both class and relay-ip match.
sol->addClass("foo"); sol->addClass("foo");
EXPECT_TRUE(subnet1 == srv_.selectSubnet(sol)); EXPECT_TRUE(subnet1 == srv_.selectSubnet(sol, drop));
EXPECT_FALSE(drop);
} }
// This test checks that it is possible to specify static reservations for // This test checks that it is possible to specify static reservations for

View File

@@ -1233,7 +1233,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetAddr) {
// The clause for assuming local subnet if there is only one subnet is was // The clause for assuming local subnet if there is only one subnet is was
// removed. // removed.
EXPECT_FALSE(srv.selectSubnet(pkt)); bool drop = false;
EXPECT_FALSE(srv.selectSubnet(pkt, drop));
EXPECT_FALSE(drop);
// CASE 2: We have only one subnet defined and we received relayed traffic. // CASE 2: We have only one subnet defined and we received relayed traffic.
// We should NOT select it. // We should NOT select it.
@@ -1243,8 +1245,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetAddr) {
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); // just a single subnet CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); // just a single subnet
CfgMgr::instance().commit(); CfgMgr::instance().commit();
pkt->setRemoteAddr(IOAddress("2001:db8:abcd::2345")); pkt->setRemoteAddr(IOAddress("2001:db8:abcd::2345"));
Subnet6Ptr selected = srv.selectSubnet(pkt); Subnet6Ptr selected = srv.selectSubnet(pkt, drop);
EXPECT_FALSE(selected); EXPECT_FALSE(selected);
EXPECT_FALSE(drop);
// CASE 3: We have three subnets defined and we received local traffic. // CASE 3: We have three subnets defined and we received local traffic.
// Nothing should be selected. // Nothing should be selected.
@@ -1254,8 +1257,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetAddr) {
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3);
CfgMgr::instance().commit(); CfgMgr::instance().commit();
pkt->setRemoteAddr(IOAddress("fe80::abcd")); pkt->setRemoteAddr(IOAddress("fe80::abcd"));
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_FALSE(selected); EXPECT_FALSE(selected);
EXPECT_FALSE(drop);
// CASE 4: We have three subnets defined and we received relayed traffic // CASE 4: We have three subnets defined and we received relayed traffic
// that came out of subnet 2. We should select subnet2 then // that came out of subnet 2. We should select subnet2 then
@@ -1265,8 +1269,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetAddr) {
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3);
CfgMgr::instance().commit(); CfgMgr::instance().commit();
pkt->setRemoteAddr(IOAddress("2001:db8:2::baca")); pkt->setRemoteAddr(IOAddress("2001:db8:2::baca"));
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_EQ(selected, subnet2); EXPECT_EQ(selected, subnet2);
EXPECT_FALSE(drop);
// CASE 5: We have three subnets defined and we received relayed traffic // CASE 5: We have three subnets defined and we received relayed traffic
// that came out of undefined subnet. We should select nothing // that came out of undefined subnet. We should select nothing
@@ -1276,7 +1281,8 @@ TEST_F(Dhcpv6SrvTest, selectSubnetAddr) {
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3);
CfgMgr::instance().commit(); CfgMgr::instance().commit();
pkt->setRemoteAddr(IOAddress("2001:db8:4::baca")); pkt->setRemoteAddr(IOAddress("2001:db8:4::baca"));
EXPECT_FALSE(srv.selectSubnet(pkt)); EXPECT_FALSE(srv.selectSubnet(pkt, drop));
EXPECT_FALSE(drop);
} }
// This test verifies if selectSubnet() selects proper subnet for a given // This test verifies if selectSubnet() selects proper subnet for a given
@@ -1300,8 +1306,10 @@ TEST_F(Dhcpv6SrvTest, selectSubnetIface) {
Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
pkt->setIface("eth0"); pkt->setIface("eth0");
Subnet6Ptr selected = srv.selectSubnet(pkt); bool drop = false;
Subnet6Ptr selected = srv.selectSubnet(pkt, drop);
EXPECT_EQ(selected, subnet1); EXPECT_EQ(selected, subnet1);
EXPECT_FALSE(drop);
// CASE 2: We have only one subnet defined and it is available via eth0. // CASE 2: We have only one subnet defined and it is available via eth0.
// Packet came from eth1. We should not select it // Packet came from eth1. We should not select it
@@ -1311,8 +1319,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetIface) {
pkt->setIface("eth1"); pkt->setIface("eth1");
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_FALSE(selected); EXPECT_FALSE(selected);
EXPECT_FALSE(drop);
// CASE 3: We have only 3 subnets defined, one over eth0, one remote and // CASE 3: We have only 3 subnets defined, one over eth0, one remote and
// one over wifi1. // one over wifi1.
@@ -1324,13 +1333,16 @@ TEST_F(Dhcpv6SrvTest, selectSubnetIface) {
CfgMgr::instance().commit(); CfgMgr::instance().commit();
pkt->setIface("eth0"); pkt->setIface("eth0");
EXPECT_EQ(subnet1, srv.selectSubnet(pkt)); EXPECT_EQ(subnet1, srv.selectSubnet(pkt, drop));
EXPECT_FALSE(drop);
pkt->setIface("eth3"); // no such interface pkt->setIface("eth3"); // no such interface
EXPECT_EQ(Subnet6Ptr(), srv.selectSubnet(pkt)); // nothing selected EXPECT_EQ(Subnet6Ptr(), srv.selectSubnet(pkt, drop)); // nothing selected
EXPECT_FALSE(drop);
pkt->setIface("wifi1"); pkt->setIface("wifi1");
EXPECT_EQ(subnet3, srv.selectSubnet(pkt)); EXPECT_EQ(subnet3, srv.selectSubnet(pkt, drop));
EXPECT_FALSE(drop);
} }
// This test verifies if selectSubnet() selects proper subnet for a given // This test verifies if selectSubnet() selects proper subnet for a given
@@ -1355,8 +1367,10 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) {
Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
pkt->relay_info_.push_back(relay); pkt->relay_info_.push_back(relay);
Subnet6Ptr selected = srv.selectSubnet(pkt); bool drop = false;
Subnet6Ptr selected = srv.selectSubnet(pkt, drop);
EXPECT_FALSE(selected); EXPECT_FALSE(selected);
EXPECT_FALSE(drop);
// CASE 2: We have three subnets defined and we received relayed traffic // CASE 2: We have three subnets defined and we received relayed traffic
// that came out of subnet 2. We should select subnet2 then // that came out of subnet 2. We should select subnet2 then
@@ -1365,22 +1379,25 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) {
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2);
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3);
CfgMgr::instance().commit(); CfgMgr::instance().commit();
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_EQ(selected, subnet2); EXPECT_EQ(selected, subnet2);
EXPECT_FALSE(drop);
// Source of the packet should have no meaning. Selection is based // Source of the packet should have no meaning. Selection is based
// on linkaddr field in the relay // on linkaddr field in the relay
pkt->setRemoteAddr(IOAddress("2001:db8:1::baca")); pkt->setRemoteAddr(IOAddress("2001:db8:1::baca"));
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_EQ(selected, subnet2); EXPECT_EQ(selected, subnet2);
EXPECT_FALSE(drop);
// But not when this linkaddr field is not usable. // But not when this linkaddr field is not usable.
Pkt6::RelayInfo relay2; Pkt6::RelayInfo relay2;
relay2.peeraddr_ = IOAddress("fe80::1"); relay2.peeraddr_ = IOAddress("fe80::1");
pkt->relay_info_.clear(); pkt->relay_info_.clear();
pkt->relay_info_.push_back(relay2); pkt->relay_info_.push_back(relay2);
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_EQ(selected, subnet1); EXPECT_EQ(selected, subnet1);
EXPECT_FALSE(drop);
// CASE 3: We have three subnets defined and we received relayed traffic // CASE 3: We have three subnets defined and we received relayed traffic
// that came out a layer 2 relay on subnet 2. We should select subnet2 then // that came out a layer 2 relay on subnet 2. We should select subnet2 then
@@ -1393,8 +1410,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) {
pkt->relay_info_.push_back(relay); pkt->relay_info_.push_back(relay);
relay2.hop_count_ = 1; relay2.hop_count_ = 1;
pkt->relay_info_.push_back(relay2); pkt->relay_info_.push_back(relay2);
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_EQ(selected, subnet2); EXPECT_EQ(selected, subnet2);
EXPECT_FALSE(drop);
// The number of level 2 relay doesn't matter // The number of level 2 relay doesn't matter
pkt->relay_info_.clear(); pkt->relay_info_.clear();
@@ -1415,8 +1433,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) {
relay23.peeraddr_ = IOAddress("fe80::1"); relay23.peeraddr_ = IOAddress("fe80::1");
relay23.hop_count_ = 4; relay23.hop_count_ = 4;
pkt->relay_info_.push_back(relay23); pkt->relay_info_.push_back(relay23);
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_EQ(selected, subnet2); EXPECT_EQ(selected, subnet2);
EXPECT_FALSE(drop);
// Only the inner/last relay with a usable address matters // Only the inner/last relay with a usable address matters
pkt->relay_info_.clear(); pkt->relay_info_.clear();
@@ -1429,8 +1448,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) {
relay3.peeraddr_ = IOAddress("fe80::1"); relay3.peeraddr_ = IOAddress("fe80::1");
relay3.hop_count_ = 4; relay3.hop_count_ = 4;
pkt->relay_info_.push_back(relay3); pkt->relay_info_.push_back(relay3);
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_EQ(selected, subnet3); EXPECT_EQ(selected, subnet3);
EXPECT_FALSE(drop);
// CASE 4: We have three subnets defined and we received relayed traffic // CASE 4: We have three subnets defined and we received relayed traffic
// that came out of undefined subnet. We should select nothing // that came out of undefined subnet. We should select nothing
@@ -1443,9 +1463,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) {
relay.hop_count_ = 0; relay.hop_count_ = 0;
relay.linkaddr_ = IOAddress("2001:db8:4::1234"); relay.linkaddr_ = IOAddress("2001:db8:4::1234");
pkt->relay_info_.push_back(relay); pkt->relay_info_.push_back(relay);
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_FALSE(selected); EXPECT_FALSE(selected);
EXPECT_FALSE(drop);
} }
// This test verifies if selectSubnet() selects proper subnet for a given // This test verifies if selectSubnet() selects proper subnet for a given
@@ -1475,16 +1495,19 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayInterfaceId) {
pkt->relay_info_.push_back(relay); pkt->relay_info_.push_back(relay);
// There is only one subnet configured and we are outside of that subnet // There is only one subnet configured and we are outside of that subnet
Subnet6Ptr selected = srv.selectSubnet(pkt); bool drop = false;
Subnet6Ptr selected = srv.selectSubnet(pkt, drop);
EXPECT_FALSE(selected); EXPECT_FALSE(selected);
EXPECT_FALSE(drop);
// CASE 2: We have only one subnet defined and it is for interface-id "relay2" // CASE 2: We have only one subnet defined and it is for interface-id "relay2"
// Packet came with interface-id "relay2". We should select it // Packet came with interface-id "relay2". We should select it
CfgMgr::instance().clear(); CfgMgr::instance().clear();
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); // just a single subnet CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); // just a single subnet
CfgMgr::instance().commit(); CfgMgr::instance().commit();
selected = srv.selectSubnet(pkt); selected = srv.selectSubnet(pkt, drop);
EXPECT_EQ(selected, subnet2); EXPECT_EQ(selected, subnet2);
EXPECT_FALSE(drop);
// CASE 3: We have only 3 subnets defined: one remote for interface-id "relay1", // CASE 3: We have only 3 subnets defined: one remote for interface-id "relay1",
// one remote for interface-id "relay2" and third local // one remote for interface-id "relay2" and third local
@@ -1495,7 +1518,8 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayInterfaceId) {
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3);
CfgMgr::instance().commit(); CfgMgr::instance().commit();
EXPECT_EQ(subnet2, srv.selectSubnet(pkt)); EXPECT_EQ(subnet2, srv.selectSubnet(pkt, drop));
EXPECT_FALSE(drop);
} }
// Checks if server responses are sent to the proper port. // Checks if server responses are sent to the proper port.
@@ -1974,24 +1998,30 @@ TEST_F(Dhcpv6SrvTest, relayOverride) {
// This is just a sanity check, we're using regular method: the relay // This is just a sanity check, we're using regular method: the relay
// belongs to the first (2001:db8:1::/64) subnet, so it's an easy decision. // belongs to the first (2001:db8:1::/64) subnet, so it's an easy decision.
EXPECT_TRUE(subnet1 == srv_.selectSubnet(sol)); bool drop = false;
EXPECT_TRUE(subnet1 == srv_.selectSubnet(sol, drop));
EXPECT_FALSE(drop);
// Relay belongs to the second subnet, so it should be selected. // Relay belongs to the second subnet, so it should be selected.
sol->relay_info_.back().linkaddr_ = IOAddress("2001:db8:2::1"); sol->relay_info_.back().linkaddr_ = IOAddress("2001:db8:2::1");
EXPECT_TRUE(subnet2 == srv_.selectSubnet(sol)); EXPECT_TRUE(subnet2 == srv_.selectSubnet(sol, drop));
EXPECT_FALSE(drop);
// Now let's check if the relay override for the first subnets works // Now let's check if the relay override for the first subnets works
sol->relay_info_.back().linkaddr_ = IOAddress("2001:db8:3::1"); sol->relay_info_.back().linkaddr_ = IOAddress("2001:db8:3::1");
EXPECT_TRUE(subnet1 == srv_.selectSubnet(sol)); EXPECT_TRUE(subnet1 == srv_.selectSubnet(sol, drop));
EXPECT_FALSE(drop);
// Now repeat that for relay matching the second subnet. // Now repeat that for relay matching the second subnet.
sol->relay_info_.back().linkaddr_ = IOAddress("2001:db8:3::2"); sol->relay_info_.back().linkaddr_ = IOAddress("2001:db8:3::2");
EXPECT_TRUE(subnet2 == srv_.selectSubnet(sol)); EXPECT_TRUE(subnet2 == srv_.selectSubnet(sol, drop));
EXPECT_FALSE(drop);
// Finally, let's check that completely mismatched relay will not get us // Finally, let's check that completely mismatched relay will not get us
// anything // anything
sol->relay_info_.back().linkaddr_ = IOAddress("2001:db8:1234::1"); sol->relay_info_.back().linkaddr_ = IOAddress("2001:db8:1234::1");
EXPECT_FALSE(srv_.selectSubnet(sol)); EXPECT_FALSE(srv_.selectSubnet(sol, drop));
EXPECT_FALSE(drop);
} }
/// @brief Creates RSOO option with suboptions /// @brief Creates RSOO option with suboptions