Browse Source

[5226] Addressed remaining missing options

Francis Dupont 7 years ago
parent
commit
aacc0c7e11

+ 3 - 0
doc/guide/dhcp4-srv.xml

@@ -1286,6 +1286,7 @@ This rather belong to the DDNS configuration
 <row><entry>streettalk-server</entry><entry>75</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>streettalk-server</entry><entry>75</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>streettalk-directory-assistance-server</entry><entry>76</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>streettalk-directory-assistance-server</entry><entry>76</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>user-class</entry><entry>77</entry><entry>binary</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>user-class</entry><entry>77</entry><entry>binary</entry><entry>false</entry><entry>false</entry></row>
+<row><entry>slp-directory-agent</entry><entry>78</entry><entry>record (boolean, ipv4-address)</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>slp-service-scope</entry><entry>79</entry><entry>record (boolean, string)</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>slp-service-scope</entry><entry>79</entry><entry>record (boolean, string)</entry><entry>false</entry><entry>false</entry></row>
 <!-- The Client FQDN option value is not explicitly configured.
 <!-- The Client FQDN option value is not explicitly configured.
 It is a part of the DDNS/D2 configuration
 It is a part of the DDNS/D2 configuration
@@ -1327,8 +1328,10 @@ It is merely echoed by the server
 <row><entry>v4-lost</entry><entry>137</entry><entry>fqdn</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>v4-lost</entry><entry>137</entry><entry>fqdn</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>capwap-ac-v4</entry><entry>138</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>capwap-ac-v4</entry><entry>138</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>sip-ua-cs-domains</entry><entry>142</entry><entry>fqdn</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>sip-ua-cs-domains</entry><entry>142</entry><entry>fqdn</entry><entry>true</entry><entry>false</entry></row>
+<row><entry>rdnss-selection</entry><entry>146</entry><entry>record (uint8, ipv4-address, ipv4-address, fqdn)</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>v4-portparams</entry><entry>159</entry><entry>record (uint8, uint8, uint16)</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>v4-portparams</entry><entry>159</entry><entry>record (uint8, uint8, uint16)</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>v4-captive-portal</entry><entry>160</entry><entry>string</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>v4-captive-portal</entry><entry>160</entry><entry>string</entry><entry>false</entry><entry>false</entry></row>
+<row><entry>option-6rd</entry><entry>212</entry><entry>record (uint8, uint8, ipv6-address, ipv4-address)</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>v4-access-domain</entry><entry>213</entry><entry>fqdn</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>v4-access-domain</entry><entry>213</entry><entry>fqdn</entry><entry>false</entry><entry>false</entry></row>
           </tbody>
           </tbody>
           </tgroup>
           </tgroup>

+ 1 - 0
doc/guide/dhcp6-srv.xml

@@ -1252,6 +1252,7 @@ temporarily override a list of interface names and listen on all interfaces.
 <row><entry>erp-local-domain-name</entry><entry>65</entry><entry>fqdn</entry><entry>false</entry></row>
 <row><entry>erp-local-domain-name</entry><entry>65</entry><entry>fqdn</entry><entry>false</entry></row>
 <row><entry>rsoo</entry><entry>66</entry><entry>empty</entry><entry>false</entry></row>
 <row><entry>rsoo</entry><entry>66</entry><entry>empty</entry><entry>false</entry></row>
 <row><entry>pd-exclude</entry><entry>67</entry><entry>binary</entry><entry>false</entry></row>
 <row><entry>pd-exclude</entry><entry>67</entry><entry>binary</entry><entry>false</entry></row>
+<row><entry>rdnss-selection</entry><entry>74</entry><entry>record (ipv6-address, uint8, fqdn)</entry><entry>true</entry></row>
 <row><entry>client-linklayer-addr</entry><entry>79</entry><entry>binary</entry><entry>false</entry></row>
 <row><entry>client-linklayer-addr</entry><entry>79</entry><entry>binary</entry><entry>false</entry></row>
 <row><entry>link-address</entry><entry>80</entry><entry>ipv6-address</entry><entry>false</entry></row>
 <row><entry>link-address</entry><entry>80</entry><entry>ipv6-address</entry><entry>false</entry></row>
 <row><entry>solmax-rt</entry><entry>82</entry><entry>uint32</entry><entry>false</entry></row>
 <row><entry>solmax-rt</entry><entry>82</entry><entry>uint32</entry><entry>false</entry></row>

+ 60 - 0
src/bin/dhcp4/tests/config_parser_unittest.cc

@@ -3120,6 +3120,66 @@ TEST_F(Dhcp4ParserTest, domainSearchOption) {
                                      " domain-search option"));
                                      " domain-search option"));
 }
 }
 
 
+// The goal of this test is to verify that the slp-directory-agent
+// option can be set using a trailing array of addresses and
+// slp-service-scope without option scope list
+TEST_F(Dhcp4ParserTest, slpOptions) {
+    ConstElementPtr x;
+    string config = "{ " + genIfaceConfig() + "," +
+        "\"rebind-timer\": 2000,"
+        "\"renew-timer\": 1000,"
+        "\"option-data\": [ {"
+        "    \"name\": \"slp-directory-agent\","
+        "    \"data\": \"true, 10.0.0.3, 127.0.0.1\""
+        " },"
+        " {"
+        "    \"name\": \"slp-service-scope\","
+        "    \"data\": \"false, \""
+        " } ],"
+        "\"subnet4\": [ { "
+        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+        "    \"subnet\": \"192.0.2.0/24\""
+        " } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ConstElementPtr json;
+    ASSERT_NO_THROW(json = parseDHCP4(config, true));
+    extractConfig(config);
+
+    EXPECT_NO_THROW(x = configureDhcp4Server(*srv_, json));
+    checkResult(x, 0);
+
+    // Get options
+    OptionContainerPtr options = CfgMgr::instance().getStagingCfg()->
+        getCfgOption()->getAll(DHCP4_OPTION_SPACE);
+    ASSERT_EQ(2, options->size());
+
+    // Get the search index. Index #1 is to search using option code.
+    const OptionContainerTypeIndex& idx = options->get<1>();
+
+    // Get the options for specified index. Expecting one option to be
+    // returned but in theory we may have multiple options with the same
+    // code so we get the range.
+    std::pair<OptionContainerTypeIndex::const_iterator,
+              OptionContainerTypeIndex::const_iterator> range =
+        idx.equal_range(DHO_DIRECTORY_AGENT);
+    // Expect a single option with the code equal to 78.
+    ASSERT_EQ(1, std::distance(range.first, range.second));
+    const uint8_t sda_expected[] = {
+        0x01, 0x0a, 0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x01
+    };
+    // Check if option is valid in terms of code and carried data.
+    testOption(*range.first, 78, sda_expected, sizeof(sda_expected));
+
+    range = idx.equal_range(DHO_SERVICE_SCOPE);
+    ASSERT_EQ(1, std::distance(range.first, range.second));
+    // Do another round of testing with second option.
+    const uint8_t sss_expected[] = {
+        0x00
+    };
+    testOption(*range.first, 79, sss_expected, sizeof(sss_expected));
+}
+
 // The goal of this test is to verify that the standard option can
 // The goal of this test is to verify that the standard option can
 // be configured to encapsulate multiple other options.
 // be configured to encapsulate multiple other options.
 TEST_F(Dhcp4ParserTest, stdOptionDataEncapsulate) {
 TEST_F(Dhcp4ParserTest, stdOptionDataEncapsulate) {

+ 160 - 48
src/bin/dhcp4/tests/get_config_unittest.cc

@@ -885,6 +885,35 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        },\n"
 "        \"option-data\": [\n"
 "        \"option-data\": [\n"
 "            {\n"
 "            {\n"
+"                \"data\": \"true, 10.0.0.3, 127.0.0.1\",\n"
+"                \"name\": \"slp-directory-agent\"\n"
+"            },\n"
+"            {\n"
+"                \"data\": \"false, \",\n"
+"                \"name\": \"slp-service-scope\"\n"
+"            }\n"
+"        ],\n"
+"        \"rebind-timer\": 2000,\n"
+"        \"renew-timer\": 1000,\n"
+"        \"subnet4\": [\n"
+"            {\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"pool\": \"192.0.2.1 - 192.0.2.100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"subnet\": \"192.0.2.0/24\"\n"
+"            }\n"
+"        ],\n"
+"        \"valid-lifetime\": 4000\n"
+"    }\n",
+    // CONFIGURATION 33
+"{\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ]\n"
+"        },\n"
+"        \"option-data\": [\n"
+"            {\n"
 "                \"data\": \"1234\",\n"
 "                \"data\": \"1234\",\n"
 "                \"name\": \"foo\",\n"
 "                \"name\": \"foo\",\n"
 "                \"space\": \"vendor-encapsulated-options-space\"\n"
 "                \"space\": \"vendor-encapsulated-options-space\"\n"
@@ -913,7 +942,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 33
+    // CONFIGURATION 34
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -964,7 +993,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 3000\n"
 "        \"valid-lifetime\": 3000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 34
+    // CONFIGURATION 35
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -999,7 +1028,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 35
+    // CONFIGURATION 36
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1034,7 +1063,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 36
+    // CONFIGURATION 37
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"eth0\", \"eth1\" ]\n"
 "            \"interfaces\": [ \"eth0\", \"eth1\" ]\n"
@@ -1043,7 +1072,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 37
+    // CONFIGURATION 38
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"eth0\", \"*\", \"eth1\" ]\n"
 "            \"interfaces\": [ \"eth0\", \"*\", \"eth1\" ]\n"
@@ -1052,7 +1081,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        \"renew-timer\": 1000,\n"
 "        \"renew-timer\": 1000,\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 38
+    // CONFIGURATION 39
 "{\n"
 "{\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
 "            \"always-include-fqdn\": true,\n"
 "            \"always-include-fqdn\": true,\n"
@@ -1087,7 +1116,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 39
+    // CONFIGURATION 40
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1112,7 +1141,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 40
+    // CONFIGURATION 41
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1210,7 +1239,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 41
+    // CONFIGURATION 42
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1251,7 +1280,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 42
+    // CONFIGURATION 43
 "{\n"
 "{\n"
 "        \"rebind-timer\": 2000,\n"
 "        \"rebind-timer\": 2000,\n"
 "        \"renew-timer\": 1000,\n"
 "        \"renew-timer\": 1000,\n"
@@ -1294,21 +1323,21 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 43
+    // CONFIGURATION 44
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "        },\n"
 "        },\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 44
+    // CONFIGURATION 45
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "        },\n"
 "        },\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 45
+    // CONFIGURATION 46
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 12345,\n"
 "        \"decline-probation-period\": 12345,\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
@@ -1316,7 +1345,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        },\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 46
+    // CONFIGURATION 47
 "{\n"
 "{\n"
 "        \"expired-leases-processing\": {\n"
 "        \"expired-leases-processing\": {\n"
 "            \"flush-reclaimed-timer-wait-time\": 35,\n"
 "            \"flush-reclaimed-timer-wait-time\": 35,\n"
@@ -1331,7 +1360,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        },\n"
 "        },\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 47
+    // CONFIGURATION 48
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1350,7 +1379,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 48
+    // CONFIGURATION 49
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1370,7 +1399,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 49
+    // CONFIGURATION 50
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1390,7 +1419,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 50
+    // CONFIGURATION 51
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1411,7 +1440,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 51
+    // CONFIGURATION 52
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1431,7 +1460,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 52
+    // CONFIGURATION 53
 "{\n"
 "{\n"
 "        \"client-classes\": [\n"
 "        \"client-classes\": [\n"
 "            {\n"
 "            {\n"
@@ -1461,7 +1490,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 53
+    // CONFIGURATION 54
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1480,7 +1509,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 54
+    // CONFIGURATION 55
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1500,7 +1529,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 55
+    // CONFIGURATION 56
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -1524,7 +1553,7 @@ const char* EXTRACTED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"valid-lifetime\": 4000\n"
 "        \"valid-lifetime\": 4000\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 56
+    // CONFIGURATION 57
 "{\n"
 "{\n"
 "        \"interfaces-config\": {\n"
 "        \"interfaces-config\": {\n"
 "            \"interfaces\": [ \"*\" ]\n"
 "            \"interfaces\": [ \"*\" ]\n"
@@ -4084,6 +4113,89 @@ const char* UNPARSED_CONFIGS[] = {
 "        },\n"
 "        },\n"
 "        \"option-data\": [\n"
 "        \"option-data\": [\n"
 "            {\n"
 "            {\n"
+"                \"code\": 78,\n"
+"                \"csv-format\": true,\n"
+"                \"data\": \"true, 10.0.0.3, 127.0.0.1\",\n"
+"                \"name\": \"slp-directory-agent\",\n"
+"                \"space\": \"dhcp4\"\n"
+"            },\n"
+"            {\n"
+"                \"code\": 79,\n"
+"                \"csv-format\": true,\n"
+"                \"data\": \"false, \",\n"
+"                \"name\": \"slp-service-scope\",\n"
+"                \"space\": \"dhcp4\"\n"
+"            }\n"
+"        ],\n"
+"        \"option-def\": [ ],\n"
+"        \"subnet4\": [\n"
+"            {\n"
+"                \"4o6-interface\": \"\",\n"
+"                \"4o6-interface-id\": \"\",\n"
+"                \"4o6-subnet\": \"\",\n"
+"                \"id\": 1,\n"
+"                \"interface\": \"\",\n"
+"                \"match-client-id\": true,\n"
+"                \"next-server\": \"0.0.0.0\",\n"
+"                \"option-data\": [ ],\n"
+"                \"pools\": [\n"
+"                    {\n"
+"                        \"option-data\": [ ],\n"
+"                        \"pool\": \"192.0.2.1-192.0.2.100\"\n"
+"                    }\n"
+"                ],\n"
+"                \"rebind-timer\": 2000,\n"
+"                \"relay\": {\n"
+"                    \"ip-address\": \"0.0.0.0\"\n"
+"                },\n"
+"                \"renew-timer\": 1000,\n"
+"                \"reservation-mode\": \"all\",\n"
+"                \"reservations\": [ ],\n"
+"                \"subnet\": \"192.0.2.0/24\",\n"
+"                \"valid-lifetime\": 4000\n"
+"            }\n"
+"        ]\n"
+"    }\n",
+    // CONFIGURATION 33
+"{\n"
+"        \"decline-probation-period\": 86400,\n"
+"        \"dhcp-ddns\": {\n"
+"            \"always-include-fqdn\": false,\n"
+"            \"enable-updates\": false,\n"
+"            \"generated-prefix\": \"myhost\",\n"
+"            \"max-queue-size\": 1024,\n"
+"            \"ncr-format\": \"JSON\",\n"
+"            \"ncr-protocol\": \"UDP\",\n"
+"            \"override-client-update\": false,\n"
+"            \"override-no-update\": false,\n"
+"            \"qualifying-suffix\": \"\",\n"
+"            \"replace-client-name\": \"never\",\n"
+"            \"sender-ip\": \"0.0.0.0\",\n"
+"            \"sender-port\": 0,\n"
+"            \"server-ip\": \"127.0.0.1\",\n"
+"            \"server-port\": 53001\n"
+"        },\n"
+"        \"dhcp4o6-port\": 0,\n"
+"        \"echo-client-id\": true,\n"
+"        \"expired-leases-processing\": {\n"
+"            \"flush-reclaimed-timer-wait-time\": 25,\n"
+"            \"hold-reclaimed-time\": 3600,\n"
+"            \"max-reclaim-leases\": 100,\n"
+"            \"max-reclaim-time\": 250,\n"
+"            \"reclaim-timer-wait-time\": 10,\n"
+"            \"unwarned-reclaim-cycles\": 5\n"
+"        },\n"
+"        \"hooks-libraries\": [ ],\n"
+"        \"host-reservation-identifiers\": [ \"hw-address\", \"duid\", \"circuit-id\", \"client-id\" ],\n"
+"        \"interfaces-config\": {\n"
+"            \"interfaces\": [ \"*\" ],\n"
+"            \"re-detect\": false\n"
+"        },\n"
+"        \"lease-database\": {\n"
+"            \"type\": \"memfile\"\n"
+"        },\n"
+"        \"option-data\": [\n"
+"            {\n"
 "                \"code\": 1,\n"
 "                \"code\": 1,\n"
 "                \"csv-format\": true,\n"
 "                \"csv-format\": true,\n"
 "                \"data\": \"1234\",\n"
 "                \"data\": \"1234\",\n"
@@ -4120,7 +4232,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        ],\n"
 "        ],\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 33
+    // CONFIGURATION 34
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -4229,7 +4341,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 34
+    // CONFIGURATION 35
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -4310,7 +4422,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 35
+    // CONFIGURATION 36
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -4396,7 +4508,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 36
+    // CONFIGURATION 37
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -4438,7 +4550,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"option-def\": [ ],\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 37
+    // CONFIGURATION 38
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -4480,7 +4592,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"option-def\": [ ],\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 38
+    // CONFIGURATION 39
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -4548,7 +4660,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 39
+    // CONFIGURATION 40
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -4616,7 +4728,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 40
+    // CONFIGURATION 41
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -4831,7 +4943,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 41
+    // CONFIGURATION 42
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -4928,7 +5040,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 42
+    // CONFIGURATION 43
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5071,7 +5183,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 43
+    // CONFIGURATION 44
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5113,7 +5225,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"option-def\": [ ],\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 44
+    // CONFIGURATION 45
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5155,7 +5267,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"option-def\": [ ],\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 45
+    // CONFIGURATION 46
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 12345,\n"
 "        \"decline-probation-period\": 12345,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5197,7 +5309,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"option-def\": [ ],\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 46
+    // CONFIGURATION 47
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5239,7 +5351,7 @@ const char* UNPARSED_CONFIGS[] = {
 "        \"option-def\": [ ],\n"
 "        \"option-def\": [ ],\n"
 "        \"subnet4\": [ ]\n"
 "        \"subnet4\": [ ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 47
+    // CONFIGURATION 48
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5307,7 +5419,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 48
+    // CONFIGURATION 49
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5375,7 +5487,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 49
+    // CONFIGURATION 50
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5443,7 +5555,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 50
+    // CONFIGURATION 51
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5511,7 +5623,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 51
+    // CONFIGURATION 52
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5579,7 +5691,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 52
+    // CONFIGURATION 53
 "{\n"
 "{\n"
 "        \"client-classes\": [\n"
 "        \"client-classes\": [\n"
 "            {\n"
 "            {\n"
@@ -5670,7 +5782,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 53
+    // CONFIGURATION 54
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5738,7 +5850,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 54
+    // CONFIGURATION 55
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5807,7 +5919,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 55
+    // CONFIGURATION 56
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"
@@ -5880,7 +5992,7 @@ const char* UNPARSED_CONFIGS[] = {
 "            }\n"
 "            }\n"
 "        ]\n"
 "        ]\n"
 "    }\n",
 "    }\n",
-    // CONFIGURATION 56
+    // CONFIGURATION 57
 "{\n"
 "{\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"decline-probation-period\": 86400,\n"
 "        \"dhcp-ddns\": {\n"
 "        \"dhcp-ddns\": {\n"

+ 59 - 0
src/bin/dhcp6/tests/config_parser_unittest.cc

@@ -3407,6 +3407,65 @@ TEST_F(Dhcp6ParserTest, stdOptionData) {
     EXPECT_EQ(1516, optionIA->getT2());
     EXPECT_EQ(1516, optionIA->getT2());
 }
 }
 
 
+// Verify that specific option object is returned for standard
+// option with trailing domain list.
+TEST_F(Dhcp6ParserTest, rdnssOption) {
+    ConstElementPtr x;
+    std::map<std::string, std::string> params;
+    params["name"] = "rdnss-selection";
+    params["space"] = DHCP6_OPTION_SPACE;
+    // Option code 74 is D6O_RDNSS_SELECTION
+    params["code"] = "74";
+    params["data"] = "2001::1, 3, isc.org, example.org, example.com";
+    params["csv-format"] = "true";
+
+    std::string config = createConfigWithOption(params);
+    ConstElementPtr json = parseDHCP6(config, true);
+
+    EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
+    checkResult(x, 0);
+
+    Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->
+        selectSubnet(IOAddress("2001:db8:1::5"), classify_);
+    ASSERT_TRUE(subnet);
+    OptionContainerPtr options = subnet->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
+    ASSERT_EQ(1, options->size());
+
+    // Get the search index. Index #1 is to search using option code.
+    const OptionContainerTypeIndex& idx = options->get<1>();
+
+    // Get the options for specified index. Expecting one option to be
+    // returned but in theory we may have multiple options with the same
+    // code so we get the range.
+    std::pair<OptionContainerTypeIndex::const_iterator,
+              OptionContainerTypeIndex::const_iterator> range =
+        idx.equal_range(D6O_RDNSS_SELECTION);
+    // Expect single option with the code equal to rndnss-selection option code.
+    ASSERT_EQ(1, std::distance(range.first, range.second));
+    // The actual pointer to the option is held in the option field
+    // in the structure returned.
+    OptionPtr option = range.first->option_;
+    ASSERT_TRUE(option);
+    // Option object returned for here is expected to be OptionCustom
+    // which is derived from Option. This class is dedicated to
+    // represent standard option D6O_RDNSS_SELECTION.
+    boost::shared_ptr<OptionCustom> optionCustom =
+        boost::dynamic_pointer_cast<OptionCustom>(option);
+    // If cast is unsuccessful than option returned was of a
+    // different type than optionCustom. This is wrong.
+    ASSERT_TRUE(optionCustom);
+    // If cast was successful we may use accessors exposed by
+    // optionCustom to validate that the content of this option
+    // has been set correctly.
+    ASSERT_EQ(5, optionCustom->getDataFieldsNum());
+    EXPECT_EQ("2001::1", optionCustom->readAddress(0).toText());
+    EXPECT_EQ(3, optionCustom->readInteger<uint8_t>(1));
+    EXPECT_EQ("isc.org.", optionCustom->readFqdn(2));
+    EXPECT_EQ("example.org.", optionCustom->readFqdn(3));
+    EXPECT_EQ("example.com.", optionCustom->readFqdn(4));
+}
+
+
 // This test checks if vendor options can be specified in the config file
 // This test checks if vendor options can be specified in the config file
 // (in hex format), and later retrieved from configured subnet
 // (in hex format), and later retrieved from configured subnet
 TEST_F(Dhcp6ParserTest, vendorOptionsHex) {
 TEST_F(Dhcp6ParserTest, vendorOptionsHex) {

+ 3 - 3
src/lib/dhcp/dhcp4.h

@@ -144,7 +144,7 @@ enum DHCPOptionType {
     DHO_STREETTALK_SERVER            = 75,
     DHO_STREETTALK_SERVER            = 75,
     DHO_STDASERVER                   = 76,
     DHO_STDASERVER                   = 76,
     DHO_USER_CLASS                   = 77,
     DHO_USER_CLASS                   = 77,
-//  DHO_DIRECTORY_AGENT              = 78,
+    DHO_DIRECTORY_AGENT              = 78,
     DHO_SERVICE_SCOPE                = 79,
     DHO_SERVICE_SCOPE                = 79,
 //  DHO_RAPID_COMMIT                 = 80,
 //  DHO_RAPID_COMMIT                 = 80,
     DHO_FQDN                         = 81,
     DHO_FQDN                         = 81,
@@ -195,7 +195,7 @@ enum DHCPOptionType {
     // 143 is removed/unassigned
     // 143 is removed/unassigned
 //  DHO_GEOLOC                       = 144,
 //  DHO_GEOLOC                       = 144,
 //  DHO_FORCERENEW_NONCE_CAPABLE     = 145,
 //  DHO_FORCERENEW_NONCE_CAPABLE     = 145,
-//  DHO_RDNSS_SELECT                 = 146,
+    DHO_RDNSS_SELECT                 = 146,
     // 147-149 are removed/unassigned
     // 147-149 are removed/unassigned
     // 150 have multiple definitions
     // 150 have multiple definitions
 //  DHO_STATUS_CODE                  = 151,
 //  DHO_STATUS_CODE                  = 151,
@@ -211,7 +211,7 @@ enum DHCPOptionType {
     // 161-209 are removed/unassigned
     // 161-209 are removed/unassigned
 //  DHO_PATH_PREFIX                  = 210,
 //  DHO_PATH_PREFIX                  = 210,
 //  DHO_REBOOT_TIME                  = 211,    
 //  DHO_REBOOT_TIME                  = 211,    
-//  DHO_6RD                          = 212,
+    DHO_6RD                          = 212,
     DHO_V4_ACCESS_DOMAIN             = 213,
     DHO_V4_ACCESS_DOMAIN             = 213,
     // 214-219 are removed/unassigned
     // 214-219 are removed/unassigned
 //  DHO_SUBNET_ALLOC                 = 220,
 //  DHO_SUBNET_ALLOC                 = 220,

+ 1 - 1
src/lib/dhcp/dhcp6.h

@@ -91,7 +91,7 @@ enum DHCPv6OptionType {
 // D6O_MIP6_HNP                            = 71, /* RFC6610 */
 // D6O_MIP6_HNP                            = 71, /* RFC6610 */
 // D6O_MIP6_HAA                            = 72, /* RFC6610 */
 // D6O_MIP6_HAA                            = 72, /* RFC6610 */
 // D6O_MIP6_HAF                            = 73, /* RFC6610 */
 // D6O_MIP6_HAF                            = 73, /* RFC6610 */
-// D6O_RDNSS_SELECTION                     = 74, /* RFC6731 */
+   D6O_RDNSS_SELECTION                     = 74, /* RFC6731 */
 // D6O_KRB_PRINCIPAL_NAME                  = 75, /* RFC6784 */
 // D6O_KRB_PRINCIPAL_NAME                  = 75, /* RFC6784 */
 // D6O_KRB_REALM_NAME                      = 76, /* RFC6784 */
 // D6O_KRB_REALM_NAME                      = 76, /* RFC6784 */
 // D6O_KRB_DEFAULT_REALM_NAME              = 77, /* RFC6784 */
 // D6O_KRB_DEFAULT_REALM_NAME              = 77, /* RFC6784 */

+ 25 - 0
src/lib/dhcp/std_option_defs.h

@@ -37,6 +37,9 @@ namespace {
 #define NO_RECORD_DEF 0, 0
 #define NO_RECORD_DEF 0, 0
 #endif
 #endif
 
 
+// SLP Directory Agent option.
+RECORD_DECL(DIRECTORY_AGENT_RECORDS, OPT_BOOLEAN_TYPE, OPT_IPV4_ADDRESS_TYPE);
+
 // SLP Service Scope option.
 // SLP Service Scope option.
 //
 //
 // The scope list is optional.
 // The scope list is optional.
@@ -65,11 +68,23 @@ RECORD_DECL(CLIENT_NDI_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT8_TYPE);
 // A client identifer: a 1 byte type field followed by opaque data depending on the type
 // A client identifer: a 1 byte type field followed by opaque data depending on the type
 RECORD_DECL(UUID_GUID_RECORDS, OPT_UINT8_TYPE, OPT_BINARY_TYPE);
 RECORD_DECL(UUID_GUID_RECORDS, OPT_UINT8_TYPE, OPT_BINARY_TYPE);
 
 
+// RFC6731 DHCPv4 Recursive DNS Server Selection option.
+//
+// Flag, two addresses and domain list
+RECORD_DECL(V4_RDNSS_SELECT_RECORDS, OPT_UINT8_TYPE, OPT_IPV4_ADDRESS_TYPE,
+            OPT_IPV4_ADDRESS_TYPE, OPT_FQDN_TYPE);
+
 // RFC7618 DHCPv4 Port Parameter option.
 // RFC7618 DHCPv4 Port Parameter option.
 //
 //
 // PSID offset, PSID-len and PSID
 // PSID offset, PSID-len and PSID
 RECORD_DECL(V4_PORTPARAMS_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT16_TYPE);
 RECORD_DECL(V4_PORTPARAMS_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT16_TYPE);
 
 
+// RFC5969 DHCPv6 6RD option.
+//
+// two 8 bit lengthes, an IPv6 address and one or more IPv4 addresses
+RECORD_DECL(OPT_6RD_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE,
+            OPT_IPV6_ADDRESS_TYPE, OPT_IPV4_ADDRESS_TYPE);
+
 /// @brief Definitions of standard DHCPv4 options.
 /// @brief Definitions of standard DHCPv4 options.
 const OptionDefParams STANDARD_V4_OPTION_DEFINITIONS[] = {
 const OptionDefParams STANDARD_V4_OPTION_DEFINITIONS[] = {
     { "subnet-mask", DHO_SUBNET_MASK, OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" },
     { "subnet-mask", DHO_SUBNET_MASK, OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" },
@@ -184,6 +199,8 @@ const OptionDefParams STANDARD_V4_OPTION_DEFINITIONS[] = {
     { "streettalk-server", DHO_STREETTALK_SERVER, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
     { "streettalk-server", DHO_STREETTALK_SERVER, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
     { "streettalk-directory-assistance-server", DHO_STDASERVER, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
     { "streettalk-directory-assistance-server", DHO_STDASERVER, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
     { "user-class", DHO_USER_CLASS, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
     { "user-class", DHO_USER_CLASS, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
+    { "slp-directory-agent", DHO_DIRECTORY_AGENT, OPT_RECORD_TYPE, true,
+      RECORD_DEF(DIRECTORY_AGENT_RECORDS), "" },
     { "slp-service-scope", DHO_SERVICE_SCOPE, OPT_RECORD_TYPE, false,
     { "slp-service-scope", DHO_SERVICE_SCOPE, OPT_RECORD_TYPE, false,
       RECORD_DEF(SERVICE_SCOPE_RECORDS), "" },
       RECORD_DEF(SERVICE_SCOPE_RECORDS), "" },
     { "fqdn", DHO_FQDN, OPT_RECORD_TYPE, false, RECORD_DEF(FQDN_RECORDS), "" },
     { "fqdn", DHO_FQDN, OPT_RECORD_TYPE, false, RECORD_DEF(FQDN_RECORDS), "" },
@@ -239,9 +256,12 @@ const OptionDefParams STANDARD_V4_OPTION_DEFINITIONS[] = {
     { "v4-lost", DHO_V4_LOST, OPT_FQDN_TYPE, false, NO_RECORD_DEF, "" },
     { "v4-lost", DHO_V4_LOST, OPT_FQDN_TYPE, false, NO_RECORD_DEF, "" },
     { "capwap-ac-v4", DHO_CAPWAP_AC_V4, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
     { "capwap-ac-v4", DHO_CAPWAP_AC_V4, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
     { "sip-ua-cs-domains", DHO_SIP_UA_CONF_SERVICE_DOMAINS, OPT_FQDN_TYPE, true, NO_RECORD_DEF, "" },
     { "sip-ua-cs-domains", DHO_SIP_UA_CONF_SERVICE_DOMAINS, OPT_FQDN_TYPE, true, NO_RECORD_DEF, "" },
+    { "rdnss-selection", DHO_RDNSS_SELECT, OPT_RECORD_TYPE, true,
+      RECORD_DEF(V4_RDNSS_SELECT_RECORDS), "" },
     { "v4-portparams", DHO_V4_PORTPARAMS, OPT_RECORD_TYPE, false,
     { "v4-portparams", DHO_V4_PORTPARAMS, OPT_RECORD_TYPE, false,
       RECORD_DEF(V4_PORTPARAMS_RECORDS), "" },
       RECORD_DEF(V4_PORTPARAMS_RECORDS), "" },
     { "v4-captive-portal", DHO_V4_CAPTIVE_PORTAL, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" },
     { "v4-captive-portal", DHO_V4_CAPTIVE_PORTAL, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" },
+    { "option-6rd", DHO_6RD, OPT_RECORD_TYPE, true, RECORD_DEF(OPT_6RD_RECORDS), "" },
     { "v4-access-domain", DHO_V4_ACCESS_DOMAIN, OPT_FQDN_TYPE, false, NO_RECORD_DEF, "" }
     { "v4-access-domain", DHO_V4_ACCESS_DOMAIN, OPT_FQDN_TYPE, false, NO_RECORD_DEF, "" }
 
 
         // @todo add definitions for all remaining options.
         // @todo add definitions for all remaining options.
@@ -285,6 +305,9 @@ RECORD_DECL(S46_PORTPARAMS, OPT_UINT8_TYPE, OPT_PSID_TYPE);
 RECORD_DECL(STATUS_CODE_RECORDS, OPT_UINT16_TYPE, OPT_STRING_TYPE);
 RECORD_DECL(STATUS_CODE_RECORDS, OPT_UINT16_TYPE, OPT_STRING_TYPE);
 // vendor-class
 // vendor-class
 RECORD_DECL(VENDOR_CLASS_RECORDS, OPT_UINT32_TYPE, OPT_BINARY_TYPE);
 RECORD_DECL(VENDOR_CLASS_RECORDS, OPT_UINT32_TYPE, OPT_BINARY_TYPE);
+// rdnss-selection
+RECORD_DECL(V6_RDNSS_SELECT_RECORDS, OPT_IPV6_ADDRESS_TYPE, OPT_UINT8_TYPE,
+            OPT_FQDN_TYPE);
 // sedhcpv6 signature
 // sedhcpv6 signature
 RECORD_DECL(SIGNATURE_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE,
 RECORD_DECL(SIGNATURE_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE,
             OPT_BINARY_TYPE);
             OPT_BINARY_TYPE);
@@ -399,6 +422,8 @@ const OptionDefParams STANDARD_V6_OPTION_DEFINITIONS[] = {
       NO_RECORD_DEF, "" },
       NO_RECORD_DEF, "" },
     { "rsoo", D6O_RSOO, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "rsoo-opts" },
     { "rsoo", D6O_RSOO, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "rsoo-opts" },
     { "pd-exclude", D6O_PD_EXCLUDE, OPT_IPV6_PREFIX_TYPE, false, NO_RECORD_DEF, "" },
     { "pd-exclude", D6O_PD_EXCLUDE, OPT_IPV6_PREFIX_TYPE, false, NO_RECORD_DEF, "" },
+    { "rdnss-selection", D6O_RDNSS_SELECTION, OPT_RECORD_TYPE, true,
+      RECORD_DEF(V6_RDNSS_SELECT_RECORDS), "" },
     { "client-linklayer-addr", D6O_CLIENT_LINKLAYER_ADDR, OPT_BINARY_TYPE, false,
     { "client-linklayer-addr", D6O_CLIENT_LINKLAYER_ADDR, OPT_BINARY_TYPE, false,
       NO_RECORD_DEF, "" },
       NO_RECORD_DEF, "" },
     { "link-address", D6O_LINK_ADDRESS, OPT_IPV6_ADDRESS_TYPE, false,
     { "link-address", D6O_LINK_ADDRESS, OPT_IPV6_ADDRESS_TYPE, false,

+ 43 - 0
src/lib/dhcp/tests/libdhcp++_unittest.cc

@@ -1285,6 +1285,15 @@ TEST_F(LibDhcpTest, stdOptionDefs4) {
     LibDhcpTest::testStdOptionDefs4(DHO_USER_CLASS, begin, end,
     LibDhcpTest::testStdOptionDefs4(DHO_USER_CLASS, begin, end,
                                     typeid(Option));
                                     typeid(Option));
 
 
+    LibDhcpTest::testStdOptionDefs4(DHO_DIRECTORY_AGENT, begin, begin + 5,
+                                    typeid(OptionCustom));
+
+    LibDhcpTest::testStdOptionDefs4(DHO_DIRECTORY_AGENT, begin, begin + 9,
+                                    typeid(OptionCustom));
+
+    LibDhcpTest::testStdOptionDefs4(DHO_DIRECTORY_AGENT, begin, begin + 45,
+                                    typeid(OptionCustom));
+
     LibDhcpTest::testStdOptionDefs4(DHO_SERVICE_SCOPE, begin, end,
     LibDhcpTest::testStdOptionDefs4(DHO_SERVICE_SCOPE, begin, end,
                                     typeid(Option4SlpServiceScope));
                                     typeid(Option4SlpServiceScope));
 
 
@@ -1431,12 +1440,32 @@ TEST_F(LibDhcpTest, stdOptionDefs4) {
                                     fqdn_buf.end(),
                                     fqdn_buf.end(),
                                     typeid(OptionCustom));
                                     typeid(OptionCustom));
 
 
+    std::vector<uint8_t> rdnss1_buf(begin, begin + 9);
+    rdnss1_buf.insert(rdnss1_buf.end(), fqdn1_buf.begin(), fqdn1_buf.end());
+
+    LibDhcpTest::testStdOptionDefs4(DHO_RDNSS_SELECT, rdnss1_buf.begin(),
+                                    rdnss1_buf.end(),
+                                    typeid(OptionCustom));
+
+    std::vector<uint8_t> rdnss_buf(begin, begin + 9);
+    rdnss_buf.insert(rdnss_buf.end(), fqdn_buf.begin(), fqdn_buf.end());
+
+    LibDhcpTest::testStdOptionDefs4(DHO_RDNSS_SELECT, rdnss_buf.begin(),
+                                    rdnss_buf.end(),
+                                    typeid(OptionCustom));
+
     LibDhcpTest::testStdOptionDefs4(DHO_V4_PORTPARAMS, begin, begin + 4,
     LibDhcpTest::testStdOptionDefs4(DHO_V4_PORTPARAMS, begin, begin + 4,
                                     typeid(OptionCustom));
                                     typeid(OptionCustom));
 
 
     LibDhcpTest::testStdOptionDefs4(DHO_V4_CAPTIVE_PORTAL, begin, end,
     LibDhcpTest::testStdOptionDefs4(DHO_V4_CAPTIVE_PORTAL, begin, end,
                                     typeid(OptionString));
                                     typeid(OptionString));
 
 
+    LibDhcpTest::testStdOptionDefs4(DHO_6RD, begin, begin + 22,
+                                    typeid(OptionCustom));
+
+    LibDhcpTest::testStdOptionDefs4(DHO_6RD, begin, begin + 46,
+                                    typeid(OptionCustom));
+
     LibDhcpTest::testStdOptionDefs4(DHO_V4_ACCESS_DOMAIN, fqdn1_buf.begin(),
     LibDhcpTest::testStdOptionDefs4(DHO_V4_ACCESS_DOMAIN, fqdn1_buf.begin(),
                                     fqdn1_buf.end(), typeid(OptionCustom));
                                     fqdn1_buf.end(), typeid(OptionCustom));
 }
 }
@@ -1705,6 +1734,20 @@ TEST_F(LibDhcpTest, stdOptionDefs6) {
     LibDhcpTest::testStdOptionDefs6(D6O_PD_EXCLUDE, begin, end,
     LibDhcpTest::testStdOptionDefs6(D6O_PD_EXCLUDE, begin, end,
                                     typeid(Option6PDExclude));
                                     typeid(Option6PDExclude));
 
 
+    std::vector<uint8_t> rdnss1_buf(begin, begin + 17);
+    rdnss1_buf.insert(rdnss1_buf.end(), fqdn1_buf.begin(), fqdn1_buf.end());
+
+    LibDhcpTest::testStdOptionDefs6(D6O_RDNSS_SELECTION, rdnss1_buf.begin(),
+                                    rdnss1_buf.end(),
+                                    typeid(OptionCustom));
+
+    std::vector<uint8_t> rdnss_buf(begin, begin + 17);
+    rdnss_buf.insert(rdnss_buf.end(), fqdn_buf.begin(), fqdn_buf.end());
+
+    LibDhcpTest::testStdOptionDefs6(D6O_RDNSS_SELECTION, rdnss_buf.begin(),
+                                    rdnss_buf.end(),
+                                    typeid(OptionCustom));
+
     LibDhcpTest::testStdOptionDefs6(D6O_CLIENT_LINKLAYER_ADDR, begin, end,
     LibDhcpTest::testStdOptionDefs6(D6O_CLIENT_LINKLAYER_ADDR, begin, end,
                                     typeid(Option));
                                     typeid(Option));