From: Shawn Routhier Date: Wed, 30 Sep 2015 06:23:12 +0000 (-0700) Subject: [trac3576] Add PXE options X-Git-Tag: trac3874_base~40^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=65097a0af77fb25da9eaf5aecc06bdf721656f06;p=thirdparty%2Fkea.git [trac3576] Add PXE options 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. --- diff --git a/doc/guide/dhcp4-srv.xml b/doc/guide/dhcp4-srv.xml index 4a116c39e1..1232c8d05b 100644 --- a/doc/guide/dhcp4-srv.xml +++ b/doc/guide/dhcp4-srv.xml @@ -1085,7 +1085,9 @@ It is merely echoed by the server client-last-transaction-time91uint32falsefalse associated-ip92ipv4-addresstruefalse --> -subnet-selection118ipv4-addressfalsefalse +client-system93uint16truefalse +client-ndi94recordfalsefalse +uuid-guid97recordfalsefalse domain-search119binaryfalsefalse vivco-suboptions124binaryfalsefalse vivso-suboptions125binaryfalsefalse diff --git a/doc/guide/dhcp6-srv.xml b/doc/guide/dhcp6-srv.xml index 084cb47a3c..aa14060ef1 100644 --- a/doc/guide/dhcp6-srv.xml +++ b/doc/guide/dhcp6-srv.xml @@ -954,6 +954,10 @@ temporarily override a list of interface names and listen on all interfaces. clt-time46uint32false lq-relay-data47recordfalse lq-client-link48ipv6-addresstrue +bootfile-url59stringfalse +bootfile-param60binaryfalse +client-arch-type61uint16true +nii62recordfalse erp-local-domain-name65fqdnfalse rsoo66emptyfalse client-linklayer-addr79binaryfalse diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc index 0d305267de..eb48f4c395 100644 --- a/src/bin/dhcp6/tests/config_parser_unittest.cc +++ b/src/bin/dhcp6/tests/config_parser_unittest.cc @@ -2067,15 +2067,15 @@ TEST_F(Dhcp6ParserTest, optionStandardDefOverride) { checkResult(status, 1); EXPECT_TRUE(errorContainsPosition(status, "")); - /// @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()); } diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am index 0c719f2e40..f637a3631f 100644 --- a/src/lib/dhcp/Makefile.am +++ b/src/lib/dhcp/Makefile.am @@ -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 diff --git a/src/lib/dhcp/dhcp4.h b/src/lib/dhcp/dhcp4.h index 56932a15bc..2297d556b2 100644 --- a/src/lib/dhcp/dhcp4.h +++ b/src/lib/dhcp/dhcp4.h @@ -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, diff --git a/src/lib/dhcp/dhcp6.h b/src/lib/dhcp/dhcp6.h index 909e735529..6e053f69b1 100644 --- a/src/lib/dhcp/dhcp6.h +++ b/src/lib/dhcp/dhcp6.h @@ -82,10 +82,10 @@ //#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 */ diff --git a/src/lib/dhcp/option_definition.cc b/src/lib/dhcp/option_definition.cc index a7d3d83db3..6569bc19f5 100644 --- a/src/lib/dhcp/option_definition.cc +++ b/src/lib/dhcp/option_definition.cc @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -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()) { diff --git a/src/lib/dhcp/option_definition.h b/src/lib/dhcp/option_definition.h index 2c41421c77..04a9693b54 100644 --- a/src/lib/dhcp/option_definition.h +++ b/src/lib/dhcp/option_definition.h @@ -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 diff --git a/src/lib/dhcp/std_option_defs.h b/src/lib/dhcp/std_option_defs.h index 9fd8cbfe9c..6f12b4f213 100644 --- a/src/lib/dhcp/std_option_defs.h +++ b/src/lib/dhcp/std_option_defs.h @@ -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" }, diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am index bfb23634ed..56014da2a4 100644 --- a/src/lib/dhcp/tests/Makefile.am +++ b/src/lib/dhcp/tests/Makefile.am @@ -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 diff --git a/src/lib/dhcp/tests/libdhcp++_unittest.cc b/src/lib/dhcp/tests/libdhcp++_unittest.cc index 70847ca846..802a54607c 100644 --- a/src/lib/dhcp/tests/libdhcp++_unittest.cc +++ b/src/lib/dhcp/tests/libdhcp++_unittest.cc @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -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)); + + 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 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 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)); + + LibDhcpTest::testStdOptionDefs6(D6O_NII, begin, begin + 3, + typeid(OptionCustom)); + LibDhcpTest::testStdOptionDefs6(D6O_RSOO, begin, end, typeid(OptionCustom), "rsoo-opts"); diff --git a/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc b/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc index 458065d5d4..0598efbfb3 100644 --- a/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc @@ -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)); }