.arg(LeaseQueryImpl4::leaseQueryLabel(query));
StatsMgr::instance().addValue("pkt4-lease-query-received", static_cast<int64_t>(1));
+ bool invalid = false;
+ bool sending = false;
try {
- LeaseQueryImplFactory::getImpl().processQuery(query);
+ LeaseQueryImplFactory::getImpl().processQuery(query, invalid, sending);
} catch (const std::exception& ex) {
// Failed to parse the packet.
LOG_DEBUG(lease_query_logger, DBGLVL_TRACE_BASIC,
.arg(LeaseQueryImpl4::leaseQueryLabel(query))
.arg(ex.what());
+ handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
+ if (sending) {
+ return (0);
+ }
+ if (!invalid) {
+ StatsMgr::instance().addValue("pkt4-processing-failed",
+ static_cast<int64_t>(1));
+ }
StatsMgr::instance().addValue("pkt4-receive-drop",
static_cast<int64_t>(1));
- handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
return (0);
}
.arg(LeaseQueryImpl6::leaseQueryLabel(query));
StatsMgr::instance().addValue("pkt6-lease-query-received", static_cast<int64_t>(1));
+ bool invalid = false;
+ bool sending = false;
try {
- LeaseQueryImplFactory::getImpl().processQuery(query);
+ LeaseQueryImplFactory::getImpl().processQuery(query, invalid, sending);
} catch (const std::exception& ex) {
// Log that we failed to process the packet.
LOG_DEBUG(lease_query_logger, DBGLVL_TRACE_BASIC,
.arg(LeaseQueryImpl6::leaseQueryLabel(query))
.arg(ex.what());
+ handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
+ if (sending) {
+ return (0);
+ }
+ if (!invalid) {
+ StatsMgr::instance().addValue("pkt6-processing-failed",
+ static_cast<int64_t>(1));
+ }
StatsMgr::instance().addValue("pkt6-receive-drop",
static_cast<int64_t>(1));
- handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
return (0);
}
///
/// @param base_query lease query to process. (Implementations
/// must use dynamic_casting).
- virtual void processQuery(isc::dhcp::PktPtr base_query) const = 0;
+ /// @param invalid Reference to a flag set to true when the query
+ /// is invalid (used to detect unexpected exceptions).
+ /// @param sending Reference to a flag set to true when the query was
+ /// processed and response will be built and sent.
+ virtual void processQuery(isc::dhcp::PktPtr base_query,
+ bool& invalid, bool& sending) const = 0;
/// @brief Keywords for Lease Query configuration.
static const isc::data::SimpleKeywords LEASE_QUERY_KEYWORDS;
};
void
-LeaseQueryImpl4::processQuery(PktPtr base_query) const {
+LeaseQueryImpl4::processQuery(PktPtr base_query, bool& invalid,
+ bool& sending) const {
Pkt4Ptr query = boost::dynamic_pointer_cast<Pkt4>(base_query);
if (!query) {
// Shouldn't happen.
/// - Validates query content
IOAddress requester_ip = query->getGiaddr();
if (requester_ip.isV4Zero()) {
+ invalid = true;
isc_throw(BadValue, "giaddr cannot be 0.0.0.0");
}
if (!isRequester(requester_ip)) {
+ invalid = true;
StatsMgr::instance().addValue("pkt4-admin-filtered",
static_cast<int64_t>(1));
isc_throw(BadValue, "rejecting query from unauthorized requester: "
OptionPtr client_server_id;
if (!acceptServerId(query, client_server_id)) {
+ invalid = true;
isc_throw(BadValue, "rejecting query from: "
<< requester_ip.toText() << ", unknown server-id: "
<< (client_server_id ? client_server_id->toText() : "malformed"));
break;
default:
// We have some combination of the three which is invalid.
+ invalid = true;
isc_throw(BadValue, "malformed lease query: "
<< "ciaddr: [" << ciaddr
<< "] HWAddr: [" << hwaddr->toText()
<< "]");
}
+ sending = true;
Pkt4Ptr response = buildResponse(response_type, query, leases);
/// Send the response if we have one
if (response) {
/// - Sends the reply
///
/// @param base_query DHCPv4 lease query to process.
- virtual void processQuery(dhcp::PktPtr base_query) const;
+ /// @param invalid Reference to a flag set to true when the query
+ /// is invalid (used to detect unexpected exceptions).
+ /// @param sending Reference to a flag set to true when the query was
+ /// processed and response will be built and sent.
+ virtual void processQuery(isc::dhcp::PktPtr base_query,
+ bool& invalid, bool& sending) const;
/// @brief Queries for an active lease matching an ip address
///
}
void
-LeaseQueryImpl6::processQuery(PktPtr base_query) const {
+LeaseQueryImpl6::processQuery(PktPtr base_query, bool& invalid,
+ bool& sending) const {
Pkt6Ptr query = boost::dynamic_pointer_cast<Pkt6>(base_query);
if (!query) {
// Shouldn't happen.
// Ensure there is a client id
DuidPtr req_clientid = query->getClientId();
if (!req_clientid) {
+ invalid = true;
isc_throw(BadValue, "DHCPV6_LEASEQUERY must supply a D6O_CLIENTID");
}
// If client sent a server-id, validate it.
- testServerId(query);
+ try {
+ testServerId(query);
+ } catch (const BadValue&) {
+ invalid = true;
+ throw;
+ }
// Validates query content using the source address.
IOAddress requester_ip = query->getRemoteAddr();
if (requester_ip.isV6Zero()) {
/// Not sure this really possible.
+ invalid = true;
isc_throw(BadValue, "DHCPV6_LEASEQUERY source address cannot be ::");
}
if (!isRequester(requester_ip)) {
// RFC 5007 says we may discard or return STATUS_NotAllowed
+ invalid = true;
StatsMgr::instance().addValue("pkt6-admin-filtered",
static_cast<int64_t>(1));
isc_throw(BadValue,
OptionCustomPtr lq_option = boost::dynamic_pointer_cast<OptionCustom>
(query->getOption(D6O_LQ_QUERY));
if (!lq_option) {
+ invalid = true;
isc_throw(BadValue, "DHCPV6_LEASEQUERY must supply a D6O_LQ_QUERY option");
}
query_link_addr = lq_option->readAddress(1);
} catch (const std::exception& ex) {
// unpack() should catch this?
+ invalid = true;
isc_throw(BadValue, "error reading query field(s):" << ex.what());
}
}
// Construct the reply.
+ sending = true;
Pkt6Ptr reply = buildReply(status_opt, query, leases);
if (reply) {
sendResponse(reply);
/// - Sends the reply
///
/// @param base_query DHCPv6 lease query to process.
+ /// @param invalid Reference to a flag set to true when the query
+ /// is invalid (used to detect unexpected exceptions).
+ /// @param sending Reference to a flag set to true when the query was
+ /// processed and response will be built and sent.
/// @throw BadValue if the query is invalid for a number reasons,
/// including if it comes from an unauthorized requester.
- virtual void processQuery(dhcp::PktPtr base_query) const;
+ virtual void processQuery(isc::dhcp::PktPtr base_query,
+ bool& invalid, bool& sending) const;
/// @brief Queries for an active lease matching an ip address.
///
// A v6 packet should get tossed.
Pkt6Ptr pkt6(new Pkt6(DHCPV6_LEASEQUERY, 0));
- ASSERT_THROW_MSG(impl->processQuery(pkt6), BadValue,
+ bool invalid = false;
+ bool sending = false;
+ ASSERT_THROW_MSG(impl->processQuery(pkt6, invalid, sending), BadValue,
"LeaseQueryImpl4 query is not DHCPv4 packet");
+ EXPECT_FALSE(invalid);
+ EXPECT_FALSE(sending);
// An empty giaddr should fail.
Pkt4Ptr lq(new Pkt4(DHCPLEASEQUERY, 123));
- ASSERT_THROW_MSG(impl->processQuery(lq), BadValue,
+ invalid = false;
+ sending = false;
+ ASSERT_THROW_MSG(impl->processQuery(lq, invalid, sending), BadValue,
"giaddr cannot be 0.0.0.0");
+ EXPECT_TRUE(invalid);
+ EXPECT_FALSE(sending);
// Set the pkt4-admin-filtered stat to 0.
StatsMgr::instance().setValue("pkt4-admin-filtered", static_cast<int64_t>(0));
// An unknown giaddr should fail.
lq->setGiaddr(IOAddress("192.0.2.2"));
- ASSERT_THROW_MSG(impl->processQuery(lq), BadValue,
+ invalid = false;
+ sending = false;
+ ASSERT_THROW_MSG(impl->processQuery(lq, invalid, sending), BadValue,
"rejecting query from unauthorized requester: 192.0.2.2");
+ EXPECT_TRUE(invalid);
+ EXPECT_FALSE(sending);
// Check the stat which was bumped by one.
ObservationPtr stat = StatsMgr::instance().getObservation("pkt4-admin-filtered");
lq->addOption(client_id);
}
- ASSERT_THROW_MSG(impl->processQuery(lq), BadValue, scenario.exp_message_);
+ invalid = false;
+ sending = false;
+ ASSERT_THROW_MSG(impl->processQuery(lq, invalid, sending), BadValue,
+ scenario.exp_message_);
+ EXPECT_TRUE(invalid);
+ EXPECT_FALSE(sending);
}
}
// A v4 packet should get tossed.
Pkt4Ptr pkt4(new Pkt4(DHCPLEASEQUERY, 0));
- ASSERT_THROW_MSG(impl->processQuery(pkt4), BadValue,
+ bool invalid = false;
+ bool sending = false;
+ ASSERT_THROW_MSG(impl->processQuery(pkt4, invalid, sending), BadValue,
"LeaseQueryImpl6 query is not DHCPv6 packet");
+ EXPECT_FALSE(invalid);
+ EXPECT_FALSE(sending);
// No client-id option should fail.
Pkt6Ptr lq(new Pkt6(DHCPV6_LEASEQUERY_REPLY, 123));
- ASSERT_THROW_MSG(impl->processQuery(lq), BadValue,
+ invalid = false;
+ sending = false;
+ ASSERT_THROW_MSG(impl->processQuery(lq, invalid, sending), BadValue,
"DHCPV6_LEASEQUERY must supply a D6O_CLIENTID");
+ EXPECT_TRUE(invalid);
+ EXPECT_FALSE(sending);
// Add a client-id option.
lq->addOption(makeClientIdOption(std::vector<uint8_t>{ 01, 02, 03, 04, 05, 06}));
// Add an a non-matching server id.
lq->addOption(makeServerIdOption(std::vector<uint8_t>{ 10, 11, 12, 13, 14, 15, 16 }));
- ASSERT_THROW_MSG(impl->processQuery(lq), BadValue,
+ invalid = false;
+ sending = false;
+ ASSERT_THROW_MSG(impl->processQuery(lq, invalid, sending), BadValue,
"rejecting DHCPV6_LEASEQUERY from: ::,"
" unknown server-id: type=00002, len=00007: 0a:0b:0c:0d:0e:0f:10");
+ EXPECT_TRUE(invalid);
+ EXPECT_FALSE(sending);
// Add a matching server id.
lq->delOption(D6O_SERVERID);
lq->addOption(makeServerIdOption(server_id_->getDuid()));
// Source address cannot be ::.
- ASSERT_THROW_MSG(impl->processQuery(lq), BadValue,
+ invalid = false;
+ sending = false;
+ ASSERT_THROW_MSG(impl->processQuery(lq, invalid, sending), BadValue,
"DHCPV6_LEASEQUERY source address cannot be ::");
+ EXPECT_TRUE(invalid);
+ EXPECT_FALSE(sending);
// Set the pkt6-admin-filtered stat to 0.
StatsMgr::instance().setValue("pkt6-admin-filtered", static_cast<int64_t>(0));
lq->setRemoteAddr(IOAddress("de:ad:be:ef::"));
// An unknown requester should fail.
- ASSERT_THROW_MSG(impl->processQuery(lq), BadValue,
+ invalid = false;
+ sending = false;
+ ASSERT_THROW_MSG(impl->processQuery(lq, invalid, sending), BadValue,
"rejecting DHCPV6_LEASEQUERY from unauthorized requester: de:ad:be:ef::");
+ EXPECT_TRUE(invalid);
+ EXPECT_FALSE(sending);
// Check the stat which was bumped by one.
ObservationPtr stat = StatsMgr::instance().getObservation("pkt6-admin-filtered");
lq->setRemoteAddr(IOAddress("2001:db8:2::1"));
// A query without a D6O_LQ_QUERY option should fail.
- ASSERT_THROW_MSG(impl->processQuery(lq), BadValue,
+ invalid = false;
+ sending = false;
+ ASSERT_THROW_MSG(impl->processQuery(lq, invalid, sending), BadValue,
"DHCPV6_LEASEQUERY must supply a D6O_LQ_QUERY option");
+ EXPECT_TRUE(invalid);
+ EXPECT_FALSE(sending);
}
// Verifies the operation of LeaseQueryImpl6::initReply().
Pkt6Ptr lq = makeLeaseQuery(scenario.qry_type_, scenario.qry_iaaddr_,
scenario.qry_cid_);
// Process the query.
- ASSERT_NO_THROW_LOG(impl->processQuery(lq));
+ bool invalid = false;
+ bool sending = false;
+ ASSERT_NO_THROW_LOG(impl->processQuery(lq, invalid, sending));
+ EXPECT_FALSE(invalid);
+ EXPECT_TRUE(sending);
// We should have generated a LEASE_QUERY_REPLY with a
// status option containing the expected status.
Pkt6Ptr lq = makeQueryByIpAddress(scenario.qry_iaaddr_);
// Process the query.
- ASSERT_NO_THROW_LOG(impl->processQuery(lq));
+ bool invalid = false;
+ bool sending = false;
+ ASSERT_NO_THROW_LOG(impl->processQuery(lq, invalid, sending));
+ EXPECT_FALSE(invalid);
+ EXPECT_TRUE(sending);
// We should have generated a DHCPV6_LEASEQUERY_REPLY with a
// status option containing the expected status.
Pkt6Ptr lq = makeQueryByIpAddress(active_lease->addr_);
// Process the query.
- ASSERT_NO_THROW_LOG(impl->processQuery(lq));
+ bool invalid = false;
+ bool sending = false;
+ ASSERT_NO_THROW_LOG(impl->processQuery(lq, invalid, sending));
+ EXPECT_FALSE(invalid);
+ EXPECT_TRUE(sending);
// We should have generated a DHCPV6_LEASEQUERY_REPLY with a
// status option containing the successful status.
Pkt6Ptr lq = makeQueryByClientId(cid1_);
// Process the query.
- ASSERT_NO_THROW_LOG(impl->processQuery(lq));
+ bool invalid = false;
+ bool sending = false;
+ ASSERT_NO_THROW_LOG(impl->processQuery(lq, invalid, sending));
+ EXPECT_FALSE(invalid);
+ EXPECT_TRUE(sending);
// We should have generated a LEASE_QUERY_REPLY with a
// status option containing the expected status.
Pkt6Ptr lq = makeQueryByClientId(cid1_);
// Process the query.
- ASSERT_NO_THROW_LOG(impl->processQuery(lq));
+ bool invalid = false;
+ bool sending = false;
+ ASSERT_NO_THROW_LOG(impl->processQuery(lq, invalid, sending));
+ EXPECT_FALSE(invalid);
+ EXPECT_TRUE(sending);
// We should have generated a LEASE_QUERY_REPLY with a
// status option containing the expected status.
Pkt6Ptr lq = makeQueryByClientId(cid1_);
// Process the query.
- ASSERT_NO_THROW_LOG(impl->processQuery(lq));
+ bool invalid = false;
+ bool sending = false;
+ ASSERT_NO_THROW_LOG(impl->processQuery(lq, invalid, sending));
+ EXPECT_FALSE(invalid);
+ EXPECT_TRUE(sending);
// We should have generated a LEASE_QUERY_REPLY with a
// status option containing the expected status.
}
// Process the query.
- ASSERT_NO_THROW_LOG(impl->processQuery(lq));
+ bool invalid = false;
+ bool sending = false;
+ ASSERT_NO_THROW_LOG(impl->processQuery(lq, invalid, sending));
+ EXPECT_FALSE(invalid);
+ EXPECT_TRUE(sending);
// We should have generated a LEASE_QUERY_REPLY with a
// status option containing the expected status.