diff options
author | Razvan Becheriu <razvan@isc.org> | 2022-10-18 14:07:53 +0200 |
---|---|---|
committer | Razvan Becheriu <razvan@isc.org> | 2022-10-24 19:49:34 +0200 |
commit | 80e8c44897d6c28e49267ab623b1203db97c75fb (patch) | |
tree | 71eec5961abe7a2de6755002ad257fe06dd00e0e /src | |
parent | [#248] using same add/get class interface (diff) | |
download | kea-80e8c44897d6c28e49267ab623b1203db97c75fb.tar.xz kea-80e8c44897d6c28e49267ab623b1203db97c75fb.zip |
[#248] template classes can add regular classes
Diffstat (limited to 'src')
32 files changed, 215 insertions, 168 deletions
diff --git a/src/bin/d2/parser_context.cc b/src/bin/d2/parser_context.cc index 703460a6de..f27a628c6a 100644 --- a/src/bin/d2/parser_context.cc +++ b/src/bin/d2/parser_context.cc @@ -169,25 +169,25 @@ D2ParserContext::contextName() case TSIG_KEYS: return ("tsig-keys"); case ALGORITHM: - return ("algorithm"); + return("algorithm"); case DIGEST_BITS: - return ("digest-bits"); + return("digest-bits"); case SECRET: - return ("secret"); + return("secret"); case FORWARD_DDNS: - return ("forward-ddns"); + return("forward-ddns"); case REVERSE_DDNS: - return ("reverse-ddns"); + return("reverse-ddns"); case DDNS_DOMAIN: - return ("ddns-domain"); + return("ddns-domain"); case DDNS_DOMAINS: - return ("ddns-domains"); + return("ddns-domains"); case DNS_SERVER: - return ("dns-server"); + return("dns-server"); case DNS_SERVERS: - return ("dns-servers"); + return("dns-servers"); case CONTROL_SOCKET: - return ("control-socket"); + return("control-socket"); case LOGGERS: return ("loggers"); case OUTPUT_OPTIONS: diff --git a/src/bin/dhcp4/dhcp4_lexer.ll b/src/bin/dhcp4/dhcp4_lexer.ll index 1aebaf1551..ccd6a72530 100644 --- a/src/bin/dhcp4/dhcp4_lexer.ll +++ b/src/bin/dhcp4/dhcp4_lexer.ll @@ -1279,12 +1279,12 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu] } } -\"template-class\" { +\"template-test\" { switch(driver.ctx_) { case isc::dhcp::Parser4Context::CLIENT_CLASSES: - return isc::dhcp::Dhcp4Parser::make_TEMPLATE_CLASS(driver.loc_); + return isc::dhcp::Dhcp4Parser::make_TEMPLATE_TEST(driver.loc_); default: - return isc::dhcp::Dhcp4Parser::make_STRING("template-class", driver.loc_); + return isc::dhcp::Dhcp4Parser::make_STRING("template-test", driver.loc_); } } diff --git a/src/bin/dhcp4/dhcp4_parser.yy b/src/bin/dhcp4/dhcp4_parser.yy index 9783cc9d18..f5c04dc8ce 100644 --- a/src/bin/dhcp4/dhcp4_parser.yy +++ b/src/bin/dhcp4/dhcp4_parser.yy @@ -170,7 +170,7 @@ using namespace std; CLIENT_CLASSES "client-classes" REQUIRE_CLIENT_CLASSES "require-client-classes" TEST "test" - TEMPLATE_CLASS "template-class" + TEMPLATE_TEST "template-test" ONLY_IF_REQUIRED "only-if-required" CLIENT_CLASS "client-class" @@ -2336,7 +2336,7 @@ not_empty_client_class_params: client_class_param client_class_param: client_class_name | client_class_test - | client_class_template_class + | client_class_template_test | only_if_required | option_def_list | option_data_list @@ -2362,10 +2362,13 @@ client_class_test: TEST { ctx.leave(); }; -client_class_template_class: TEMPLATE_CLASS COLON BOOLEAN { - ctx.unique("template-class", ctx.loc2pos(@1)); - ElementPtr b(new BoolElement($3, ctx.loc2pos(@3))); - ctx.stack_.back()->set("template-class", b); +client_class_template_test: TEMPLATE_TEST { + ctx.unique("template-test", ctx.loc2pos(@1)); + ctx.enter(ctx.NO_KEYWORD); +} COLON STRING { + ElementPtr template_test(new StringElement($4, ctx.loc2pos(@4))); + ctx.stack_.back()->set("template-test", template_test); + ctx.leave(); }; only_if_required: ONLY_IF_REQUIRED COLON BOOLEAN { diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 017affde7f..df0b100047 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -250,7 +250,7 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine, // Perform second pass of classification. evaluateClasses(query, true); - const ClientClasses& classes = query_->getClassesAndSubClasses(); + const ClientClasses& classes = query_->getClasses(); if (!classes.empty()) { LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_ASSIGNED) .arg(query_->getLabel()) @@ -2489,7 +2489,7 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) { Lease4Ptr lease; - auto const& classes = query->getClassesAndSubClasses(); + auto const& classes = query->getClasses(); // We used to issue a separate query (two actually: one for client-id // and another one for hw-addr for) each subnet in the shared network. diff --git a/src/bin/dhcp4/tests/config_parser_unittest.cc b/src/bin/dhcp4/tests/config_parser_unittest.cc index a263daf940..f80a8d6d64 100644 --- a/src/bin/dhcp4/tests/config_parser_unittest.cc +++ b/src/bin/dhcp4/tests/config_parser_unittest.cc @@ -6103,11 +6103,11 @@ TEST_F(Dhcp4ParserTest, templateClientClassValidLifetime) { " \"min-valid-lifetime\": 1000, \n" " \"valid-lifetime\": 2000, \n" " \"max-valid-lifetime\": 3000, \n" - " \"template-class\": true, \n" + " \"template-test\": \"''\" \n" " }, \n" " { \n" " \"name\": \"two\", \n" - " \"template-class\": true \n" + " \"template-test\": \"''\" \n" " } \n" "], \n" "\"subnet4\": [ { \n" diff --git a/src/bin/dhcp4/tests/fqdn_unittest.cc b/src/bin/dhcp4/tests/fqdn_unittest.cc index 2caf0ec6dd..2a275c6041 100644 --- a/src/bin/dhcp4/tests/fqdn_unittest.cc +++ b/src/bin/dhcp4/tests/fqdn_unittest.cc @@ -398,7 +398,7 @@ public: return (DdnsParamsPtr(new DdnsParams())); } - return (CfgMgr::instance().getCurrentCfg()->getDdnsParams(subnet_)); + return(CfgMgr::instance().getCurrentCfg()->getDdnsParams(subnet_)); } // Create a lease to be used by various tests. @@ -457,8 +457,8 @@ public: /// @return An std::string contained the generated FQDN. std::string generatedNameFromAddress(const IOAddress& addr, const bool trailing_dot = true) { - return (CfgMgr::instance().getD2ClientMgr() - .generateFqdn(addr, *getDdnsParams(), trailing_dot)); + return(CfgMgr::instance().getD2ClientMgr() + .generateFqdn(addr, *getDdnsParams(), trailing_dot)); } // Get the Client FQDN Option from the given message. diff --git a/src/bin/dhcp4/tests/simple_parser4_unittest.cc b/src/bin/dhcp4/tests/simple_parser4_unittest.cc index df104f8293..6ac157a99c 100644 --- a/src/bin/dhcp4/tests/simple_parser4_unittest.cc +++ b/src/bin/dhcp4/tests/simple_parser4_unittest.cc @@ -210,6 +210,6 @@ TEST_F(SimpleParser4Test, optionDefDefaults4) { checkBoolValue(def, "array", false); } -} -} -} +}; +}; +}; diff --git a/src/bin/dhcp6/dhcp6_lexer.ll b/src/bin/dhcp6/dhcp6_lexer.ll index e9577eec15..6e6340a6fa 100644 --- a/src/bin/dhcp6/dhcp6_lexer.ll +++ b/src/bin/dhcp6/dhcp6_lexer.ll @@ -1611,12 +1611,12 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu] } } -\"template-class\" { +\"template-test\" { switch(driver.ctx_) { case isc::dhcp::Parser6Context::CLIENT_CLASSES: - return isc::dhcp::Dhcp6Parser::make_TEMPLATE_CLASS(driver.loc_); + return isc::dhcp::Dhcp6Parser::make_TEMPLATE_TEST(driver.loc_); default: - return isc::dhcp::Dhcp6Parser::make_STRING("template-class", driver.loc_); + return isc::dhcp::Dhcp6Parser::make_STRING("template-test", driver.loc_); } } diff --git a/src/bin/dhcp6/dhcp6_parser.yy b/src/bin/dhcp6/dhcp6_parser.yy index 23d12eb637..18e90b911d 100644 --- a/src/bin/dhcp6/dhcp6_parser.yy +++ b/src/bin/dhcp6/dhcp6_parser.yy @@ -168,7 +168,7 @@ using namespace std; CLIENT_CLASSES "client-classes" REQUIRE_CLIENT_CLASSES "require-client-classes" TEST "test" - TEMPLATE_CLASS "template-class" + TEMPLATE_TEST "template-test" ONLY_IF_REQUIRED "only-if-required" CLIENT_CLASS "client-class" @@ -2408,7 +2408,7 @@ not_empty_client_class_params: client_class_param client_class_param: client_class_name | client_class_test - | client_class_template_class + | client_class_template_test | only_if_required | option_data_list | user_context @@ -2433,10 +2433,13 @@ client_class_test: TEST { ctx.leave(); }; -client_class_template_class: TEMPLATE_CLASS COLON BOOLEAN { - ctx.unique("template-class", ctx.loc2pos(@1)); - ElementPtr b(new BoolElement($3, ctx.loc2pos(@3))); - ctx.stack_.back()->set("template-class", b); +client_class_template_test: TEMPLATE_TEST { + ctx.unique("template-test", ctx.loc2pos(@1)); + ctx.enter(ctx.NO_KEYWORD); +} COLON STRING { + ElementPtr template_test(new StringElement($4, ctx.loc2pos(@4))); + ctx.stack_.back()->set("template-test", template_test); + ctx.leave(); }; only_if_required: ONLY_IF_REQUIRED COLON BOOLEAN { diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 34f08986f6..dfad23ba04 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -569,7 +569,7 @@ Dhcpv6Srv::initContext(const Pkt6Ptr& pkt, // Perform second pass of classification. evaluateClasses(pkt, true); - const ClientClasses& classes = pkt->getClassesAndSubClasses(); + const ClientClasses& classes = pkt->getClasses(); if (!classes.empty()) { LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASS_ASSIGNED) .arg(pkt->getLabel()) @@ -4056,7 +4056,7 @@ Dhcpv6Srv::setReservedClientClasses(const Pkt6Ptr& pkt, } } - const ClientClasses& classes = pkt->getClassesAndSubClasses(); + const ClientClasses& classes = pkt->getClasses(); if (!classes.empty()) { LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_CLASS_ASSIGNED) .arg(pkt->getLabel()) diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc index cc3c6a8989..33b64c02b4 100644 --- a/src/bin/dhcp6/tests/config_parser_unittest.cc +++ b/src/bin/dhcp6/tests/config_parser_unittest.cc @@ -8169,11 +8169,11 @@ TEST_F(Dhcp6ParserTest, templateClientClassValidPreferredLifetime) { " \"min-preferred-lifetime\": 4000, \n" " \"preferred-lifetime\": 5000, \n" " \"max-preferred-lifetime\": 6000, \n" - " \"template-class\": true \n" + " \"template-test\": \"''\" \n" " }, \n" " { \n" " \"name\": \"two\", \n" - " \"template-class\": true \n" + " \"template-test\": \"''\" \n" " } \n" "], \n" "\"subnet6\": [ { \n" diff --git a/src/bin/dhcp6/tests/fqdn_unittest.cc b/src/bin/dhcp6/tests/fqdn_unittest.cc index a26c0b7e8c..683a71cf62 100644 --- a/src/bin/dhcp6/tests/fqdn_unittest.cc +++ b/src/bin/dhcp6/tests/fqdn_unittest.cc @@ -145,7 +145,7 @@ public: return (DdnsParamsPtr(new DdnsParams())); } - return (CfgMgr::instance().getCurrentCfg()->getDdnsParams(subnet_)); + return(CfgMgr::instance().getCurrentCfg()->getDdnsParams(subnet_)); } /// @brief Construct the DHCPv6 Client FQDN option using flags and diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc b/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc index b284aaab3f..7d431b40dd 100644 --- a/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc +++ b/src/hooks/dhcp/lease_cmds/lease_cmds_callouts.cc @@ -34,7 +34,7 @@ extern "C" { /// 1 otherwise. int lease4_add(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.leaseAddHandler(handle)); + return(lease_cmds.leaseAddHandler(handle)); } /// @brief This is a command callout for 'lease6-add' command. @@ -45,7 +45,7 @@ int lease4_add(CalloutHandle& handle) { /// 1 otherwise. int lease6_add(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.leaseAddHandler(handle)); + return(lease_cmds.leaseAddHandler(handle)); } /// @brief This is a command callout for 'lease6-bulk-apply' command. @@ -67,7 +67,7 @@ int lease6_bulk_apply(CalloutHandle& handle) { /// 1 otherwise. int lease4_get(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.leaseGetHandler(handle)); + return(lease_cmds.leaseGetHandler(handle)); } /// @brief This is a command callout for 'lease6-get' command. @@ -78,7 +78,7 @@ int lease4_get(CalloutHandle& handle) { /// 1 otherwise. int lease6_get(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.leaseGetHandler(handle)); + return(lease_cmds.leaseGetHandler(handle)); } /// @brief This is a command callout for 'lease4-get-all' command. @@ -188,7 +188,7 @@ int lease6_get_by_hostname(CalloutHandle& handle) { /// 1 otherwise. int lease4_del(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.lease4DelHandler(handle)); + return(lease_cmds.lease4DelHandler(handle)); } /// @brief This is a command callout for 'lease6-del' command. @@ -199,7 +199,7 @@ int lease4_del(CalloutHandle& handle) { /// 1 otherwise. int lease6_del(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.lease6DelHandler(handle)); + return(lease_cmds.lease6DelHandler(handle)); } /// @brief This is a command callout for 'lease4-update' command. @@ -210,7 +210,7 @@ int lease6_del(CalloutHandle& handle) { /// 1 otherwise. int lease4_update(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.lease4UpdateHandler(handle)); + return(lease_cmds.lease4UpdateHandler(handle)); } /// @brief This is a command callout for 'lease6-update' command. @@ -221,7 +221,7 @@ int lease4_update(CalloutHandle& handle) { /// 1 otherwise. int lease6_update(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.lease6UpdateHandler(handle)); + return(lease_cmds.lease6UpdateHandler(handle)); } /// @brief This is a command callout for 'lease4-wipe' command. @@ -232,7 +232,7 @@ int lease6_update(CalloutHandle& handle) { /// 1 otherwise. int lease4_wipe(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.lease4WipeHandler(handle)); + return(lease_cmds.lease4WipeHandler(handle)); } /// @brief This is a command callout for 'lease6-wipe' command. @@ -243,7 +243,7 @@ int lease4_wipe(CalloutHandle& handle) { /// 1 otherwise. int lease6_wipe(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.lease6WipeHandler(handle)); + return(lease_cmds.lease6WipeHandler(handle)); } /// @brief This is a command callout for 'lease4-resend-ddns' command. @@ -254,7 +254,7 @@ int lease6_wipe(CalloutHandle& handle) { /// 1 otherwise. int lease4_resend_ddns(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.lease4ResendDdnsHandler(handle)); + return(lease_cmds.lease4ResendDdnsHandler(handle)); } /// @brief This is a command callout for 'lease6-resend-ddns' command. @@ -265,7 +265,7 @@ int lease4_resend_ddns(CalloutHandle& handle) { /// 1 otherwise. int lease6_resend_ddns(CalloutHandle& handle) { LeaseCmds lease_cmds; - return (lease_cmds.lease6ResendDdnsHandler(handle)); + return(lease_cmds.lease6ResendDdnsHandler(handle)); } /// @brief This is a command callout for 'lease4-write' command. diff --git a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp4.cc b/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp4.cc index d70fa258c1..afaceced64 100644 --- a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp4.cc +++ b/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp4.cc @@ -4525,7 +4525,7 @@ PgSqlConfigBackendDHCPv4Impl::getStatement(size_t index) const { << index << ", is invalid"); } - return (tagged_statements[index]); + return(tagged_statements[index]); } PgSqlConfigBackendDHCPv4::PgSqlConfigBackendDHCPv4(const DatabaseConnection::ParameterMap& parameters) diff --git a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc b/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc index b78b4d63e3..5ad7e43188 100644 --- a/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc +++ b/src/hooks/dhcp/pgsql_cb/pgsql_cb_dhcp6.cc @@ -4994,7 +4994,7 @@ PgSqlConfigBackendDHCPv6Impl::getStatement(size_t index) const { << index << ", is invalid"); } - return (tagged_statements[index]); + return(tagged_statements[index]); } PgSqlConfigBackendDHCPv6::PgSqlConfigBackendDHCPv6(const DatabaseConnection::ParameterMap& parameters) diff --git a/src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc b/src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc index c04eb74c14..4399cb08a2 100644 --- a/src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc +++ b/src/hooks/dhcp/pgsql_cb/pgsql_cb_impl.cc @@ -50,7 +50,7 @@ PgSqlConfigBackendImpl::insertQuery(size_t index, uint64_t PgSqlConfigBackendImpl::updateDeleteQuery(size_t index, const PsqlBindArray& in_bindings) { - return (conn_.updateDeleteQuery(getStatement(index), in_bindings)); + return(conn_.updateDeleteQuery(getStatement(index), in_bindings)); } PgSqlConfigBackendImpl::ScopedAuditRevision::ScopedAuditRevision( diff --git a/src/hooks/dhcp/run_script/tests/run_script_unittests.cc b/src/hooks/dhcp/run_script/tests/run_script_unittests.cc index 7ca5babee7..46d9c8d277 100644 --- a/src/hooks/dhcp/run_script/tests/run_script_unittests.cc +++ b/src/hooks/dhcp/run_script/tests/run_script_unittests.cc @@ -156,7 +156,7 @@ generateLease4() { Lease4Ptr lease4(new Lease4(IOAddress("192.168.0.1"), hwaddr, clientid, 2, 3, 4, false, false, "test.hostname")); - return (lease4); + return(lease4); } /// @brief Generate a valid Lease6. diff --git a/src/hooks/dhcp/stat_cmds/stat_cmds_callouts.cc b/src/hooks/dhcp/stat_cmds/stat_cmds_callouts.cc index df90c55fe1..228772f981 100644 --- a/src/hooks/dhcp/stat_cmds/stat_cmds_callouts.cc +++ b/src/hooks/dhcp/stat_cmds/stat_cmds_callouts.cc @@ -32,7 +32,7 @@ extern "C" { /// 1 otherwise. int stat_lease4_get(CalloutHandle& handle) { StatCmds stat_cmds; - return (stat_cmds.statLease4GetHandler(handle)); + return(stat_cmds.statLease4GetHandler(handle)); } /// @brief This is a command callout for 'stat-lease6-get' command. @@ -43,7 +43,7 @@ int stat_lease4_get(CalloutHandle& handle) { /// 1 otherwise. int stat_lease6_get(CalloutHandle& handle) { StatCmds stat_cmds; - return (stat_cmds.statLease6GetHandler(handle)); + return(stat_cmds.statLease6GetHandler(handle)); } /// @brief This function is called when the library is loaded. diff --git a/src/hooks/dhcp/user_chk/pkt_send_co.cc b/src/hooks/dhcp/user_chk/pkt_send_co.cc index 788d133022..740bc4b6c3 100644 --- a/src/hooks/dhcp/user_chk/pkt_send_co.cc +++ b/src/hooks/dhcp/user_chk/pkt_send_co.cc @@ -402,7 +402,7 @@ void generate_output_record(const std::string& id_type_str, std::string getV6AddrStr(Pkt6Ptr response) { OptionPtr tmp = response->getOption(D6O_IA_NA); if (tmp) { - return (getAddrStrIA_NA(tmp)); + return(getAddrStrIA_NA(tmp)); } // IA_NA not there so try IA_PD @@ -411,7 +411,7 @@ std::string getV6AddrStr(Pkt6Ptr response) { isc_throw (isc::BadValue, "Response has neither IA_NA nor IA_PD"); } - return (getAddrStrIA_PD(tmp)); + return(getAddrStrIA_PD(tmp)); } /// @brief Stringify the lease address in an D6O_IA_NA option set diff --git a/src/hooks/dhcp/user_chk/user_file.cc b/src/hooks/dhcp/user_chk/user_file.cc index e324bcb2b0..96cb6a0fc4 100644 --- a/src/hooks/dhcp/user_chk/user_file.cc +++ b/src/hooks/dhcp/user_chk/user_file.cc @@ -54,7 +54,7 @@ UserFile::readNextUser() { // We got something, try to make a user out of it. if (file_.gcount() > 0) { - return (makeUser(buf)); + return(makeUser(buf)); } } diff --git a/src/lib/database/dbaccess_parser.cc b/src/lib/database/dbaccess_parser.cc index 76ba13799e..caee236282 100644 --- a/src/lib/database/dbaccess_parser.cc +++ b/src/lib/database/dbaccess_parser.cc @@ -91,7 +91,6 @@ DbAccessParser::parse(std::string& access_string, max_row_errors = param.second->intValue(); values_copy[param.first] = boost::lexical_cast<std::string>(max_row_errors); - } else { // all remaining string parameters diff --git a/src/lib/dhcp/classify.h b/src/lib/dhcp/classify.h index 0c857048ea..f7d38c4c39 100644 --- a/src/lib/dhcp/classify.h +++ b/src/lib/dhcp/classify.h @@ -64,9 +64,9 @@ namespace dhcp { > ClientClassContainer; /// @brief Defines a single subclass (template class instantiation). - struct SubClass { + struct SubClassRelation { /// @brief Constructor. - SubClass(const ClientClass& template_class, const ClientClass& subclass) : + SubClassRelation(const ClientClass& template_class, const ClientClass& subclass) : template_class_(template_class), subclass_(subclass) { } @@ -77,6 +77,30 @@ namespace dhcp { ClientClass subclass_; }; + /// @brief Tag for the sequence index. + struct TemplateClassSequenceTag { }; + + /// @brief Tag for the name index. + struct TemplateClassNameTag { }; + + /// @brief the subclass multi-index. + typedef boost::multi_index_container< + SubClassRelation, + boost::multi_index::indexed_by< + // First index is the sequence one. + boost::multi_index::sequenced< + boost::multi_index::tag<TemplateClassSequenceTag> + >, + // Second index is the name hash one. + boost::multi_index::hashed_unique< + boost::multi_index::tag<TemplateClassNameTag>, + boost::multi_index::member<SubClassRelation, + ClientClass, + &SubClassRelation::template_class_> + > + > + > SubClassRelationContainer; + /// @brief Container for storing client class names /// /// Both a list to iterate on it in insert order and unordered diff --git a/src/lib/dhcp/pkt.cc b/src/lib/dhcp/pkt.cc index f70043edf2..fa85b0070b 100644 --- a/src/lib/dhcp/pkt.cc +++ b/src/lib/dhcp/pkt.cc @@ -77,10 +77,7 @@ Pkt::delOption(uint16_t type) { bool Pkt::inClass(const ClientClass& client_class) { - if (classes_.contains(client_class)) { - return (true); - } - return (subclasses_.contains(client_class)); + return (classes_.contains(client_class)); } void @@ -92,9 +89,7 @@ Pkt::addClass(const ClientClass& client_class, bool required) { ClientClasses& classes = !required ? classes_ : required_classes_; if (!classes.contains(client_class)) { classes.insert(client_class); - if (!subclasses_.empty()) { - subclasses_.insert(client_class); - } + static_cast<void>(subclasses_.push_back(SubClassRelation(client_class, client_class))); } } @@ -105,11 +100,12 @@ Pkt::addSubClass(const ClientClass& template_class, const ClientClass& subclass) classes_.insert("ALL"); } if (!classes_.contains(template_class)) { - if (subclasses_.empty()) { - subclasses_ = classes_; - } classes_.insert(template_class); - subclasses_.insert(subclass); + static_cast<void>(subclasses_.push_back(SubClassRelation(template_class, subclass))); + } + if (!classes_.contains(subclass)) { + classes_.insert(subclass); + static_cast<void>(subclasses_.push_back(SubClassRelation(subclass, subclass))); } } diff --git a/src/lib/dhcp/pkt.h b/src/lib/dhcp/pkt.h index 89cfb4c39c..dd1e395f39 100644 --- a/src/lib/dhcp/pkt.h +++ b/src/lib/dhcp/pkt.h @@ -327,13 +327,6 @@ public: return (!required ? classes_ : required_classes_); } - /// @brief Returns true if the subclass set is not empty - /// - /// @return true if there is at least one subclass associated with the packet. - bool hasSubClasses() const { - return (!subclasses_.empty()); - } - /// @brief Returns the class set including template classes associated with /// subclasses /// @@ -343,10 +336,7 @@ public: /// @return if required is false (the default) the classes the /// packet belongs to else the classes which are required to be /// evaluated. - const ClientClasses getClassesAndSubClasses() const { - if (subclasses_.empty()) { - return (classes_); - } + const SubClassRelationContainer& getSubClassesRelations() const { return (subclasses_); } @@ -662,7 +652,7 @@ public: /// iterate over existing classes. Having it public also solves the problem /// of returned reference lifetime. It is preferred to use @ref inClass and /// @ref addSubClass to operate on this field. - ClientClasses subclasses_; + SubClassRelationContainer subclasses_; /// @brief Collection of options present in this message. /// diff --git a/src/lib/dhcp/tests/pkt4_unittest.cc b/src/lib/dhcp/tests/pkt4_unittest.cc index 1bd45b5ce6..4687835a87 100644 --- a/src/lib/dhcp/tests/pkt4_unittest.cc +++ b/src/lib/dhcp/tests/pkt4_unittest.cc @@ -933,14 +933,12 @@ TEST_F(Pkt4Test, clientClasses) { EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_EROUTER)); EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_MODEM)); EXPECT_TRUE(pkt.getClasses().empty()); - EXPECT_FALSE(pkt.hasSubClasses()); // Add to the first class pkt.addClass(DOCSIS3_CLASS_EROUTER); EXPECT_TRUE(pkt.inClass(DOCSIS3_CLASS_EROUTER)); EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_MODEM)); ASSERT_FALSE(pkt.getClasses().empty()); - EXPECT_FALSE(pkt.hasSubClasses()); // Add to a second class pkt.addClass(DOCSIS3_CLASS_MODEM); @@ -951,7 +949,6 @@ TEST_F(Pkt4Test, clientClasses) { EXPECT_NO_THROW(pkt.addClass("foo")); EXPECT_NO_THROW(pkt.addClass("foo")); EXPECT_NO_THROW(pkt.addClass("foo")); - EXPECT_FALSE(pkt.hasSubClasses()); // Check that the packet belongs to 'foo' EXPECT_TRUE(pkt.inClass("foo")); @@ -964,17 +961,14 @@ TEST_F(Pkt4Test, deferredClientClasses) { // Default values (do not belong to any class) EXPECT_TRUE(pkt.getClasses(true).empty()); - EXPECT_FALSE(pkt.hasSubClasses()); // Add to the first class pkt.addClass(DOCSIS3_CLASS_EROUTER, true); EXPECT_EQ(1, pkt.getClasses(true).size()); - EXPECT_FALSE(pkt.hasSubClasses()); // Add to a second class pkt.addClass(DOCSIS3_CLASS_MODEM, true); EXPECT_EQ(2, pkt.getClasses(true).size()); - EXPECT_FALSE(pkt.hasSubClasses()); EXPECT_TRUE(pkt.getClasses(true).contains(DOCSIS3_CLASS_EROUTER)); EXPECT_TRUE(pkt.getClasses(true).contains(DOCSIS3_CLASS_MODEM)); EXPECT_FALSE(pkt.getClasses(true).contains("foo")); @@ -983,7 +977,6 @@ TEST_F(Pkt4Test, deferredClientClasses) { EXPECT_NO_THROW(pkt.addClass("foo", true)); EXPECT_NO_THROW(pkt.addClass("foo", true)); EXPECT_NO_THROW(pkt.addClass("foo", true)); - EXPECT_FALSE(pkt.hasSubClasses()); // Check that the packet belongs to 'foo' EXPECT_TRUE(pkt.getClasses(true).contains("foo")); @@ -998,14 +991,12 @@ TEST_F(Pkt4Test, templateClasses) { EXPECT_FALSE(pkt.inClass("eth0")); EXPECT_FALSE(pkt.inClass("interface-id0")); EXPECT_TRUE(pkt.getClasses().empty()); - EXPECT_FALSE(pkt.hasSubClasses()); // Add to the first subclass pkt.addSubClass("template-interface-name", "eth0"); EXPECT_TRUE(pkt.inClass("eth0")); EXPECT_FALSE(pkt.inClass("interface-id0")); ASSERT_FALSE(pkt.getClasses().empty()); - EXPECT_TRUE(pkt.hasSubClasses()); // Add to a second subclass pkt.addSubClass("template-interface-id", "interface-id0"); diff --git a/src/lib/dhcp/tests/pkt6_unittest.cc b/src/lib/dhcp/tests/pkt6_unittest.cc index f92f4168f5..f433bae6b6 100644 --- a/src/lib/dhcp/tests/pkt6_unittest.cc +++ b/src/lib/dhcp/tests/pkt6_unittest.cc @@ -1307,14 +1307,12 @@ TEST_F(Pkt6Test, clientClasses) { EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_EROUTER)); EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_MODEM)); EXPECT_TRUE(pkt.getClasses().empty()); - EXPECT_FALSE(pkt.hasSubClasses()); // Add to the first class pkt.addClass(DOCSIS3_CLASS_EROUTER); EXPECT_TRUE(pkt.inClass(DOCSIS3_CLASS_EROUTER)); EXPECT_FALSE(pkt.inClass(DOCSIS3_CLASS_MODEM)); ASSERT_FALSE(pkt.getClasses().empty()); - EXPECT_FALSE(pkt.hasSubClasses()); // Add to a second class pkt.addClass(DOCSIS3_CLASS_MODEM); @@ -1325,7 +1323,6 @@ TEST_F(Pkt6Test, clientClasses) { EXPECT_NO_THROW(pkt.addClass("foo")); EXPECT_NO_THROW(pkt.addClass("foo")); EXPECT_NO_THROW(pkt.addClass("foo")); - EXPECT_FALSE(pkt.hasSubClasses()); // Check that the packet belongs to 'foo' EXPECT_TRUE(pkt.inClass("foo")); @@ -1338,17 +1335,14 @@ TEST_F(Pkt6Test, deferredClientClasses) { // Default values (do not belong to any class) EXPECT_TRUE(pkt.getClasses(true).empty()); - EXPECT_FALSE(pkt.hasSubClasses()); // Add to the first class pkt.addClass(DOCSIS3_CLASS_EROUTER, true); EXPECT_EQ(1, pkt.getClasses(true).size()); - EXPECT_FALSE(pkt.hasSubClasses()); // Add to a second class pkt.addClass(DOCSIS3_CLASS_MODEM, true); EXPECT_EQ(2, pkt.getClasses(true).size()); - EXPECT_FALSE(pkt.hasSubClasses()); EXPECT_TRUE(pkt.getClasses(true).contains(DOCSIS3_CLASS_EROUTER)); EXPECT_TRUE(pkt.getClasses(true).contains(DOCSIS3_CLASS_MODEM)); EXPECT_FALSE(pkt.getClasses(true).contains("foo")); @@ -1357,7 +1351,6 @@ TEST_F(Pkt6Test, deferredClientClasses) { EXPECT_NO_THROW(pkt.addClass("foo", true)); EXPECT_NO_THROW(pkt.addClass("foo", true)); EXPECT_NO_THROW(pkt.addClass("foo", true)); - EXPECT_FALSE(pkt.hasSubClasses()); // Check that the packet belongs to 'foo' EXPECT_TRUE(pkt.getClasses(true).contains("foo")); @@ -1372,14 +1365,12 @@ TEST_F(Pkt6Test, templateClasses) { EXPECT_FALSE(pkt.inClass("eth0")); EXPECT_FALSE(pkt.inClass("interface-id0")); EXPECT_TRUE(pkt.getClasses().empty()); - EXPECT_FALSE(pkt.hasSubClasses()); // Add to the first subclass pkt.addSubClass("template-interface-name", "eth0"); EXPECT_TRUE(pkt.inClass("eth0")); EXPECT_FALSE(pkt.inClass("interface-id0")); ASSERT_FALSE(pkt.getClasses().empty()); - EXPECT_TRUE(pkt.hasSubClasses()); // Add to a second subclass pkt.addSubClass("template-interface-id", "interface-id0"); diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index b514055669..9fcdcce2ec 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -425,7 +425,7 @@ inAllowedPool(AllocEngine::ClientContext6& ctx, const Lease::Type& lease_type, // If the subnet belongs to a shared network we will be iterating // over the subnets that belong to this shared network. Subnet6Ptr current_subnet = ctx.subnet_; - auto const& classes = ctx.query_->getClassesAndSubClasses(); + auto const& classes = ctx.query_->getClasses(); while (current_subnet) { if (current_subnet->clientSupported(classes)) { @@ -658,7 +658,7 @@ AllocEngine::findReservation(ClientContext6& ctx) { } } - auto const& classes = ctx.query_->getClassesAndSubClasses(); + auto const& classes = ctx.query_->getClasses(); // We can only search for the reservation if a subnet has been selected. while (subnet) { @@ -919,7 +919,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) { CalloutHandle::CalloutNextStep callout_status = CalloutHandle::NEXT_STEP_CONTINUE; - auto const& classes = ctx.query_->getClassesAndSubClasses(); + auto const& classes = ctx.query_->getClasses(); for (; subnet; subnet = subnet->getNextSubnet(original_subnet)) { if (!subnet->clientSupported(classes)) { @@ -1360,7 +1360,7 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx, // There is no lease for a reservation in this IA. So, let's now iterate // over reservations specified and try to allocate one of them for the IA. - auto const& classes = ctx.query_->getClassesAndSubClasses(); + auto const& classes = ctx.query_->getClasses(); for (Subnet6Ptr subnet = ctx.subnet_; subnet; subnet = subnet->getNextSubnet(ctx.subnet_)) { @@ -2259,7 +2259,7 @@ AllocEngine::extendLease6(ClientContext6& ctx, Lease6Ptr lease) { // is not permitted by subnet client classification, delete it. if (!(ctx.hasGlobalReservation(makeIPv6Resrv(*lease))) && (((lease->type_ != Lease::TYPE_PD) && !ctx.subnet_->inRange(lease->addr_)) || - !ctx.subnet_->clientSupported(ctx.query_->getClassesAndSubClasses()))) { + !ctx.subnet_->clientSupported(ctx.query_->getClasses()))) { // Oh dear, the lease is no longer valid. We need to get rid of it. // Remove this lease from LeaseMgr @@ -3290,7 +3290,7 @@ hasAddressReservation(AllocEngine::ClientContext4& ctx) { // No address reservation found here, so let's try another subnet // within the same shared network. - subnet = subnet->getNextSubnet(ctx.subnet_, ctx.query_->getClassesAndSubClasses()); + subnet = subnet->getNextSubnet(ctx.subnet_, ctx.query_->getClasses()); } return (false); @@ -3316,7 +3316,7 @@ void findClientLease(AllocEngine::ClientContext4& ctx, Lease4Ptr& client_lease) Subnet4Ptr original_subnet = ctx.subnet_; - auto const& classes = ctx.query_->getClassesAndSubClasses(); + auto const& classes = ctx.query_->getClasses(); // Client identifier is optional. First check if we can try to lookup // by client-id. @@ -3401,7 +3401,7 @@ inAllowedPool(AllocEngine::ClientContext4& ctx, const IOAddress& address) { // If the subnet belongs to a shared network we will be iterating // over the subnets that belong to this shared network. Subnet4Ptr current_subnet = ctx.subnet_; - auto const& classes = ctx.query_->getClassesAndSubClasses(); + auto const& classes = ctx.query_->getClasses(); while (current_subnet) { if (current_subnet->inPool(Lease::TYPE_V4, address, classes)) { @@ -3513,7 +3513,7 @@ AllocEngine::allocateLease4(ClientContext4& ctx) { // subnets allowed for this client within the shared network, we // can't allocate a lease. Subnet4Ptr subnet = ctx.subnet_; - auto const& classes = ctx.query_->getClassesAndSubClasses(); + auto const& classes = ctx.query_->getClasses(); if (subnet && !subnet->clientSupported(classes)) { ctx.subnet_ = subnet->getNextSubnet(subnet, classes); } @@ -3604,7 +3604,7 @@ AllocEngine::findReservation(ClientContext4& ctx) { } } - auto const& classes = ctx.query_->getClassesAndSubClasses(); + auto const& classes = ctx.query_->getClasses(); // We can only search for the reservation if a subnet has been selected. while (subnet) { @@ -4411,7 +4411,7 @@ AllocEngine::allocateUnreservedLease4(ClientContext4& ctx) { // no matching pools for the client. uint64_t subnets_with_unavail_pools = 0; - auto const& classes = ctx.query_->getClassesAndSubClasses(); + auto const& classes = ctx.query_->getClasses(); while (subnet) { ClientIdPtr client_id; diff --git a/src/lib/dhcpsrv/client_class_def.cc b/src/lib/dhcpsrv/client_class_def.cc index 53e229994d..53e382bde9 100644 --- a/src/lib/dhcpsrv/client_class_def.cc +++ b/src/lib/dhcpsrv/client_class_def.cc @@ -294,7 +294,13 @@ ClientClassDef::toElement() const { ElementPtr TemplateClientClassDef::toElement() const { auto const& result = ClientClassDef::toElement(); - result->set("template-class", Element::create(true)); + auto const& test = result->get("test"); + if (test) { + result->set("template-test", test); + result->remove("test"); + } else { + result->set("template-test", Element::create("")); + } return (result); } diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc index 61c8ce8747..c62fe59610 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.cc +++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc @@ -1882,7 +1882,7 @@ Memfile_LeaseMgr::loadLeasesFromFiles(const std::string& filename, lease_file.reset(new LeaseFileType(filename)); LeaseFileLoader::load<LeaseObjectType>(*lease_file, storage, max_row_errors, false); - conversion_needed = conversion_needed || lease_file->needsConversion(); + conversion_needed = conversion_needed || lease_file->needsConversion(); return (conversion_needed); } @@ -2006,7 +2006,7 @@ Memfile_LeaseMgr::startLeaseStatsQuery4() { query->start(); } - return (query); + return(query); } LeaseStatsQueryPtr @@ -2019,7 +2019,7 @@ Memfile_LeaseMgr::startSubnetLeaseStatsQuery4(const SubnetID& subnet_id) { query->start(); } - return (query); + return(query); } LeaseStatsQueryPtr @@ -2034,7 +2034,7 @@ Memfile_LeaseMgr::startSubnetRangeLeaseStatsQuery4(const SubnetID& first_subnet_ query->start(); } - return (query); + return(query); } LeaseStatsQueryPtr @@ -2047,7 +2047,7 @@ Memfile_LeaseMgr::startLeaseStatsQuery6() { query->start(); } - return (query); + return(query); } LeaseStatsQueryPtr @@ -2060,7 +2060,7 @@ Memfile_LeaseMgr::startSubnetLeaseStatsQuery6(const SubnetID& subnet_id) { query->start(); } - return (query); + return(query); } LeaseStatsQueryPtr @@ -2075,7 +2075,7 @@ Memfile_LeaseMgr::startSubnetRangeLeaseStatsQuery6(const SubnetID& first_subnet_ query->start(); } - return (query); + return(query); } size_t @@ -2163,15 +2163,15 @@ Memfile_LeaseMgr::getClassLeaseCount(const ClientClass& client_class, const Lease::Type& ltype /* = Lease::TYPE_V4*/) const { if (MultiThreadingMgr::instance().getMode()) { std::lock_guard<std::mutex> lock(*mutex_); - return (class_lease_counter_.getClassCount(client_class, ltype)); + return(class_lease_counter_.getClassCount(client_class, ltype)); } else { - return (class_lease_counter_.getClassCount(client_class, ltype)); + return(class_lease_counter_.getClassCount(client_class, ltype)); } } void Memfile_LeaseMgr::clearClassLeaseCounts() { - return (class_lease_counter_.clear()); + return(class_lease_counter_.clear()); } std::string diff --git a/src/lib/dhcpsrv/parsers/client_class_def_parser.cc b/src/lib/dhcpsrv/parsers/client_class_def_parser.cc index 8c48a9afbc..99e6692571 100644 --- a/src/lib/dhcpsrv/parsers/client_class_def_parser.cc +++ b/src/lib/dhcpsrv/parsers/client_class_def_parser.cc @@ -50,6 +50,12 @@ ExpressionParser::parse(ExpressionPtr& expression, // by str() enclosed in quotes. std::string value; expression_cfg->getValue(value); + + if (parser_type == EvalContext::PARSER_STRING && value.empty()) { + isc_throw(DhcpConfigError, "expression can not be empty at (" + << expression_cfg->getPosition() << ")"); + } + try { EvalContext eval_ctx(family == AF_INET ? Option::V4 : Option::V6, check_defined); @@ -83,29 +89,33 @@ ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary, EvalContext::ParserType parser_type = EvalContext::PARSER_BOOL; - // Let's try to parse the template-class flag + // Let's try to parse the template-test expression bool is_template = false; - if (class_def_cfg->contains("template-class")) { - is_template = getBoolean(class_def_cfg, "template-class"); - if (is_template) { - parser_type = EvalContext::PARSER_STRING; - } - } // Parse matching expression ExpressionPtr match_expr; ConstElementPtr test_cfg = class_def_cfg->get("test"); + ConstElementPtr template_test_cfg = class_def_cfg->get("template-test"); + if (test_cfg && template_test_cfg) { + isc_throw(DhcpConfigError, "expected either 'test' or 'template-test' (" + << test_cfg->getPosition() << ") and (" + << template_test_cfg->getPosition() << ")"); + } std::string test; bool depend_on_known = false; + EvalContext::CheckDefined check_defined = EvalContext::acceptAll; + if (template_test_cfg) { + test_cfg = template_test_cfg; + parser_type = EvalContext::PARSER_STRING; + is_template = true; + } else { + check_defined = [&class_dictionary, &depend_on_known, check_dependencies](const ClientClass& cclass) { + return (!check_dependencies || isClientClassDefined(class_dictionary, depend_on_known, cclass)); + }; + } + if (test_cfg) { ExpressionParser parser; - auto check_defined = - [&class_dictionary, &depend_on_known, check_dependencies] - (const ClientClass& cclass) { - return (!check_dependencies || isClientClassDefined(class_dictionary, - depend_on_known, - cclass)); - }; parser.parse(match_expr, test_cfg, family, check_defined, parser_type); test = test_cfg->stringValue(); } @@ -285,7 +295,7 @@ ClientClassDefParser::checkParametersSupported(const ConstElementPtr& class_def_ "valid-lifetime", "min-valid-lifetime", "max-valid-lifetime", - "template-class"}; + "template-test"}; // The v4 client class supports additional parameters. static std::set<std::string> supported_params_v4 = { "option-def", diff --git a/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc b/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc index 305d024c52..0ca5f0450a 100644 --- a/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc +++ b/src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc @@ -378,7 +378,7 @@ TEST_F(ClientClassDefParserTest, checkAllSupported4) { " \"min-valid-lifetime\": 1000,\n" " \"max-valid-lifetime\": 1000,\n" " \"next-server\": \"192.0.2.3\",\n" - " \"template-class\": true,\n" + " \"template-test\": \"\",\n" " \"server-hostname\": \"myhost\",\n" " \"boot-file-name\": \"efi\"" "}\n"; @@ -400,7 +400,7 @@ TEST_F(ClientClassDefParserTest, checkAllSupported6) { " \"option-data\": [ ],\n" " \"user-context\": { },\n" " \"only-if-required\": false,\n" - " \"template-class\": true,\n" + " \"template-test\": \"\",\n" " \"preferred-lifetime\": 800,\n" " \"min-preferred-lifetime\": 800,\n" " \"max-preferred-lifetime\": 800\n" @@ -638,8 +638,7 @@ TEST_F(ClientClassDefParserTest, templateNameAndExpressionClass4) { std::string cfg_text = "{ \n" " \"name\": \"class_one\", \n" - " \"template-class\": true, \n" - " \"test\": \"" + test + "\" \n" + " \"template-test\": \"" + test + "\" \n" "} \n"; ClientClassDefPtr cclass; @@ -730,8 +729,7 @@ TEST_F(ClientClassDefParserTest, templateNameAndExpressionClass6) { std::string cfg_text = "{ \n" " \"name\": \"class_one\", \n" - " \"template-class\": true, \n" - " \"test\": \"" + test + "\" \n" + " \"template-test\": \"" + test + "\" \n" "} \n"; ClientClassDefPtr cclass; @@ -894,8 +892,7 @@ TEST_F(ClientClassDefParserTest, templateBasicValidClass4) { std::string cfg_text = "{ \n" " \"name\": \"MICROSOFT\", \n" - " \"test\": \"" + test + "\", \n" - " \"template-class\": true, \n" + " \"template-test\": \"" + test + "\", \n" " \"option-data\": [ \n" " { \n" " \"name\": \"domain-name-servers\", \n" @@ -994,8 +991,7 @@ TEST_F(ClientClassDefParserTest, templateBasicValidClass6) { std::string cfg_text = "{ \n" " \"name\": \"MICROSOFT\", \n" - " \"test\": \"" + test + "\", \n" - " \"template-class\": true, \n" + " \"template-test\": \"" + test + "\", \n" " \"option-data\": [ \n" " { \n" " \"name\": \"sip-server-addr\", \n" @@ -1095,13 +1091,38 @@ TEST_F(ClientClassDefParserTest, invalidExpression) { DhcpConfigError); } -// Verifies that a class with an invalid expression, fails to parse. +// Verifies that a class with an invalid template expression, fails to parse. TEST_F(ClientClassDefParserTest, templateInvalidExpression) { std::string cfg_text = "{ \n" " \"name\": \"one\", \n" - " \"template-class\": true, \n" - " \"test\": 777 \n" + " \"template-test\": 777 \n" + "} \n"; + + ClientClassDefPtr cclass; + ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET6), + DhcpConfigError); +} + +// Verifies that a class with an empty expression, fails to parse. +TEST_F(ClientClassDefParserTest, emptyExpression) { + std::string cfg_text = + "{ \n" + " \"name\": \"one\", \n" + " \"test\": \"\" \n" + "} \n"; + + ClientClassDefPtr cclass; + ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET6), + DhcpConfigError); +} + +// Verifies that a class with an empty expression, fails to parse. +TEST_F(ClientClassDefParserTest, templateEmptyExpression) { + std::string cfg_text = + "{ \n" + " \"name\": \"one\", \n" + " \"template-test\": \"\" \n" "} \n"; ClientClassDefPtr cclass; @@ -1109,6 +1130,20 @@ TEST_F(ClientClassDefParserTest, templateInvalidExpression) { DhcpConfigError); } +// Verifies that a class with both test and template-test expressions, fails to parse. +TEST_F(ClientClassDefParserTest, bothTestAndTemplateTestExpressions) { + std::string cfg_text = + "{ \n" + " \"name\": \"one\", \n" + " \"test\": \"true\", \n" + " \"template-test\": \"\" \n" + "} \n"; + + ClientClassDefPtr cclass; + ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET), + DhcpConfigError); +} + // Verifies that a class with invalid option-def, fails to parse. TEST_F(ClientClassDefParserTest, invalidOptionDef) { std::string cfg_text = @@ -1187,15 +1222,15 @@ TEST_F(ClientClassDefListParserTest, templateSimpleValidList) { "[ \n" " { \n" " \"name\": \"one\", \n" - " \"template-class\": true \n" + " \"template-test\": \"''\" \n" " }, \n" " { \n" " \"name\": \"two\", \n" - " \"template-class\": true \n" + " \"template-test\": \"''\" \n" " }, \n" " { \n" " \"name\": \"three\", \n" - " \"template-class\": true \n" + " \"template-test\": \"''\" \n" " } \n" "] \n"; @@ -1257,15 +1292,15 @@ TEST_F(ClientClassDefListParserTest, templateDuplicateClass) { "[ \n" " { \n" " \"name\": \"one\", \n" - " \"template-class\": true \n" + " \"template-test\": \"''\" \n" " }, \n" " { \n" " \"name\": \"two\", \n" - " \"template-class\": true \n" + " \"template-test\": \"''\" \n" " }, \n" " { \n" " \"name\": \"two\", \n" - " \"template-class\": true \n" + " \"template-test\": \"''\" \n" " } \n" "] \n"; diff --git a/src/lib/dhcpsrv/tests/client_class_def_unittest.cc b/src/lib/dhcpsrv/tests/client_class_def_unittest.cc index f0f0e8451f..e7894a52c3 100644 --- a/src/lib/dhcpsrv/tests/client_class_def_unittest.cc +++ b/src/lib/dhcpsrv/tests/client_class_def_unittest.cc @@ -1510,7 +1510,7 @@ TEST(TemplateClientClassDef, unparseDef) { std::string name = "class1"; ExpressionPtr expr; ASSERT_NO_THROW(cclass.reset(new TemplateClientClassDef(name, expr))); - std::string test = "option[12].text == 'foo'"; + std::string test = "option[12].text"; cclass->setTest(test); std::string comment = "bar"; std::string user_context = "{ \"comment\": \"" + comment + "\", "; @@ -1529,11 +1529,10 @@ TEST(TemplateClientClassDef, unparseDef) { // Unparse it std::string expected = "{\n" "\"name\": \"" + name + "\",\n" - "\"test\": \"" + test + "\",\n" + "\"template-test\": \"" + test + "\",\n" "\"only-if-required\": true,\n" "\"next-server\": \"" + next_server + "\",\n" "\"server-hostname\": \"" + sname + "\",\n" - "\"template-class\": true,\n" "\"boot-file-name\": \"" + filename + "\",\n" "\"option-data\": [ ],\n" "\"user-context\": { \"bar\": 1,\n" @@ -1573,7 +1572,7 @@ TEST(ClientClassDictionary, templateUnparseDict) { "\"name\": \"" + name + "\",\n" "\"next-server\": \"0.0.0.0\",\n" "\"server-hostname\": \"\",\n" - "\"template-class\": true,\n" + "\"template-test\": \"\",\n" "\"boot-file-name\": \"\",\n" "\"option-data\": [ ] }"); }; |