]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5277] Extended server-hostname and boot-file-name (native for subnet4, else inherited)
authorFrancis Dupont <fdupont@isc.org>
Sun, 1 Oct 2017 21:20:38 +0000 (23:20 +0200)
committerFrancis Dupont <fdupont@isc.org>
Sun, 1 Oct 2017 21:20:38 +0000 (23:20 +0200)
17 files changed:
doc/examples/kea4/shared-network.json
doc/guide/dhcp4-srv.xml
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/json_config_parser.cc
src/bin/dhcp4/tests/config_parser_unittest.cc
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dora_unittest.cc
src/bin/dhcp4/tests/get_config_unittest.cc
src/bin/dhcp4/tests/inform_unittest.cc
src/lib/dhcpsrv/parsers/dhcp_parsers.cc
src/lib/dhcpsrv/parsers/simple_parser4.cc
src/lib/dhcpsrv/subnet.cc
src/lib/dhcpsrv/subnet.h
src/lib/dhcpsrv/tests/cfg_subnets4_unittest.cc
src/lib/dhcpsrv/tests/shared_network_parser_unittest.cc
src/lib/dhcpsrv/tests/shared_network_unittest.cc
src/lib/dhcpsrv/tests/subnet_unittest.cc

index be3babc7a0b7462f7953d96d0bc1785294d02047..14eceb8db9967fb2d9da057a5deb97f536264642 100644 (file)
@@ -72,6 +72,8 @@
                     "id": 1,
                     "match-client-id": true,
                     "next-server": "0.0.0.0",
+                    "server-hostname": "",
+                    "boot-file-name": "",
                     "option-data": [ ],
                     "pools": [ ],
                     "rebind-timer": 20,
@@ -91,6 +93,8 @@
                     "id": 2,
                     "match-client-id": true,
                     "next-server": "0.0.0.0",
+                    "server-hostname": "",
+                    "boot-file-name": "",
                     "option-data": [ ],
                     "pools": [ ],
                     "rebind-timer": 20,
index a4c450c60467691e101507b78c1cf42fa05a56e4..e794d00c8b1e5f39954371483c584e8ae77c630f 100644 (file)
@@ -2591,14 +2591,24 @@ It is merely echoed by the server
       not be sent. It may also be set to an empty string, which means the same as if
       it was not defined at all, i.e. use the global value.
       </para>
+      <para>
+      The <command>server-hostname</command> (that conveys a server hostname,
+      can be up to 64 bytes long and will be sent in the sname field) and
+      <command>boot-file-name</command> (that conveys the configuration file,
+      can be up to 128 bytes long and will be sent using file field)
+      directives are handled the same way than <command>next-server</command>.
+      </para>
 
 <screen>
 "Dhcp4": {
-    <userinput>"next-server": "192.0.2.123"</userinput>,
+    <userinput>"next-server": "192.0.2.123",
+    "boot-file-name": "/dev/null"</userinput>,
     ...,
     "subnet4": [
         {
-            <userinput>"next-server": "192.0.2.234"</userinput>,
+            <userinput>"next-server": "192.0.2.234",
+            "server-hostname": "some-name.example.org",
+            "boot-file-name": "bootfile.efi"</userinput>,
             ...
         }
     ]
index 602bf5efc89198875825672e4374a9665e752b05..323918ba0c820164ad3e1cd449c0d5fea41dc561 100644 (file)
@@ -2165,6 +2165,28 @@ Dhcpv4Srv::setFixedFields(Dhcpv4Exchange& ex) {
         if (!subnet_next_server.isV4Zero()) {
             response->setSiaddr(subnet_next_server);
         }
+
+        const string& sname = subnet->getSname();
+        if (!sname.empty()) {
+            // Converting string to (const uint8_t*, size_t len) format is
+            // tricky. reinterpret_cast is not the most elegant solution,
+            // but it does avoid us making unnecessary copy. We will convert
+            // sname and file fields in Pkt4 to string one day and life
+            // will be easier.
+            response->setSname(reinterpret_cast<const uint8_t*>(sname.c_str()),
+                               sname.size());
+        }
+
+        const string& filename = subnet->getFilename();
+        if (!filename.empty()) {
+            // Converting string to (const uint8_t*, size_t len) format is
+            // tricky. reinterpret_cast is not the most elegant solution,
+            // but it does avoid us making unnecessary copy. We will convert
+            // sname and file fields in Pkt4 to string one day and life
+            // will be easier.
+            response->setFile(reinterpret_cast<const uint8_t*>(filename.c_str()),
+                              filename.size());
+        }
     }
 
     // Step 2: Try to set the values based on classes.
index b2e0704ea2d67aaee7a7358c8d4cf305c26f933e..31ce8ec87bf510c00257afdb8c0e6ef4d50d8f7a 100644 (file)
@@ -455,7 +455,9 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set,
                  (config_pair.first == "dhcp4o6-port") ||
                  (config_pair.first == "echo-client-id") ||
                  (config_pair.first == "match-client-id") ||
-                 (config_pair.first == "next-server")) {
+                 (config_pair.first == "next-server") ||
+                 (config_pair.first == "server-hostname") ||
+                 (config_pair.first == "boot-file-name")) {
                 continue;
             }
 
index 6ac125b3ef5107270d6c539554b711e2a5dda15f..0cb062d8679c7dca19f4fa0bf536670a0a6ab200 100644 (file)
@@ -1106,14 +1106,16 @@ TEST_F(Dhcp4ParserTest, reconfigureRemoveSubnet) {
 
 /// @todo: implement subnet removal test as part of #3281.
 
-// Checks if the next-server defined as global parameter is taken into
-// consideration.
+// Checks if the next-server and other fixed BOOTP fields defined as
+// global parameter are taken into consideration.
 TEST_F(Dhcp4ParserTest, nextServerGlobal) {
 
     string config = "{ " + genIfaceConfig() + "," +
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"next-server\": \"1.2.3.4\", "
+        "\"server-hostname\": \"foo\", "
+        "\"boot-file-name\": \"bar\", "
         "\"subnet4\": [ { "
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"subnet\": \"192.0.2.0/24\" } ],"
@@ -1135,10 +1137,12 @@ TEST_F(Dhcp4ParserTest, nextServerGlobal) {
         getCfgSubnets4()->selectSubnet(IOAddress("192.0.2.200"));
     ASSERT_TRUE(subnet);
     EXPECT_EQ("1.2.3.4", subnet->getSiaddr().toText());
+    EXPECT_EQ("foo", subnet->getSname());
+    EXPECT_EQ("bar", subnet->getFilename());
 }
 
-// Checks if the next-server defined as subnet parameter is taken into
-// consideration.
+// Checks if the next-server and other fixed BOOTP fields defined as
+// subnet parameter are taken into consideration.
 TEST_F(Dhcp4ParserTest, nextServerSubnet) {
 
     string config = "{ " + genIfaceConfig() + "," +
@@ -1147,6 +1151,8 @@ TEST_F(Dhcp4ParserTest, nextServerSubnet) {
         "\"subnet4\": [ { "
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"next-server\": \"1.2.3.4\", "
+        "    \"server-hostname\": \"foo\", "
+        "    \"boot-file-name\": \"bar\", "
         "    \"subnet\": \"192.0.2.0/24\" } ],"
         "\"valid-lifetime\": 4000 }";
 
@@ -1166,6 +1172,8 @@ TEST_F(Dhcp4ParserTest, nextServerSubnet) {
         getCfgSubnets4()->selectSubnet(IOAddress("192.0.2.200"));
     ASSERT_TRUE(subnet);
     EXPECT_EQ("1.2.3.4", subnet->getSiaddr().toText());
+    EXPECT_EQ("foo", subnet->getSname());
+    EXPECT_EQ("bar", subnet->getFilename());
 }
 
 // Test checks several negative scenarios for next-server configuration: bogus
@@ -1209,12 +1217,43 @@ TEST_F(Dhcp4ParserTest, nextServerNegative) {
         "    \"subnet\": \"192.0.2.0/24\" } ],"
         "\"valid-lifetime\": 4000 }";
 
+    // Config with too large server-hostname
+    string bigsname(Pkt4::MAX_SNAME_LEN + 1, ' ');
+    string config_bogus4 = "{ " + genIfaceConfig() + "," +
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet4\": [ { "
+        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+        "    \"rebind-timer\": 2000, "
+        "    \"renew-timer\": 1000, "
+        "    \"server-hostname\": \"" + bigsname + "\", " +
+        "    \"subnet\": \"192.0.2.0/24\" } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    // Config with too large boot-file-hostname
+    string bigfilename(Pkt4::MAX_FILE_LEN + 1, ' ');
+    string config_bogus5 = "{ " + genIfaceConfig() + "," +
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet4\": [ { "
+        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+        "    \"rebind-timer\": 2000, "
+        "    \"renew-timer\": 1000, "
+        "    \"boot-file-name\": \"" + bigfilename + "\", " +
+        "    \"subnet\": \"192.0.2.0/24\" } ],"
+        "\"valid-lifetime\": 4000 }";
+
+
     ConstElementPtr json1;
     ASSERT_NO_THROW(json1 = parseDHCP4(config_bogus1));
     ConstElementPtr json2;
     ASSERT_NO_THROW(json2 = parseDHCP4(config_bogus2));
     ConstElementPtr json3;
     ASSERT_NO_THROW(json3 = parseDHCP4(config_bogus3));
+    ConstElementPtr json4;
+    ASSERT_NO_THROW(json4 = parseDHCP4(config_bogus4));
+    ConstElementPtr json5;
+    ASSERT_NO_THROW(json5 = parseDHCP4(config_bogus5));
 
     // check if returned status is always a failure
     ConstElementPtr status;
@@ -1233,6 +1272,18 @@ TEST_F(Dhcp4ParserTest, nextServerNegative) {
     EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json3));
     checkResult(status, 0);
     EXPECT_FALSE(errorContainsPosition(status, "<string>"));
+
+    CfgMgr::instance().clear();
+
+    EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json4));
+    checkResult(status, 1);
+    EXPECT_TRUE(errorContainsPosition(status, "<string>"));
+
+    CfgMgr::instance().clear();
+
+    EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json5));
+    checkResult(status, 1);
+    EXPECT_TRUE(errorContainsPosition(status, "<string>"));
 }
 
 // Checks if the next-server defined as global value is overridden by subnet
@@ -1243,9 +1294,13 @@ TEST_F(Dhcp4ParserTest, nextServerOverride) {
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"next-server\": \"192.0.0.1\", "
+        "\"server-hostname\": \"nohost\","
+        "\"boot-file-name\": \"nofile\","        
         "\"subnet4\": [ { "
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"next-server\": \"1.2.3.4\", "
+        "    \"server-hostname\": \"some-name.example.org\","
+        "    \"boot-file-name\": \"bootfile.efi\","
         "    \"subnet\": \"192.0.2.0/24\" } ],"
         "\"valid-lifetime\": 4000 }";
 
@@ -1265,6 +1320,8 @@ TEST_F(Dhcp4ParserTest, nextServerOverride) {
         getCfgSubnets4()->selectSubnet(IOAddress("192.0.2.200"));
     ASSERT_TRUE(subnet);
     EXPECT_EQ("1.2.3.4", subnet->getSiaddr().toText());
+    EXPECT_EQ("some-name.example.org", subnet->getSname());
+    EXPECT_EQ("bootfile.efi", subnet->getFilename());
 }
 
 // Check whether it is possible to configure echo-client-id
@@ -5229,6 +5286,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
         "    \"interface\": \"eth0\",\n"
         "    \"match-client-id\": false,\n"
         "    \"next-server\": \"1.2.3.4\",\n"
+        "    \"server-hostname\": \"foo\",\n"
+        "    \"boot-file-name\": \"bar\",\n"
         "    \"relay\": {\n"
         "        \"ip-address\": \"5.6.7.8\"\n"
         "    },\n"
@@ -5249,6 +5308,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
         "        \"valid-lifetime\": 400,\n"
         "        \"match-client-id\": true,\n"
         "        \"next-server\": \"11.22.33.44\",\n"
+        "        \"server-hostname\": \"some-name.example.org\",\n"
+        "        \"boot-file-name\": \"bootfile.efi\",\n"
         "        \"relay\": {\n"
         "            \"ip-address\": \"55.66.77.88\"\n"
         "        },\n"
@@ -5299,6 +5360,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
     EXPECT_EQ("eth0", s->getIface());
     EXPECT_EQ(false, s->getMatchClientId());
     EXPECT_EQ(IOAddress("1.2.3.4"), s->getSiaddr());
+    EXPECT_EQ("foo", s->getSname());
+    EXPECT_EQ("bar", s->getFilename());
     EXPECT_EQ(IOAddress("5.6.7.8"), s->getRelayInfo().addr_);
     EXPECT_EQ(Network::HR_OUT_OF_POOL, s->getHostReservationMode());
 
@@ -5312,6 +5375,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
     EXPECT_EQ("eth0", s->getIface());
     EXPECT_EQ(true, s->getMatchClientId());
     EXPECT_EQ(IOAddress("11.22.33.44"), s->getSiaddr());
+    EXPECT_EQ("some-name.example.org", s->getSname());
+    EXPECT_EQ("bootfile.efi", s->getFilename());
     EXPECT_EQ(IOAddress("55.66.77.88"), s->getRelayInfo().addr_);
     EXPECT_EQ(Network::HR_DISABLED, s->getHostReservationMode());
 
@@ -5329,6 +5394,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
     EXPECT_EQ("", s->getIface());
     EXPECT_EQ(true, s->getMatchClientId());
     EXPECT_EQ(IOAddress("0.0.0.0"), s->getSiaddr());
+    EXPECT_TRUE(s->getSname().empty());
+    EXPECT_TRUE(s->getFilename().empty());
     EXPECT_EQ(IOAddress("0.0.0.0"), s->getRelayInfo().addr_);
     EXPECT_EQ(Network::HR_ALL, s->getHostReservationMode());
 }
