]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[trac3576] Add PXE options
authorShawn Routhier <sar@isc.org>
Wed, 30 Sep 2015 06:23:12 +0000 (23:23 -0700)
committerShawn Routhier <sar@isc.org>
Wed, 30 Sep 2015 06:23:12 +0000 (23:23 -0700)
Add the options used by PXE
rfc4578 (dhcpv4)
93 Client_System (arch type)
94 Client NDI (network Interface id)
97 UUID/GUID client machine option def

rfc5970 (dhcpv6)
59 BOOTFILE_URL
60 BOOTFILE_PARAM
61 CLIENT_ARCH_TYPE
62 NII

Option 60 requires a special class in order to process the length & string tuples

As some unreleated tests used option 59 as an undefined option they needed to be
updated to use another option.

12 files changed:
doc/guide/dhcp4-srv.xml
doc/guide/dhcp6-srv.xml
src/bin/dhcp6/tests/config_parser_unittest.cc
src/lib/dhcp/Makefile.am
src/lib/dhcp/dhcp4.h
src/lib/dhcp/dhcp6.h
src/lib/dhcp/option_definition.cc
src/lib/dhcp/option_definition.h
src/lib/dhcp/std_option_defs.h
src/lib/dhcp/tests/Makefile.am
src/lib/dhcp/tests/libdhcp++_unittest.cc
src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc

index 4a116c39e1d2018d74292f52d65ad2410827a19d..1232c8d05b6ace097152edb1ffddd703ada8e844 100644 (file)
@@ -1085,7 +1085,9 @@ It is merely echoed by the server
 <row><entry>client-last-transaction-time</entry><entry>91</entry><entry>uint32</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>associated-ip</entry><entry>92</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
 -->
-<row><entry>subnet-selection</entry><entry>118</entry><entry>ipv4-address</entry><entry>false</entry><entry>false</entry></row>
+<row><entry>client-system</entry><entry>93</entry><entry>uint16</entry><entry>true</entry><entry>false</entry></row>
+<row><entry>client-ndi</entry><entry>94</entry><entry>record</entry><entry>false</entry><entry>false</entry></row>
+<row><entry>uuid-guid</entry><entry>97</entry><entry>record</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>domain-search</entry><entry>119</entry><entry>binary</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>vivco-suboptions</entry><entry>124</entry><entry>binary</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>vivso-suboptions</entry><entry>125</entry><entry>binary</entry><entry>false</entry><entry>false</entry></row>
index 084cb47a3c58c4f62135ecfbcac029b964fbe948..aa14060ef155abb35036cf2c35de07bf93dca89f 100644 (file)
@@ -954,6 +954,10 @@ temporarily override a list of interface names and listen on all interfaces.
 <row><entry>clt-time</entry><entry>46</entry><entry>uint32</entry><entry>false</entry></row>
 <row><entry>lq-relay-data</entry><entry>47</entry><entry>record</entry><entry>false</entry></row>
 <row><entry>lq-client-link</entry><entry>48</entry><entry>ipv6-address</entry><entry>true</entry></row>
