Commit 3e7fa856 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[5016] Update server code and tests to properly use exclude option.

parent 9145a3c0
......@@ -893,26 +893,7 @@ Dhcpv6Srv::appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer,
// Get the list of options that client requested.
const std::vector<uint16_t>& requested_opts = option_oro->getValues();
if (co_list.empty()) {
// If there are no options configured, we at least have to check if
// the client has requested PD exclude, which is configured as
// part of the pool configuration.
ctx.pd_exclude_requested_ = (std::find(requested_opts.begin(),
requested_opts.end(),
D6O_PD_EXCLUDE) !=
requested_opts.end());
return;
}
BOOST_FOREACH(uint16_t opt, requested_opts) {
// Prefix Exclude option requires special handling, as it can
// be configured as part of the pool configuration.
if (opt == D6O_PD_EXCLUDE) {
ctx.pd_exclude_requested_ = true;
// Prefix Exclude can only be included in the IA Prefix option
// of IA_PD. Thus there is nothing more to do here.
continue;
}
// Iterate on the configured option list
for (CfgOptionList::const_iterator copts = co_list.begin();
copts != co_list.end(); ++copts) {
......@@ -1576,6 +1557,8 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
ia_rsp->setT1(subnet->getT1());
ia_rsp->setT2(subnet->getT2());
const bool pd_exclude_requested = requestedInORO(query, D6O_PD_EXCLUDE);
for (Lease6Collection::iterator l = leases.begin();
l != leases.end(); ++l) {
......@@ -1594,14 +1577,12 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
(*l)->valid_lft_));
ia_rsp->addOption(addr);
if (ctx.pd_exclude_requested_) {
if (pd_exclude_requested) {
// PD exclude option has been requested via ORO, thus we need to
// include it if the pool configuration specifies this option.
Pool6Ptr pool = boost::dynamic_pointer_cast<
Pool6>(subnet->getPool(Lease::TYPE_PD, (*l)->addr_));
if (pool && pool->getExcludedPrefixLength() > 0) {
std::cout << pool->getExcludedPrefix() << "/"
<< (unsigned)pool->getExcludedPrefixLength() << std::endl;
OptionPtr opt(new Option6PDExclude((*l)->addr_,
(*l)->prefixlen_,
pool->getExcludedPrefix(),
......@@ -1877,6 +1858,8 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
// into temporary container.
AllocEngine::HintContainer hints = ctx.currentIA().hints_;
const bool pd_exclude_requested = requestedInORO(query, D6O_PD_EXCLUDE);
// For all the leases we have now, add the IAPPREFIX with non-zero lifetimes
for (Lease6Collection::const_iterator l = leases.begin(); l != leases.end(); ++l) {
......@@ -1885,7 +1868,8 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
(*l)->preferred_lft_, (*l)->valid_lft_));
ia_rsp->addOption(prf);
if (ctx.pd_exclude_requested_) {
if (pd_exclude_requested) {
// PD exclude option has been requested via ORO, thus we need to
// include it if the pool configuration specifies this option.
Pool6Ptr pool = boost::dynamic_pointer_cast<
......@@ -3288,5 +3272,19 @@ int Dhcpv6Srv::getHookIndexBuffer6Send() {
return (Hooks.hook_index_buffer6_send_);
}
bool
Dhcpv6Srv::requestedInORO(const Pkt6Ptr& query, const uint16_t code) const {
OptionUint16ArrayPtr oro =
boost::dynamic_pointer_cast<OptionUint16Array>(query->getOption(D6O_ORO));
if (oro) {
const std::vector<uint16_t>& codes = oro->getValues();
return (std::find(codes.begin(), codes.end(), code) != codes.end());
}
return (false);
}
};
};
......@@ -805,6 +805,15 @@ private:
/// @param query packet received
static void processStatsReceived(const Pkt6Ptr& query);
/// @brief Checks if the specified option code has been requested using
/// the Option Request option.
///
/// @param query Pointer to the client's query.
/// @parma code Option code.
///
/// @return true if option has been requested in the ORO.
bool requestedInORO(const Pkt6Ptr& query, const uint16_t code) const;
/// UDP port number on which server listens.
uint16_t port_;
......
......@@ -218,7 +218,7 @@ const char* RENEW_CONFIGS[] = {
" \"interface-id\": \"\","
" \"interface\": \"eth0\""
" } ],"
"\"valid-lifetime\": 4000 }
"\"valid-lifetime\": 4000 }"
};
/// @brief Test fixture class for testing Renew.
......@@ -352,7 +352,7 @@ TEST_F(RenewTest, renewWithExcludedPrefix) {
ASSERT_FALSE(option);
// Reconfigure the server to use the prefix pool with excluded prefix.
configure(RENEW_CONFIGS[4], *client.getServer());
configure(RENEW_CONFIGS[5], *client.getServer());
// Send Renew message to the server, including IA_NA and IA_PD.
ASSERT_NO_THROW(client.doRenew());
......
......@@ -339,7 +339,7 @@ TEST_F(SARRTest, directClientExcludedPrefix) {
// Configure client to request IA_PD.
client.requestPrefix();
client.requestOption(D6O_PD_EXCLUDE);
configure(CONFIGS[2], *client.getServer());
configure(CONFIGS[3], *client.getServer());
// Make sure we ended-up having expected number of subnets configured.
const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
getCfgSubnets6()->getAll();
......
......@@ -350,7 +350,7 @@ AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet,
duid_(duid), hwaddr_(), host_identifiers_(), host_(),
fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns),
hostname_(hostname), callout_handle_(callout_handle),
allocated_resources_(), ias_(), pd_exclude_requested_(false) {
allocated_resources_(), ias_() {
// Initialize host identifiers.
if (duid) {
......
......@@ -397,10 +397,6 @@ public:
/// @brief Container holding IA specific contexts.
std::vector<IAContext> ias_;
/// @brief Indicates if PD exclude option has been requested by a
/// client.
bool pd_exclude_requested_;
/// @brief Convenience method adding allocated prefix or address.
///
/// @param prefix Prefix or address.
......
......@@ -71,7 +71,7 @@ int Dhcp4o6IpcBase::open(uint16_t port, EndpointType endpoint_type) {
}
// We'll connect to the loopback address so bind to it too.
local6.sin6_addr.s6_addr[15] = 1;
if (bind(sock, (struct sockaddr *)&local6, sizeof(local6)) < 0) {
if (::bind(sock, (struct sockaddr *)&local6, sizeof(local6)) < 0) {
::close(sock);
isc_throw(Dhcp4o6IpcError, "Failed to bind DHCP4o6 socket.");
}
......
......@@ -525,11 +525,7 @@ private:
// If the option space is a standard DHCPv4 or DHCPv6 option space,
// this is most likely a standard option, for which we have a
// definition created within libdhcp++.
OptionDefinitionPtr def;
if ((space == DHCP4_OPTION_SPACE) ||
(space == DHCP6_OPTION_SPACE)) {
def = LibDHCP::getOptionDef(universe_, code);
}
OptionDefinitionPtr def = LibDHCP::getOptionDef(space, code);
// Otherwise, we may check if this an option encapsulated within the
// vendor space.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment