}
if (create_ncr_check) {
+ // Context flags are normally set during lease allocation. Since that
+ // hasn't occurred we'll set them here to match the expected values.
// Call createNameChangeRequests
- ASSERT_NO_THROW(srv_->createNameChangeRequests(answer));
+ ctx.fwd_dns_update_ = exp_fwd.value_;
+ ctx.rev_dns_update_ = exp_rev.value_;
+ ASSERT_NO_THROW(srv_->createNameChangeRequests(answer, ctx));
if (exp_fwd.value_ || exp_rev.value_) {
// Should have created 1 NCR.
NameChangeRequestPtr ncr;
TEST_F(FqdnDhcpv6SrvTest, createNameChangeRequestsNoAnswer) {
Pkt6Ptr answer;
- EXPECT_THROW(srv_->createNameChangeRequests(answer),
+ AllocEngine::ClientContext6 ctx;
+ ctx.fwd_dns_update_ = ctx.rev_dns_update_ = true;
+ EXPECT_THROW(srv_->createNameChangeRequests(answer, ctx),
isc::Unexpected);
}
Option6ClientFqdn::FULL);
answer->addOption(fqdn);
- EXPECT_THROW(srv_->createNameChangeRequests(answer), isc::Unexpected);
+ AllocEngine::ClientContext6 ctx;
+ ctx.fwd_dns_update_ = ctx.rev_dns_update_ = true;
+ EXPECT_THROW(srv_->createNameChangeRequests(answer, ctx), isc::Unexpected);
}
// Create Reply message with Client Id and Server id.
Pkt6Ptr answer = generateMessageWithIds(DHCPV6_REPLY);
- ASSERT_NO_THROW(srv_->createNameChangeRequests(answer));
+ AllocEngine::ClientContext6 ctx;
+ ctx.fwd_dns_update_ = ctx.rev_dns_update_ = true;
+ ASSERT_NO_THROW(srv_->createNameChangeRequests(answer, ctx));
// There should be no new NameChangeRequests.
ASSERT_EQ(0, d2_mgr_.getQueueSize());
"myhost.example.com",
Option6ClientFqdn::FULL);
answer->addOption(fqdn);
-
- ASSERT_NO_THROW(srv_->createNameChangeRequests(answer));
+ AllocEngine::ClientContext6 ctx;
+ ctx.fwd_dns_update_ = ctx.rev_dns_update_ = true;
+ ASSERT_NO_THROW(srv_->createNameChangeRequests(answer, ctx));
// We didn't add any IAs, so there should be no NameChangeRequests in the
// queue.
}
// Test that exactly one NameChangeRequest is created as a result of processing
-// the answer message which holds 3 IAs and when FQDN is specified.
+// the answer message which holds 3 IAs and when FQDN is specified. We also
+// verify that the context flags, fwd_dns_update_ and rev_dns_update_, gate
+// whether or not a NameChangeRequest is created.
TEST_F(FqdnDhcpv6SrvTest, createNameChangeRequests) {
// Create Reply message with Client Id and Server id.
Pkt6Ptr answer = generateMessageWithIds(DHCPV6_REPLY);
answer->addOption(fqdn);
// Create NameChangeRequest for the first allocated address.
- ASSERT_NO_THROW(srv_->createNameChangeRequests(answer));
+ AllocEngine::ClientContext6 ctx;
+ ctx.fwd_dns_update_ = ctx.rev_dns_update_ = true;
+ ASSERT_NO_THROW(srv_->createNameChangeRequests(answer, ctx));
ASSERT_EQ(1, d2_mgr_.getQueueSize());
// Verify that NameChangeRequest is correct.
"FAAAA3EBD29826B5C907B2C9268A6F52",
0, 500);
+ // If context flags are false we should not create the NCR.
+ ctx.fwd_dns_update_ = ctx.rev_dns_update_ = false;
+ ASSERT_NO_THROW(srv_->createNameChangeRequests(answer, ctx));
+ ASSERT_EQ(0, d2_mgr_.getQueueSize());
+
+ // If only the forward flag is true, we create the NCR.
+ ctx.fwd_dns_update_ = true;
+ ASSERT_NO_THROW(srv_->createNameChangeRequests(answer, ctx));
+ // Verify that NameChangeRequest is correct.
+ verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
+ "2001:db8:1::1",
+ "000201415AA33D1187D148275136FA30300478"
+ "FAAAA3EBD29826B5C907B2C9268A6F52",
+ 0, 500);
+ ASSERT_EQ(0, d2_mgr_.getQueueSize());
+
+ // If only the reverse flag is true, we create the NCR.
+ ctx.fwd_dns_update_ = false;
+ ctx.rev_dns_update_ = true;
+ ASSERT_NO_THROW(srv_->createNameChangeRequests(answer, ctx));
+ // Verify that NameChangeRequest is correct.
+ verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
+ "2001:db8:1::1",
+ "000201415AA33D1187D148275136FA30300478"
+ "FAAAA3EBD29826B5C907B2C9268A6F52",
+ 0, 500);
}
// Checks that NameChangeRequests to add entries are not
answer->addOption(fqdn);
// An attempt to send a NCR would throw.
- ASSERT_NO_THROW(srv_->createNameChangeRequests(answer));
+ AllocEngine::ClientContext6 ctx;
+ ctx.fwd_dns_update_ = ctx.rev_dns_update_ = true;
+ ASSERT_NO_THROW(srv_->createNameChangeRequests(answer, ctx));
}
-
// Test creation of the NameChangeRequest to remove both forward and reverse
// mapping for the given lease.
TEST_F(FqdnDhcpv6SrvTest, createRemovalNameChangeRequestFwdRev) {
// a different domain-name. Server should use existing lease for the second
// request but modify the DNS entries for the lease according to the contents
// of the FQDN sent in the second request.
-/// @todo: Fix will be available on trac3677
-TEST_F(FqdnDhcpv6SrvTest, DISABLED_processTwoRequests) {
+TEST_F(FqdnDhcpv6SrvTest, processTwoRequestsDiffFqdn) {
// Create a Request message with FQDN option and generate server's
// response using processRequest function. This will result in the
// creation of a new lease and the appropriate NameChangeRequest
// to add both reverse and forward mapping to DNS.
testProcessMessage(DHCPV6_REQUEST, "myhost.example.com",
"myhost.example.com.");
+
+ // The lease should have been recorded in the database.
+ lease_ = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ IOAddress("2001:db8:1:1::dead:beef"));
+ ASSERT_TRUE(lease_);
+
ASSERT_EQ(1, d2_mgr_.getQueueSize());
verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
"2001:db8:1:1::dead:beef",
"000201415AA33D1187D148275136FA30300478"
"FAAAA3EBD29826B5C907B2C9268A6F52",
- lease_->cltt_ + lease_->valid_lft_, 4000);
+ 0, 4000);
+
// Client may send another request message with a new domain-name. In this
// case the same lease will be returned. The existing DNS entry needs to
"2001:db8:1:1::dead:beef",
"000201415AA33D1187D148275136FA30300478"
"FAAAA3EBD29826B5C907B2C9268A6F52",
- 0, 4000);
+ lease_->cltt_ + lease_->valid_lft_, 4000);
verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
"2001:db8:1:1::dead:beef",
"000201D422AA463306223D269B6CB7AFE7AAD265FC"
}
+// Test that client may send two requests, each carrying FQDN option with
+// the same domain-name. Server should use existing lease for the second
+// request and not modify the DNS entries.
+TEST_F(FqdnDhcpv6SrvTest, processTwoRequestsSameFqdn) {
+ // Create a Request message with FQDN option and generate server's
+ // response using processRequest function. This will result in the
+ // creation of a new lease and the appropriate NameChangeRequest
+ // to add both reverse and forward mapping to DNS.
+ testProcessMessage(DHCPV6_REQUEST, "myhost.example.com",
+ "myhost.example.com.");
+
+ // The lease should have been recorded in the database.
+ lease_ = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ IOAddress("2001:db8:1:1::dead:beef"));
+ ASSERT_TRUE(lease_);
+
+ ASSERT_EQ(1, d2_mgr_.getQueueSize());
+ verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
+ "2001:db8:1:1::dead:beef",
+ "000201415AA33D1187D148275136FA30300478"
+ "FAAAA3EBD29826B5C907B2C9268A6F52",
+ 0, 4000);
+
+
+ // Client may send another request message with a same domain-name. In this
+ // case the same lease will be returned. The existing DNS entry should be
+ // left alone, so we expect no NameChangeRequests queued..
+ testProcessMessage(DHCPV6_REQUEST, "myhost.example.com",
+ "myhost.example.com.");
+ ASSERT_EQ(0, d2_mgr_.getQueueSize());
+}
+
// Test that NameChangeRequest is not generated when Solicit message is sent.
// The Solicit is here sent after a lease has been allocated for a client.
// The Solicit conveys a different hostname which would trigger updates to
// DNS entry added previously when Request was processed, another one to
// add a new entry for the FQDN held in the Renew.
/// @todo: Fix will be available on trac3677
-TEST_F(FqdnDhcpv6SrvTest, DISABLED_processRequestRenew) {
+TEST_F(FqdnDhcpv6SrvTest, processRequestRenewDiffFqdn) {
// Create a Request message with FQDN option and generate server's
// response using processRequest function. This will result in the
// creation of a new lease and the appropriate NameChangeRequest
// to add both reverse and forward mapping to DNS.
testProcessMessage(DHCPV6_REQUEST, "myhost.example.com",
"myhost.example.com.");
+ // The lease should have been recorded in the database.
+ lease_ = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ IOAddress("2001:db8:1:1::dead:beef"));
+ ASSERT_TRUE(lease_);
+
ASSERT_EQ(1, d2_mgr_.getQueueSize());
verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
"2001:db8:1:1::dead:beef",
"2001:db8:1:1::dead:beef",
"000201415AA33D1187D148275136FA30300478"
"FAAAA3EBD29826B5C907B2C9268A6F52",
- 0, 4000);
+ lease_->cltt_ + lease_->valid_lft_, 4000);
verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
"2001:db8:1:1::dead:beef",
"000201D422AA463306223D269B6CB7AFE7AAD265FC"
}
+// Test that client may send Request followed by the Renew, both holding
+// FQDN options, but each option holding different domain-name. The Renew
+// should result in generation of the two NameChangeRequests, one to remove
+// DNS entry added previously when Request was processed, another one to
+// add a new entry for the FQDN held in the Renew.
+TEST_F(FqdnDhcpv6SrvTest, processRequestRenewSameFqdn) {
+ // Create a Request message with FQDN option and generate server's
+ // response using processRequest function. This will result in the
+ // creation of a new lease and the appropriate NameChangeRequest
+ // to add both reverse and forward mapping to DNS.
+ testProcessMessage(DHCPV6_REQUEST, "myhost.example.com",
+ "myhost.example.com.");
+ ASSERT_EQ(1, d2_mgr_.getQueueSize());
+ verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
+ "2001:db8:1:1::dead:beef",
+ "000201415AA33D1187D148275136FA30300478"
+ "FAAAA3EBD29826B5C907B2C9268A6F52",
+ 0, 4000);
+
+ ASSERT_EQ(0, d2_mgr_.getQueueSize());
+
+ // Client may send Renew message with a same domain-name. In this
+ // case the same lease will be returned. No DNS updates should be
+ // required, so the NCR queue should be empty.
+ testProcessMessage(DHCPV6_RENEW, "myhost.example.com",
+ "myhost.example.com.");
+ ASSERT_EQ(0, d2_mgr_.getQueueSize());
+}
+
TEST_F(FqdnDhcpv6SrvTest, processRequestRelease) {
// Create a Request message with FQDN option and generate server's
// response using processRequest function. This will result in the
*ctx.duid_,
ctx.currentIA().iaid_,
ctx.subnet_->getID());
-
// Now do the checks:
// Case 1. if there are no leases, and there are reservations...
// 1.1. are the reserved addresses are used by someone else?
if (old_data->expired()) {
reclaimExpiredLease(old_data, ctx.callout_handle_);
- } else if (!lease->hasIdenticalFqdn(*old_data)) {
- // We're not reclaiming the lease but since the FQDN has changed
- // we have to at least send NCR.
- queueNCR(CHG_REMOVE, old_data);
+ } else {
+ if (!lease->hasIdenticalFqdn(*old_data)) {
+ // We're not reclaiming the lease but since the FQDN has changed
+ // we have to at least send NCR.
+ queueNCR(CHG_REMOVE, old_data);
+ } else {
+ // Callers should use the context flags to drive whether or
+ // not we do an update, not the lease flags. Changing those
+ // would alter the flags in the database, which we want to
+ // preserve them as they were were when the lease was created.
+ ctx.fwd_dns_update_ = false;
+ ctx.rev_dns_update_ = false;
+ }
}
// Now that the lease has been reclaimed, we can go ahead and update it
// in the lease database.
Lease6Collection
AllocEngine::updateLeaseData(ClientContext6& ctx, const Lease6Collection& leases) {
Lease6Collection updated_leases;
+ bool remove_queued = false;
for (Lease6Collection::const_iterator lease_it = leases.begin();
lease_it != leases.end(); ++lease_it) {
Lease6Ptr lease(new Lease6(**lease_it));
lease->fqdn_fwd_ = ctx.fwd_dns_update_;
lease->fqdn_rev_ = ctx.rev_dns_update_;
lease->hostname_ = ctx.hostname_;
- if (!ctx.fake_allocation_ &&
- (conditionalExtendLifetime(*lease) ||
- (lease->fqdn_fwd_ != (*lease_it)->fqdn_fwd_) ||
- (lease->fqdn_rev_ != (*lease_it)->fqdn_rev_) ||
- (lease->hostname_ != (*lease_it)->hostname_))) {
- ctx.currentIA().changed_leases_.push_back(*lease_it);
- LeaseMgrFactory::instance().updateLease6(lease);
+ if (!ctx.fake_allocation_) {
+ bool fqdn_changed = ((lease->type_ != Lease::TYPE_PD) &&
+ !(lease->hasIdenticalFqdn(**lease_it)));
+
+ if (conditionalExtendLifetime(*lease) || fqdn_changed) {
+ ctx.currentIA().changed_leases_.push_back(*lease_it);
+ LeaseMgrFactory::instance().updateLease6(lease);
+
+ // If the FQDN differs, remove existing DNS entries.
+ // We only need one remove.
+ if (fqdn_changed && !remove_queued) {
+ queueNCR(CHG_REMOVE, *lease_it);
+ remove_queued = true;
+ }
+ }
}
+
updated_leases.push_back(lease);
}
+
+ // If we didn't do a remove, then the FQDN is unchanged so this amounts
+ // to renew. Note this assumes this method is only called when client
+ // issues a request, rather than a renew or rebind.
+ if (!remove_queued) {
+ ctx.fwd_dns_update_ = false;
+ ctx.rev_dns_update_ = false;
+ }
+
return (updated_leases);
}