+<row><entry>bootfile-url</entry><entry>59</entry><entry>string</entry><entry>false</entry></row>
+<row><entry>bootfile-param</entry><entry>60</entry><entry>binary</entry><entry>false</entry></row>
+<row><entry>client-arch-type</entry><entry>61</entry><entry>uint16</entry><entry>true</entry></row>
+<row><entry>nii</entry><entry>62</entry><entry>record</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>client-linklayer-addr</entry><entry>79</entry><entry>binary</entry><entry>false</entry></row>
index 0d305267de7b7e96785e34a63f7483c2bf2defd4..eb48f4c395e2a68d16539f4a3223709cfc484c18 100644 (file)
@@ -2067,15 +2067,15 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) {
     checkResult(status, 1);
     EXPECT_TRUE(errorContainsPosition(status, "<string>"));
 
-    /// @todo The option 59 is a standard DHCPv6 option. However, at this point
+    /// @todo The option 63 is a standard DHCPv6 option. However, at this point
     /// there is no definition for this option in libdhcp++, so it should be
     /// allowed to define it from the configuration interface. This test will
     /// have to be removed once definitions for remaining standard options are
     /// created.
     config =
         "{ \"option-def\": [ {"
-        "      \"name\": \"boot-file-name\","
-        "      \"code\": 59,"
+        "      \"name\": \"geolocation\","
+        "      \"code\": 63,"
         "      \"type\": \"string\","
         "      \"array\": False,"
         "      \"record-types\": \"\","
@@ -2092,12 +2092,12 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) {
     checkResult(status, 0);
 
     def = CfgMgr::instance().getStagingCfg()->
-        getCfgOptionDef()->get("dhcp6", 59);
+        getCfgOptionDef()->get("dhcp6", 63);
     ASSERT_TRUE(def);
 
     // Check the option data.
-    EXPECT_EQ("boot-file-name", def->getName());
-    EXPECT_EQ(59, def->getCode());
+    EXPECT_EQ("geolocation", def->getName());
+    EXPECT_EQ(63, def->getCode());
     EXPECT_EQ(OPT_STRING_TYPE, def->getType());
     EXPECT_FALSE(def->getArrayType());
 }
index 0c719f2e404452017166ed293eecb5fa291450c9..f637a3631f4912ddec5e9de0c8b117949ef02c35 100644 (file)
@@ -41,6 +41,7 @@ libkea_dhcp___la_SOURCES += option.cc option.h
 libkea_dhcp___la_SOURCES += option_custom.cc option_custom.h
 libkea_dhcp___la_SOURCES += option_data_types.cc option_data_types.h
 libkea_dhcp___la_SOURCES += option_definition.cc option_definition.h
+libkea_dhcp___la_SOURCES += option_opaque_data_tuples.cc option_opqaue_data_tuples.h
 libkea_dhcp___la_SOURCES += option_space.cc option_space.h
 libkea_dhcp___la_SOURCES += option_string.cc option_string.h
 libkea_dhcp___la_SOURCES += protocol_util.cc protocol_util.h
index 56932a15bc31e6819181c625b624aa679b68f39a..2297d556b2d7b19699b1b097b9ae8e0a9538f75f 100644 (file)
@@ -165,11 +165,11 @@ enum DHCPOptionType {
     DHO_AUTHENTICATE                 = 90,  /* RFC3118, was 210 */
     DHO_CLIENT_LAST_TRANSACTION_TIME = 91,
     DHO_ASSOCIATED_IP                = 92,
-//  DHO_SYSTEM                       = 93,
-//  DHO_NDI                          = 94,
+    DHO_SYSTEM                       = 93, /* RFC4578 */
+    DHO_NDI                          = 94, /* RFC4578 */
 //  DHO_LDAP                         = 95,
     // 96 is removed/unassigned
-//  DHO_UUID_GUID                    = 97,
+    DHO_UUID_GUID                    = 97, /* RFC4578 */
 //  DHO_USER_AUTH                    = 98,
 //  DHO_GEOCONF_CIVIC                = 99,
 //  DHO_PCODE                        = 100,
index 909e735529352db74c12c93d644dc2ed7c8f115b..6e053f69b197993f22e1db236150bd81b804b98d 100644 (file)
 //#define D6O_NTP_SERVER                          56 /* RFC5908 */
 //#define D6O_V6_ACCESS_DOMAIN                    57 /* RFC5986 */
 //#define D6O_SIP_UA_CS_LIST                      58 /* RFC6011 */
-//#define D6O_BOOTFILE_URL                        59 /* RFC5970 */
-//#define D6O_BOOTFILE_PARAM                      60 /* RFC5970 */
-//#define D6O_CLIENT_ARCH_TYPE                    61 /* RFC5970 */
-//#define D6O_NII                                 62 /* RFC5970 */
+#define D6O_BOOTFILE_URL                        59 /* RFC5970 */
+#define D6O_BOOTFILE_PARAM                      60 /* RFC5970 */
+#define D6O_CLIENT_ARCH_TYPE                    61 /* RFC5970 */
+#define D6O_NII                                 62 /* RFC5970 */
 //#define D6O_GEOLOCATION                         63 /* RFC6225 */
 //#define D6O_AFTR_NAME                           64 /* RFC6334 */
 #define D6O_ERP_LOCAL_DOMAIN_NAME               65 /* RFC6440 */
index a7d3d83db3553f57286cd1323d19df567c27f509..6569bc19f539aa639226c074c51dbced6a88d4db 100644 (file)
@@ -27,6 +27,7 @@
 #include <dhcp/option_definition.h>
 #include <dhcp/option_int.h>
 #include <dhcp/option_int_array.h>
+#include <dhcp/option_opaque_data_tuples.h>
 #include <dhcp/option_space.h>
 #include <dhcp/option_string.h>
 #include <dhcp/option_vendor.h>
@@ -436,6 +437,11 @@ OptionDefinition::haveStatusCodeFormat() const {
             (record_fields_[1] == OPT_STRING_TYPE));
 }
 
+bool
+OptionDefinition::haveOpaqueDataTuplesFormat() const {
+    return (getType() == OPT_BINARY_TYPE);
+}
+
 bool
 OptionDefinition::convertToBool(const std::string& value_str) const {
     // Case insensitve check that the input is one of: "true" or "false".
@@ -696,6 +702,9 @@ OptionDefinition::factorySpecialFormatOption(Option::Universe u,
         } else if (getCode() == D6O_STATUS_CODE && haveStatusCodeFormat()) {
             // Status Code (option code 13)
             return (OptionPtr(new Option6StatusCode(begin, end)));
+        } else if (getCode() == D6O_BOOTFILE_PARAM && haveOpaqueDataTuplesFormat()) {
+            // Bootfile params (option code 60)
+            return (OptionPtr(new OptionOpaqueDataTuples(Option::V6, getCode(), begin, end)));
         }
     } else {
         if ((getCode() == DHO_FQDN) && haveFqdn4Format()) {
index 2c41421c77961a592c67ae35858ae43d7a4cb0be..04a9693b54d7af26820e55cb7867b757f35f96ca 100644 (file)
@@ -370,6 +370,11 @@ public:
     /// @return true if option has the format of DHCPv6 Status code option.
     bool haveStatusCodeFormat() const;
 
+    /// @brief Check if the option has format of OpaqueDataTuples type options.
+    ///
+    /// @return true if option has the format of OpaqueDataTuples type options.
+    bool haveOpaqueDataTuplesFormat() const;
+
     /// @brief Option factory.
     ///
     /// This function creates an instance of DHCP option using
index 9fd8cbfe9c9627ee87c683afa4d40c813fad74d3..6f12b4f213aad2e3242c3300d347b0350cb38ac0 100644 (file)
@@ -72,6 +72,13 @@ RECORD_DECL(FQDN_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT8_TYPE,
 // Opaque data is represented here by the binary data field.
 RECORD_DECL(VIVCO_RECORDS, OPT_UINT32_TYPE, OPT_BINARY_TYPE);
 
+// RFC4578 (PXE) record fields
+//
+// Three 1 byte fileds to describe a network interface: type, major and minor
+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
+RECORD_DECL(UUID_GUID_RECORDS, OPT_UINT8_TYPE, OPT_BINARY_TYPE);
+
 /// @brief Definitions of standard DHCPv4 options.
 const OptionDefParams OPTION_DEF_PARAMS4[] = {
     { "subnet-mask", DHO_SUBNET_MASK, OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" },
@@ -188,6 +195,9 @@ const OptionDefParams OPTION_DEF_PARAMS4[] = {
     { "client-last-transaction-time", DHO_CLIENT_LAST_TRANSACTION_TIME,
       OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" },
     { "associated-ip", DHO_ASSOCIATED_IP, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
+    { "client-system", DHO_SYSTEM, OPT_UINT16_TYPE, true, NO_RECORD_DEF, "" },
+    { "client-ndi", DHO_NDI, OPT_RECORD_TYPE, false, RECORD_DEF(CLIENT_NDI_RECORDS), "" },
+    { "uuid-guid", DHO_UUID_GUID, OPT_RECORD_TYPE, false, RECORD_DEF(UUID_GUID_RECORDS), "" },
     { "subnet-selection", DHO_SUBNET_SELECTION,
       OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" },
     // The following options need a special encoding of data
@@ -240,6 +250,11 @@ RECORD_DECL(VENDOR_CLASS_RECORDS, OPT_UINT32_TYPE, OPT_BINARY_TYPE);
 RECORD_DECL(SIGNATURE_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE,
             OPT_BINARY_TYPE);
 
+// RFC5970 (PXE) Class record fields
+//
+// Three 1 byte fileds to describe a network interface: type, major and minor
+RECORD_DECL(CLIENT_NII_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_UINT8_TYPE);
+
 /// Standard DHCPv6 option definitions.
 ///
 /// @warning in this array, the initializers are provided for all
@@ -329,6 +344,10 @@ const OptionDefParams OPTION_DEF_PARAMS6[] = {
       RECORD_DEF(LQ_RELAY_DATA_RECORDS), "" },
     { "lq-client-link", D6O_LQ_CLIENT_LINK, OPT_IPV6_ADDRESS_TYPE, true,
       NO_RECORD_DEF, "" },
+    { "bootfile-url", D6O_BOOTFILE_URL, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" },
+    { "bootfile-param", D6O_BOOTFILE_PARAM, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
+    { "client-arch-type", D6O_CLIENT_ARCH_TYPE, OPT_UINT16_TYPE, true, NO_RECORD_DEF, "" },
+    { "nii", D6O_NII, OPT_RECORD_TYPE, false, RECORD_DEF(CLIENT_NII_RECORDS), "" },
     { "erp-local-domain-name", D6O_ERP_LOCAL_DOMAIN_NAME, OPT_FQDN_TYPE, false,
       NO_RECORD_DEF, "" },
     { "rsoo", D6O_RSOO, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "rsoo-opts" },
index bfb23634eda26da409738569cdb2f48ec5495e78..56014da2a4987366abeb7b33ae9c16ab3c999f9c 100644 (file)
@@ -51,7 +51,6 @@ libdhcp___unittests_SOURCES += hwaddr_unittest.cc
 libdhcp___unittests_SOURCES += iface_mgr_unittest.cc
 libdhcp___unittests_SOURCES += iface_mgr_test_config.cc iface_mgr_test_config.h
 libdhcp___unittests_SOURCES += libdhcp++_unittest.cc
-libdhcp___unittests_SOURCES += opaque_data_tuple_unittest.cc
 libdhcp___unittests_SOURCES += option4_addrlst_unittest.cc
 libdhcp___unittests_SOURCES += option4_client_fqdn_unittest.cc
 libdhcp___unittests_SOURCES += option6_addrlst_unittest.cc
@@ -65,6 +64,7 @@ libdhcp___unittests_SOURCES += option_int_array_unittest.cc
 libdhcp___unittests_SOURCES += option_data_types_unittest.cc
 libdhcp___unittests_SOURCES += option_definition_unittest.cc
 libdhcp___unittests_SOURCES += option_custom_unittest.cc
+libdhcp___unittests_SOURCES += option_opaque_data_tuples_unittest.cc
 libdhcp___unittests_SOURCES += option_unittest.cc
 libdhcp___unittests_SOURCES += option_space_unittest.cc
 libdhcp___unittests_SOURCES += option_string_unittest.cc
index 70847ca8463a0b2c523900965ef14e2e4089bdac..802a54607ccb7f117d2209ed167a30b2dc4b39c2 100644 (file)
@@ -29,6 +29,7 @@
 #include <dhcp/option_custom.h>
 #include <dhcp/option_int.h>
 #include <dhcp/option_int_array.h>
+#include <dhcp/option_opaque_data_tuples.h>
 #include <dhcp/option_string.h>
 #include <dhcp/option_vendor.h>
 #include <dhcp/option_vendor_class.h>
@@ -941,6 +942,15 @@ TEST_F(LibDhcpTest, stdOptionDefs4) {
     LibDhcpTest::testStdOptionDefs4(DHO_SUBNET_SELECTION, begin, end,
                                     typeid(OptionCustom));
 
+    LibDhcpTest::testStdOptionDefs4(DHO_SYSTEM, begin, end,
+                                    typeid(OptionIntArray<uint16_t>));
+
+    LibDhcpTest::testStdOptionDefs4(DHO_NDI, begin, begin + 3,
+                                    typeid(OptionCustom));
+
+    LibDhcpTest::testStdOptionDefs4(DHO_UUID_GUID, begin, begin + 17,
+                                    typeid(OptionCustom));
+
     LibDhcpTest::testStdOptionDefs4(DHO_DOMAIN_SEARCH, begin, end,
                                     typeid(Option));
 
@@ -1016,6 +1026,13 @@ TEST_F(LibDhcpTest, stdOptionDefs6) {
     std::vector<uint8_t> vclass_buf(vclass_data,
                                     vclass_data + sizeof(vclass_data));;
 
+    // Initialize test buffer for Bootfile Param option.
+    const char bparam_data[] = {
+        0x00, 0x01, 0x02
+    };
+    std::vector<uint8_t> bparam_buf(bparam_data,
+                                     bparam_data + sizeof(bparam_data));;
+
     // The actual test starts here for all supported option codes.
     LibDhcpTest::testStdOptionDefs6(D6O_CLIENTID, begin, end,
                                     typeid(Option));
@@ -1161,6 +1178,19 @@ TEST_F(LibDhcpTest, stdOptionDefs6) {
     LibDhcpTest::testStdOptionDefs6(D6O_LQ_CLIENT_LINK, begin, end,
                                     typeid(Option6AddrLst));
 
+    LibDhcpTest::testStdOptionDefs6(D6O_BOOTFILE_URL, begin, end,
+                                   typeid(OptionString));
+
+    LibDhcpTest::testStdOptionDefs6(D6O_BOOTFILE_PARAM, bparam_buf.begin(),
+                                    bparam_buf.end(),
+                                   typeid(OptionOpaqueDataTuples));
+
+    LibDhcpTest::testStdOptionDefs6(D6O_CLIENT_ARCH_TYPE, begin, end,
+                                   typeid(OptionIntArray<uint16_t>));
+
+    LibDhcpTest::testStdOptionDefs6(D6O_NII, begin, begin + 3,
+                                   typeid(OptionCustom));
+
     LibDhcpTest::testStdOptionDefs6(D6O_RSOO, begin, end,
                                     typeid(OptionCustom),
                                     "rsoo-opts");
index 458065d5d4237a060f2ea3eec86c57cf391b7035..0598efbfb3e4738a21666787dbb06d317267f87d 100644 (file)
@@ -231,9 +231,9 @@ TEST(CfgOptionDefTest, overrideStdOptionDef) {
     def.reset(new OptionDefinition("sntp-servers", D6O_SNTP_SERVERS,
                                    "ipv4-address"));
     EXPECT_THROW(cfg.add(def, DHCP6_OPTION_SPACE), isc::BadValue);
-    // There is no definition for option 59 in libdhcp++ yet, so it should
+    // There is no definition for option 63 in libdhcp++ yet, so it should
     // be possible provide a custom definition.
-    def.reset(new OptionDefinition("bootfile-url", 59, "uint32"));
+    def.reset(new OptionDefinition("geolocation", 63, "uint32"));
     EXPECT_NO_THROW(cfg.add(def, DHCP6_OPTION_SPACE));
 }