Commit ee888857 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[3035] Process Hostname option sent by a client.

parent fc2b2f8f
......@@ -809,7 +809,7 @@ Dhcpv4Srv::processClientFqdnOption(const Option4ClientFqdnPtr& fqdn,
// one.
if (fqdn->getDomainNameType() == Option4ClientFqdn::PARTIAL) {
std::ostringstream name;
if (fqdn->getDomainName().empty()) {
if (fqdn->getDomainName().empty() || FQDN_REPLACE_CLIENT_NAME) {
name << FQDN_GENERATED_PARTIAL_NAME;
} else {
name << fqdn->getDomainName();
......@@ -843,12 +843,43 @@ Dhcpv4Srv::processClientFqdnOption(const Option4ClientFqdnPtr& fqdn,
void
Dhcpv4Srv::processHostnameOption(const OptionCustomPtr& opt_hostname,
Pkt4Ptr& answer) {
// Do nothing if the DNS updates are disabled.
if (!FQDN_ENABLE_UPDATE) {
return;
}
std::string hostname = opt_hostname->readString();
answer->addOption(OptionCustomPtr(new OptionCustom(*opt_hostname)));
unsigned int label_count = OptionDataTypeUtil::getLabelCount(hostname);
// Copy construct the hostname provided by the client. It is entirely
// possible that we will use the hostname option provided by the client
// to perform the DNS update and we will send the same option to him to
// indicate that we accepted this hostname.
OptionCustomPtr opt_hostname_resp(new OptionCustom(*opt_hostname));
// The hostname option may be unqualified or fully qualified. The lab_count
// holds the number of labels for the name. The number of 1 means that
// there is only root label "." (even for unqualified names, as the
// getLabelCount function treats each name as a fully qualified one).
// By checking the number of labels present in the hostname we may infer
// whether client has sent the fully qualified or unqualified hostname.
// If there is only one label, it is a root. We will have to generate
// the whole domain name for the client.
if (FQDN_REPLACE_CLIENT_NAME || (label_count < 2)) {
std::ostringstream resp_hostname;
resp_hostname << FQDN_GENERATED_PARTIAL_NAME << "."
<< FQDN_PARTIAL_SUFFIX << ".";
opt_hostname_resp->writeString(resp_hostname.str());
// If there are two labels, it means that the client has specified
// the unqualified name. We have to concatenate the unqalified name
// with the domain name.
} else if (label_count == 2) {
std::ostringstream resp_hostname;
resp_hostname << hostname << "." << FQDN_PARTIAL_SUFFIX << ".";
opt_hostname_resp->writeString(resp_hostname.str());
}
answer->addOption(opt_hostname_resp);
}
void
......@@ -997,6 +1028,16 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
hostname = fqdn->getDomainName();
fqdn_fwd = fqdn->getFlag(Option4ClientFqdn::FLAG_S);
fqdn_rev = !fqdn->getFlag(Option4ClientFqdn::FLAG_N);
} else {
OptionCustomPtr opt_hostname = boost::dynamic_pointer_cast<
OptionCustom>(answer->getOption(DHO_HOST_NAME));
if (opt_hostname) {
hostname = opt_hostname->readString();
// @todo It could be configurable what sort of updates the server
// is doing when Hostname option was sent.
fqdn_fwd = true;
fqdn_rev = true;
}
}
// Use allocation engine to pick a lease for this client. Allocation engine
......
......@@ -362,6 +362,13 @@ TEST_F(NameDhcpv4SrvTest, serverUpdateForwardPartialNameFqdn) {
}
// Test that server generates the fully qualified domain name for the client
// if client supplies the unqualified name in the Hostname option.
TEST_F(NameDhcpv4SrvTest, serverUpdateUnqualifiedHostname) {
Pkt4Ptr query = generatePktWithHostname(DHCPREQUEST, "myhost");
testProcessHostname(query, "myhost.example.com.");
}
// Test that server generates the fully qualified domain name for the client
// if clietn supplies empty domain name.
TEST_F(NameDhcpv4SrvTest, serverUpdateForwardNoNameFqdn) {
......@@ -522,7 +529,7 @@ TEST_F(NameDhcpv4SrvTest, processDiscover) {
// 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.
TEST_F(NameDhcpv4SrvTest, processTwoRequests) {
TEST_F(NameDhcpv4SrvTest, processTwoRequestsFqdn) {
Pkt4Ptr req1 = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_S |
Option4ClientFqdn::FLAG_E,
"myhost.example.com.",
......@@ -570,6 +577,52 @@ TEST_F(NameDhcpv4SrvTest, processTwoRequests) {
0, subnet_->getValid());
}
// Test that client may send two requests, each carrying Hostname option with
// a different name. Server should use existing lease for the second request
// but modify the DNS entries for the lease according to the contents of the
// Hostname sent in the second request.
TEST_F(NameDhcpv4SrvTest, processTwoRequestsHostname) {
Pkt4Ptr req1 = generatePktWithHostname(DHCPREQUEST, "myhost.example.com.");
Pkt4Ptr reply;
ASSERT_NO_THROW(reply = srv_->processRequest(req1));
checkResponse(reply, DHCPACK, 1234);
// Verify that there is one NameChangeRequest generated.
ASSERT_EQ(1, srv_->name_change_reqs_.size());
verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
reply->getYiaddr().toText(), "myhost.example.com.",
"00010132E91AA355CFBB753C0F0497A5A940436"
"965B68B6D438D98E680BF10B09F3BCF",
0, subnet_->getValid());
// Create another Request message but with a different Hostname. Server
// should generate two NameChangeRequests: one to remove existing entry,
// another one to add new entry with updated domain-name.
Pkt4Ptr req2 = generatePktWithHostname(DHCPREQUEST, "otherhost");
ASSERT_NO_THROW(reply = srv_->processRequest(req2));
checkResponse(reply, DHCPACK, 1234);
// There should be two NameChangeRequests. Verify that they are valid.
ASSERT_EQ(2, srv_->name_change_reqs_.size());
verifyNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, true, true,
reply->getYiaddr().toText(),
"myhost.example.com.",
"00010132E91AA355CFBB753C0F0497A5A940436"
"965B68B6D438D98E680BF10B09F3BCF",
0, subnet_->getValid());
verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true,
reply->getYiaddr().toText(),
"otherhost.example.com.",
"000101A5AEEA7498BD5AD9D3BF600E49FF39A7E3"
"AFDCE8C3D0E53F35CC584DD63C89CA",
0, subnet_->getValid());
}
// Test that when the Release message is sent for the previously acquired
// lease, then server genenerates a NameChangeRequest to remove the entries
// corresponding to the lease being released.
......
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