index 85897604b15ebcc9468b281655fbf4b66dd4e581..3871288170c9213602b8ea6e681b2a8a8b1ba6e1 100644 (file)
@@ -1255,7 +1255,7 @@ TEST_F(Dhcpv4SrvTest, siaddr) {
 // Checks if the next-server defined as global value is overridden by subnet
 // specific value and returned in server messages. There's also similar test for
 // checking parser only configuration, see Dhcp4ParserTest.nextServerOverride in
-// config_parser_unittest.cc.
+// config_parser_unittest.cc. This test was extended to other BOOTP fixed fields.
 TEST_F(Dhcpv4SrvTest, nextServerOverride) {
     IfaceMgrTestConfig test_config(true);
     IfaceMgr::instance().openSockets4();
@@ -1270,9 +1270,13 @@ TEST_F(Dhcpv4SrvTest, nextServerOverride) {
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"next-server\": \"192.0.0.1\", "
+        "\"server-hostname\": \"nohost\", "
+        "\"boot-file-name\": \"nofile\", "
         "\"subnet4\": [ { "
         "    \"pools\": [ { \"pool\":  \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"next-server\": \"1.2.3.4\", "
+        "    \"server-hostname\": \"some-name.example.org\", "
+        "    \"boot-file-name\": \"bootfile.efi\", "
         "    \"subnet\": \"192.0.2.0/24\" } ],"
         "\"valid-lifetime\": 4000 }";
 
@@ -1300,6 +1304,16 @@ TEST_F(Dhcpv4SrvTest, nextServerOverride) {
     EXPECT_EQ(DHCPOFFER, offer->getType());
 
     EXPECT_EQ("1.2.3.4", offer->getSiaddr().toText());
+    std::string sname("some-name.example.org");
+    uint8_t sname_buf[Pkt4::MAX_SNAME_LEN];
+    std::memset(sname_buf, 0, Pkt4::MAX_SNAME_LEN);
+    std::memcpy(sname_buf, sname.c_str(), sname.size());
+    EXPECT_EQ(0, std::memcmp(sname_buf, &offer->getSname()[0], Pkt4::MAX_SNAME_LEN));
+    std::string filename("bootfile.efi");
+    uint8_t filename_buf[Pkt4::MAX_FILE_LEN];
+    std::memset(filename_buf, 0, Pkt4::MAX_FILE_LEN);
+    std::memcpy(filename_buf, filename.c_str(), filename.size());
+    EXPECT_EQ(0, std::memcmp(filename_buf, &offer->getFile()[0], Pkt4::MAX_FILE_LEN));
 }
 
 // Checks if the next-server defined as global value is used in responses
@@ -1320,6 +1334,8 @@ TEST_F(Dhcpv4SrvTest, nextServerGlobal) {
         "\"rebind-timer\": 2000, "
         "\"renew-timer\": 1000, "
         "\"next-server\": \"192.0.0.1\", "
+        "\"server-hostname\": \"some-name.example.org\", "
+        "\"boot-file-name\": \"bootfile.efi\", "
         "\"subnet4\": [ { "
         "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
         "    \"subnet\": \"192.0.2.0/24\" } ],"
@@ -1349,6 +1365,16 @@ TEST_F(Dhcpv4SrvTest, nextServerGlobal) {
     EXPECT_EQ(DHCPOFFER, offer->getType());
 
     EXPECT_EQ("192.0.0.1", offer->getSiaddr().toText());
+    std::string sname("some-name.example.org");
+    uint8_t sname_buf[Pkt4::MAX_SNAME_LEN];
+    std::memset(sname_buf, 0, Pkt4::MAX_SNAME_LEN);
+    std::memcpy(sname_buf, sname.c_str(), sname.size());
+    EXPECT_EQ(0, std::memcmp(sname_buf, &offer->getSname()[0], Pkt4::MAX_SNAME_LEN));
+    std::string filename("bootfile.efi");
+    uint8_t filename_buf[Pkt4::MAX_FILE_LEN];
+    std::memset(filename_buf, 0, Pkt4::MAX_FILE_LEN);
+    std::memcpy(filename_buf, filename.c_str(), filename.size());
+    EXPECT_EQ(0, std::memcmp(filename_buf, &offer->getFile()[0], Pkt4::MAX_FILE_LEN));
 }
 
 // Checks if server is able to handle a relayed traffic from DOCSIS3.0 modems
index f6a23c4f735466213617fb53eacfdad147fdcbf5..10261ce6dd996df5dd70f9cb35499babc6afde52 100644 (file)
@@ -267,6 +267,8 @@ const char* DORA_CONFIGS[] = {
         "},"
         "\"valid-lifetime\": 600,"
         "\"next-server\": \"10.0.0.1\","
+        "\"server-hostname\": \"nohost\","
+        "\"boot-file-name\": \"nofile\","
         "\"subnet4\": [ { "
         "    \"subnet\": \"10.0.0.0/24\", "
         "    \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],"
index 5c6cdb163534bfa40446c735476a92ce40355765..79a5e7aac529381fbfb1dddec03f066627d10e1d 100644 (file)
@@ -223,12 +223,14 @@ const char* EXTRACTED_CONFIGS[] = {
 "    }\n",
     // CONFIGURATION 6
 "{\n"
+"        \"boot-file-name\": \"bar\",\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "        },\n"
 "        \"next-server\": \"1.2.3.4\",\n"
 "        \"rebind-timer\": 2000,\n"
 "        \"renew-timer\": 1000,\n"
+"        \"server-hostname\": \"foo\",\n"
 "        \"subnet4\": [\n"
 "            {\n"
 "                \"pools\": [\n"
@@ -250,12 +252,14 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"subnet4\": [\n"
 "            {\n"
+"                \"boot-file-name\": \"bar\",\n"
 "                \"next-server\": \"1.2.3.4\",\n"
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"pool\": \"192.0.2.1 - 192.0.2.100\"\n"
 "                    }\n"
 "                ],\n"
+"                \"server-hostname\": \"foo\",\n"
 "                \"subnet\": \"192.0.2.0/24\"\n"
 "            }\n"
 "        ],\n"
@@ -263,20 +267,24 @@ const char* EXTRACTED_CONFIGS[] = {
 "    }\n",
     // CONFIGURATION 8
 "{\n"
+"        \"boot-file-name\": \"nofile\",\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "        },\n"
 "        \"next-server\": \"192.0.0.1\",\n"
 "        \"rebind-timer\": 2000,\n"
 "        \"renew-timer\": 1000,\n"
+"        \"server-hostname\": \"nohost\",\n"
 "        \"subnet4\": [\n"
 "            {\n"
+"                \"boot-file-name\": \"bootfile.efi\",\n"
 "                \"next-server\": \"1.2.3.4\",\n"
 "                \"pools\": [\n"
 "                    {\n"
 "                        \"pool\": \"192.0.2.1 - 192.0.2.100\"\n"
 "                    }\n"
 "                ],\n"
+"                \"server-hostname\": \"some-name.example.org\",\n"
 "                \"subnet\": \"192.0.2.0/24\"\n"
 "            }\n"
 "        ],\n"
@@ -1547,7 +1555,8 @@ const char* EXTRACTED_CONFIGS[] = {
 "            }\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
-"    }\n"};
+"    }\n"
+};
 
 /// @brief unparsed configurations
 const char* UNPARSED_CONFIGS[] = {
@@ -1640,6 +1649,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -1657,6 +1667,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 900,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -1708,6 +1719,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -1725,6 +1737,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -1776,6 +1789,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -1793,6 +1807,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -1844,6 +1859,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -1861,6 +1877,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -1868,6 +1885,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 2,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -1885,6 +1903,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -1892,6 +1911,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 3,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -1909,6 +1929,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.4.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -1916,6 +1937,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 4,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -1933,6 +1955,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.5.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -1984,6 +2007,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1024,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2001,6 +2025,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -2008,6 +2033,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 100,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2025,6 +2051,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -2032,6 +2059,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2049,6 +2077,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.4.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -2056,6 +2085,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 34,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2073,6 +2103,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.5.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -2124,6 +2155,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"bar\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"1.2.3.4\",\n"
@@ -2141,6 +2173,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"foo\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -2192,6 +2225,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"bar\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"1.2.3.4\",\n"
@@ -2209,6 +2243,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"foo\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -2260,6 +2295,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"bootfile.efi\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"1.2.3.4\",\n"
@@ -2277,6 +2313,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"some-name.example.org\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -2328,6 +2365,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2345,6 +2383,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -2396,6 +2435,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2413,6 +2453,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -2464,6 +2505,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2481,6 +2523,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -2488,6 +2531,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 2,\n"
 "                \"match-client-id\": false,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2505,6 +2549,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -2556,6 +2601,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": false,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2573,6 +2619,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -2580,6 +2627,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 2,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2597,6 +2645,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -2648,6 +2697,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2665,6 +2715,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4\n"
 "            }\n"
@@ -2716,6 +2767,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2737,6 +2789,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -2744,6 +2797,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 2,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2765,6 +2819,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -2816,6 +2871,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -2833,6 +2889,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -3281,6 +3338,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -3298,6 +3356,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -3349,6 +3408,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -3383,6 +3443,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -3461,6 +3522,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -3478,6 +3540,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -3661,6 +3724,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -3678,6 +3742,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 3000\n"
 "            }\n"
@@ -3738,6 +3803,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -3772,6 +3838,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -3823,6 +3890,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -3849,6 +3917,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -3856,6 +3925,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 2,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -3882,6 +3952,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -3933,6 +4004,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -3967,6 +4039,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -4018,6 +4091,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -4057,6 +4131,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -4231,6 +4306,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -4248,6 +4324,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 3000\n"
 "            }\n"
@@ -4314,6 +4391,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -4331,6 +4409,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -4401,6 +4480,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -4418,6 +4498,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -4555,6 +4636,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -4572,6 +4654,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -4623,6 +4706,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -4640,6 +4724,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4\n"
 "            }\n"
@@ -4691,6 +4776,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 123,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -4708,6 +4794,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -4715,6 +4802,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 234,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -4787,6 +4875,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                        \"server-hostname\": \"\"\n"
 "                    }\n"
 "                ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -4794,6 +4883,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 542,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -4859,6 +4949,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                        \"server-hostname\": \"\"\n"
 "                    }\n"
 "                ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.4.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -4920,6 +5011,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 234,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -4957,6 +5049,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                        \"server-hostname\": \"\"\n"
 "                    }\n"
 "                ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5008,6 +5101,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5025,6 +5119,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -5032,6 +5127,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 2,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5049,6 +5145,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"out-of-pool\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.3.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -5056,6 +5153,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 3,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5073,6 +5171,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"disabled\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.4.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            },\n"
@@ -5080,6 +5179,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 4,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5097,6 +5197,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.5.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5320,6 +5421,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5337,6 +5439,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5388,6 +5491,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"2001:db8::123/45\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5405,6 +5509,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5456,6 +5561,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"ethX\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5473,6 +5579,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5524,6 +5631,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"ethX\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"2001:db8::543/21\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5541,6 +5649,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5592,6 +5701,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"vlan123\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5609,6 +5719,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5686,6 +5797,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5703,6 +5815,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5754,6 +5867,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5771,6 +5885,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5822,6 +5937,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5840,6 +5956,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5891,6 +6008,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5913,6 +6031,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
@@ -5964,6 +6083,7 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"4o6-interface\": \"\",\n"
 "                \"4o6-interface-id\": \"\",\n"
 "                \"4o6-subnet\": \"\",\n"
+"                \"boot-file-name\": \"\",\n"
 "                \"id\": 1,\n"
 "                \"match-client-id\": true,\n"
 "                \"next-server\": \"0.0.0.0\",\n"
@@ -5986,11 +6106,13 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"renew-timer\": 1000,\n"
 "                \"reservation-mode\": \"all\",\n"
 "                \"reservations\": [ ],\n"
+"                \"server-hostname\": \"\",\n"
 "                \"subnet\": \"192.0.2.0/24\",\n"
 "                \"valid-lifetime\": 4000\n"
 "            }\n"
 "        ]\n"
-"    }\n"};
+"    }\n"
+};
 
 /// @brief the number of configurations
 const size_t max_config_counter = sizeof(EXTRACTED_CONFIGS) / sizeof(char*);
index b6c17b41bd105982772320e31b72a8cddf1095ce..42a5cfe31bcb73b05af6d6dd22781bb69c95ecfc 100644 (file)
@@ -109,6 +109,8 @@ const char* INFORM_CONFIGS[] = {
         "},"
         "\"valid-lifetime\": 600,"
         "\"next-server\": \"10.0.0.1\","
+        "\"server-hostname\": \"nohost\","
+        "\"server-hostname\": \"nofile\","
         "\"subnet4\": [ { "
         "    \"subnet\": \"192.0.2.0/24\", "
         "    \"reservations\": [ "
index cfb1dc78c362edf8bed4bbaf4ffe56059e3a1c43..393e1624ed30b5ce7977c2604ce6d9afc1284c2e 100644 (file)
@@ -708,6 +708,32 @@ Subnet4ConfigParser::initSubnet(data::ConstElementPtr params,
                   << next_server << "(" << pos << ")");
     }
 
+    // Set server-hostname.
+    std::string sname = getString(params, "server-hostname");
+    if (!sname.empty()) {
+        if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
+            ConstElementPtr error = params->get("server-hostname");
+            isc_throw(DhcpConfigError, "server-hostname must be at most "
+                      << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
+                      << sname.length() << " ("
+                      << error->getPosition() << ")");
+        }
+        subnet4->setSname(sname);
+    }
+
+    // Set boot-file-name.
+    std::string filename =getString(params, "boot-file-name");
+    if (!filename.empty()) {
+        if (filename.length() > Pkt4::MAX_FILE_LEN) {
+            ConstElementPtr error = params->get("boot-file-name");
+            isc_throw(DhcpConfigError, "boot-file-name must be at most "
+                      << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
+                      << filename.length() << " ("
+                      << error->getPosition() << ")");
+        }
+        subnet4->setFilename(filename);
+    }
+
     // Get interface name. If it is defined, then the subnet is available
     // directly over specified network interface.
     std::string iface = getString(params, "interface");
index a8c47891c8ddf77c6566ab969a8d39ce935de3e7..e766e96323690cfe7eeae25e039d3a389915d197 100644 (file)
@@ -63,7 +63,9 @@ const SimpleDefaults SimpleParser4::GLOBAL4_DEFAULTS = {
     { "dhcp4o6-port",             Element::integer, "0" },
     { "echo-client-id",           Element::boolean, "true" },
     { "match-client-id",          Element::boolean, "true" },
-    { "next-server",              Element::string,  "0.0.0.0" }
+    { "next-server",              Element::string,  "0.0.0.0" },
+    { "server-hostname",          Element::string,  "" },
+    { "boot-file-name",           Element::string,  "" }
 };
 
 /// @brief This table defines default values for each IPv4 subnet.
@@ -118,6 +120,7 @@ const SimpleDefaults SimpleParser4::IFACE4_DEFAULTS = {
 /// This list is also used for inheriting from global to shared networks
 /// and from shared networks to subnets within it.
 const ParamsList SimpleParser4::INHERIT_TO_SUBNET4 = {
+    "boot-file-name",
     "client-class",
     "interface",
     "match-client-id",
@@ -126,6 +129,7 @@ const ParamsList SimpleParser4::INHERIT_TO_SUBNET4 = {
     "relay",
     "renew-timer",
     "reservation-mode",
+    "server-hostname",
     "valid-lifetime"
 };
 
index e3808b4b5c1012ef4792195c8212a312ef7b5d25..837faed17171e0b03457af52ac56b3dd72ad5f21 100644 (file)
@@ -239,6 +239,21 @@ isc::asiolink::IOAddress Subnet4::getSiaddr() const {
     return (siaddr_);
 }
 
+void Subnet4::setSname(const std::string& sname) {
+    sname_ = sname;
+}
+
+const std::string& Subnet4::getSname() const {
+    return (sname_);
+}
+void Subnet4::setFilename(const std::string& filename) {
+    filename_ = filename;
+}
+
+const std::string& Subnet4::getFilename() const {
+    return (filename_);
+}
+
 const PoolCollection& Subnet::getPools(Lease::Type type) const {
     // check if the type is valid (and throw if it isn't)
     checkType(type);
@@ -574,6 +589,12 @@ Subnet4::toElement() const {
     // Set next-server
     map->set("next-server", Element::create(getSiaddr().toText()));
 
+    // Set server-hostname
+    map->set("server-hostname", Element::create(getSname()));
+
+    // Set boot-file-name
+    map->set("boot-file-name",Element::create(getFilename()));
+
     // Set pools
     const PoolCollection& pools = getPools(Lease::TYPE_V4);
     ElementPtr pool_list = Element::createList();
index 818f83cbc7802c29f6477215448ec73ef4f59f00..40d34a1cd4a6ec5c499ea1e6f9e58a8e3f062387 100644 (file)
@@ -457,6 +457,26 @@ public:
     /// @return siaddr value
     isc::asiolink::IOAddress getSiaddr() const;
 
+    /// @brief Sets server hostname for the Subnet4 
+    ///
+    /// Will be used for server hostname field (may be empty if not defined)
+    void setSname(const std::string& sname);
+
+    /// @brief Returns server hostname for this subnet
+    ///
+    /// @return server hostname value
+    const std::string& getSname() const;
+
+    /// @brief Sets boot file name for the Subnet4 
+    ///
+    /// Will be used for boot file name (may be empty if not defined)
+    void setFilename(const std::string& filename);
+
+    /// @brief Returns boot file name for this subnet
+    ///
+    /// @return boot file name value
+    const std::string& getFilename() const;
+
     /// @brief Returns DHCP4o6 configuration parameters.
     ///
     /// This structure is always available. If the 4o6 is not enabled, its
@@ -497,6 +517,12 @@ private:
     /// @brief siaddr value for this subnet
     isc::asiolink::IOAddress siaddr_;
 
+    /// @brief server hostname for this subnet
+    std::string sname_;
+
+    /// @brief boot file name for this subnet
+    std::string filename_;
+
     /// @brief All the information related to DHCP4o6
     Cfg4o6 dhcp4o6_;
 };
index a0664d24f461f1d05601718d1c2dadae2268f86a..91958fbb767785064a85de5ede24fe90cfeeae45 100644 (file)
@@ -748,6 +748,8 @@ TEST(CfgSubnets4Test, unparseSubnet) {
         "    \"relay\": { \"ip-address\": \"0.0.0.0\" },\n"
         "    \"match-client-id\": true,\n"
         "    \"next-server\": \"0.0.0.0\",\n"
+        "    \"server-hostname\": \"\",\n"
+        "    \"boot-file-name\": \"\",\n"
         "    \"renew-timer\": 1,\n"
         "    \"rebind-timer\": 2,\n"
         "    \"valid-lifetime\": 3,\n"
@@ -765,6 +767,8 @@ TEST(CfgSubnets4Test, unparseSubnet) {
         "    \"interface\": \"lo\",\n"
         "    \"match-client-id\": true,\n"
         "    \"next-server\": \"0.0.0.0\",\n"
+        "    \"server-hostname\": \"\",\n"
+        "    \"boot-file-name\": \"\",\n"
         "    \"renew-timer\": 1,\n"
         "    \"rebind-timer\": 2,\n"
         "    \"valid-lifetime\": 3,\n"
@@ -781,6 +785,8 @@ TEST(CfgSubnets4Test, unparseSubnet) {
         "    \"interface\": \"eth1\",\n"
         "    \"match-client-id\": true,\n"
         "    \"next-server\": \"0.0.0.0\",\n"
+        "    \"server-hostname\": \"\",\n"
+        "    \"boot-file-name\": \"\",\n"
         "    \"renew-timer\": 1,\n"
         "    \"rebind-timer\": 2,\n"
         "    \"valid-lifetime\": 3,\n"
@@ -815,6 +821,8 @@ TEST(CfgSubnets4Test, unparsePool) {
         "    \"relay\": { \"ip-address\": \"0.0.0.0\" },\n"
         "    \"match-client-id\": true,\n"
         "    \"next-server\": \"0.0.0.0\",\n"
+        "    \"server-hostname\": \"\",\n"
+        "    \"boot-file-name\": \"\",\n"
         "    \"renew-timer\": 1,\n"
         "    \"rebind-timer\": 2,\n"
         "    \"valid-lifetime\": 3,\n"
index d8cc6313f1806ff24b64b5682d779cc994028d11..03329f87e3819ebac36161a0d6558df224e51e1c 100644 (file)
@@ -49,6 +49,8 @@ public:
                 "            \"valid-lifetime\": 300,"
                 "            \"match-client-id\": false,"
                 "            \"next-server\": \"\","
+                "            \"server-hostname\": \"\","
+                "            \"boot-file-name\": \"\","
                 "            \"client-class\": \"\","
                 "            \"reservation-mode\": \"all\","
                 "            \"4o6-interface\": \"\","
@@ -67,6 +69,8 @@ public:
                 "            \"valid-lifetime\": 30,"
                 "            \"match-client-id\": false,"
                 "            \"next-server\": \"\","
+                "            \"server-hostname\": \"\","
+                "            \"boot-file-name\": \"\","
                 "            \"client-class\": \"\","
                 "            \"reservation-mode\": \"all\","
                 "            \"4o6-interface\": \"\","
index e9bcc7c6c4ea760e7ad044cff45a42ca3ced566b..30aedd054f0f3b273f66a06ae7ca250cc2ed859d 100644 (file)
@@ -222,6 +222,8 @@ TEST(SharedNetwork4Test, unparse) {
         "        \"id\": 1,\n"
         "        \"match-client-id\": true,\n"
         "        \"next-server\": \"0.0.0.0\",\n"
+        "        \"server-hostname\": \"\",\n"
+        "        \"boot-file-name\": \"\",\n"
         "        \"option-data\": [ ],\n"
         "        \"pools\": [ ],\n"
         "        \"rebind-timer\": 20,\n"
@@ -240,6 +242,8 @@ TEST(SharedNetwork4Test, unparse) {
         "        \"id\": 2,\n"
         "        \"match-client-id\": true,\n"
         "        \"next-server\": \"0.0.0.0\",\n"
+        "        \"server-hostname\": \"\",\n"
+        "        \"boot-file-name\": \"\",\n"
         "        \"option-data\": [ ],\n"
         "        \"pools\": [ ],\n"
         "        \"rebind-timer\": 20,\n"
index 8081d11c9a757701f21549678f2095f82cce38ba..34b5ddde30ad525ef8edd36f66d9ce0ef100facc 100644 (file)
@@ -110,6 +110,34 @@ TEST(Subnet4Test, siaddr) {
         BadValue);
 }
 
+// Checks whether server-hostname field can be set and retrieved correctly.
+TEST(Subnet4Test, serverHostname) {
+    Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
+
+    // Check if the default is empty
+    EXPECT_TRUE(subnet.getSname().empty());
+
+    // Check that we can set it up
+    EXPECT_NO_THROW(subnet.setSname("foobar"));
+
+    // Check that we can get it back
+    EXPECT_EQ("foobar", subnet.getSname());
+}
+
+// Checks whether boot-file-name field can be set and retrieved correctly.
+TEST(Subnet4Test, bootFileName) {
+    Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
+
+    // Check if the default is empty
+    EXPECT_TRUE(subnet.getFilename().empty());
+
+    // Check that we can set it up
+    EXPECT_NO_THROW(subnet.setFilename("foobar"));
+
+    // Check that we can get it back
+    EXPECT_EQ("foobar", subnet.getFilename());
+}
+
 // Checks if the match-client-id flag can be set and retrieved.
 TEST(Subnet4Test, matchClientId) {
     Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);