diff --git a/src/lib/dhcp/libdhcp++.cc b/src/lib/dhcp/libdhcp++.cc index a3921cc6b6..14844583ac 100644 --- a/src/lib/dhcp/libdhcp++.cc +++ b/src/lib/dhcp/libdhcp++.cc @@ -329,10 +329,35 @@ LibDHCP::initStdOptionDefs4() { // Now let's add all option definitions. for (int i = 0; i < OPTION_DEF_PARAMS_SIZE4; ++i) { - OptionDefinitionPtr definition(new OptionDefinition(OPTION_DEF_PARAMS4[i].name, - OPTION_DEF_PARAMS4[i].code, - OPTION_DEF_PARAMS4[i].type, - OPTION_DEF_PARAMS4[i].array)); + std::string encapsulates(OPTION_DEF_PARAMS4[i].encapsulates); + if (!encapsulates.empty() && OPTION_DEF_PARAMS4[i].array) { + isc_throw(isc::BadValue, "invalid standard option definition: " + << "option with code '" << OPTION_DEF_PARAMS4[i].code + << "' may not encapsulate option space '" + << encapsulates << "' because the definition" + << " indicates that this option comprises an array" + << " of values"); + } + + // Depending whether the option encapsulates an option space or not + // we pick different constructor to create an instance of the option + // definition. + OptionDefinitionPtr definition; + if (encapsulates.empty()) { + // Option does not encapsulate any option space. + definition.reset(new OptionDefinition(OPTION_DEF_PARAMS4[i].name, + OPTION_DEF_PARAMS4[i].code, + OPTION_DEF_PARAMS4[i].type, + OPTION_DEF_PARAMS4[i].array)); + + } else { + // Option does encapsulate an option space. + definition.reset(new OptionDefinition(OPTION_DEF_PARAMS4[i].name, + OPTION_DEF_PARAMS4[i].code, + OPTION_DEF_PARAMS4[i].type, + OPTION_DEF_PARAMS4[i].encapsulates)); + + } for (int rec = 0; rec < OPTION_DEF_PARAMS4[i].records_size; ++rec) { definition->addRecordField(OPTION_DEF_PARAMS4[i].records[rec]); @@ -358,10 +383,34 @@ LibDHCP::initStdOptionDefs6() { v6option_defs_.clear(); for (int i = 0; i < OPTION_DEF_PARAMS_SIZE6; ++i) { - OptionDefinitionPtr definition(new OptionDefinition(OPTION_DEF_PARAMS6[i].name, - OPTION_DEF_PARAMS6[i].code, - OPTION_DEF_PARAMS6[i].type, - OPTION_DEF_PARAMS6[i].array)); + std::string encapsulates(OPTION_DEF_PARAMS6[i].encapsulates); + if (!encapsulates.empty() && OPTION_DEF_PARAMS6[i].array) { + isc_throw(isc::BadValue, "invalid standard option definition: " + << "option with code '" << OPTION_DEF_PARAMS6[i].code + << "' may not encapsulate option space '" + << encapsulates << "' because the definition" + << " indicates that this option comprises an array" + << " of values"); + } + + // Depending whether an option encapsulates an option space or not + // we pick different constructor to create an instance of the option + // definition. + OptionDefinitionPtr definition; + if (encapsulates.empty()) { + // Option does not encapsulate any option space. + definition.reset(new OptionDefinition(OPTION_DEF_PARAMS6[i].name, + OPTION_DEF_PARAMS6[i].code, + OPTION_DEF_PARAMS6[i].type, + OPTION_DEF_PARAMS6[i].array)); + } else { + // Option does encapsulate an option space. + definition.reset(new OptionDefinition(OPTION_DEF_PARAMS6[i].name, + OPTION_DEF_PARAMS6[i].code, + OPTION_DEF_PARAMS6[i].type, + OPTION_DEF_PARAMS6[i].encapsulates)); + + } for (int rec = 0; rec < OPTION_DEF_PARAMS6[i].records_size; ++rec) { definition->addRecordField(OPTION_DEF_PARAMS6[i].records[rec]); diff --git a/src/lib/dhcp/std_option_defs.h b/src/lib/dhcp/std_option_defs.h index 144df8b875..839a5d9827 100644 --- a/src/lib/dhcp/std_option_defs.h +++ b/src/lib/dhcp/std_option_defs.h @@ -50,6 +50,8 @@ struct OptionDefParams { bool array; // is array const OptionDataType* records; // record fields size_t records_size; // number of fields in a record + const char* encapsulates; // option space encapsulated by + // the particular option. }; // fqdn option record fields. @@ -64,128 +66,128 @@ RECORD_DECL(FQDN_RECORDS, OPT_UINT8_TYPE, OPT_UINT8_TYPE, OPT_STRING_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 }, - { "time-offset", DHO_TIME_OFFSET, OPT_UINT32_TYPE, false, NO_RECORD_DEF }, - { "routers", DHO_ROUTERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, - { "time-servers", DHO_TIME_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, + { "subnet-mask", DHO_SUBNET_MASK, OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" }, + { "time-offset", DHO_TIME_OFFSET, OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, + { "routers", DHO_ROUTERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, + { "time-servers", DHO_TIME_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "name-servers", DHO_NAME_SERVERS, OPT_IPV4_ADDRESS_TYPE, - false, NO_RECORD_DEF }, + false, NO_RECORD_DEF, "" }, { "domain-name-servers", DHO_DOMAIN_NAME_SERVERS, - OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, - { "log-servers", DHO_LOG_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, + { "log-servers", DHO_LOG_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "cookie-servers", DHO_COOKIE_SERVERS, OPT_IPV4_ADDRESS_TYPE, - true, NO_RECORD_DEF }, - { "lpr-servers", DHO_LPR_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, - { "impress-servers", DHO_IMPRESS_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, + true, NO_RECORD_DEF, "" }, + { "lpr-servers", DHO_LPR_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, + { "impress-servers", DHO_IMPRESS_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "resource-location-servers", DHO_RESOURCE_LOCATION_SERVERS, - OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, - { "host-name", DHO_HOST_NAME, OPT_STRING_TYPE, false, NO_RECORD_DEF }, - { "boot-size", DHO_BOOT_SIZE, OPT_UINT16_TYPE, false, NO_RECORD_DEF }, - { "merit-dump", DHO_MERIT_DUMP, OPT_STRING_TYPE, false, NO_RECORD_DEF }, - { "domain-name", DHO_DOMAIN_NAME, OPT_FQDN_TYPE, false, NO_RECORD_DEF }, - { "swap-server", DHO_SWAP_SERVER, OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF }, - { "root-path", DHO_ROOT_PATH, OPT_STRING_TYPE, false, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, + { "host-name", DHO_HOST_NAME, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" }, + { "boot-size", DHO_BOOT_SIZE, OPT_UINT16_TYPE, false, NO_RECORD_DEF, "" }, + { "merit-dump", DHO_MERIT_DUMP, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" }, + { "domain-name", DHO_DOMAIN_NAME, OPT_FQDN_TYPE, false, NO_RECORD_DEF, "" }, + { "swap-server", DHO_SWAP_SERVER, OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" }, + { "root-path", DHO_ROOT_PATH, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" }, { "extensions-path", DHO_EXTENSIONS_PATH, OPT_STRING_TYPE, - false, NO_RECORD_DEF }, - { "ip-forwarding", DHO_IP_FORWARDING, OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF }, + false, NO_RECORD_DEF, "" }, + { "ip-forwarding", DHO_IP_FORWARDING, OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF, "" }, { "non-local-source-routing", DHO_NON_LOCAL_SOURCE_ROUTING, - OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF }, - { "policy-filter", DHO_POLICY_FILTER, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, + OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF, "" }, + { "policy-filter", DHO_POLICY_FILTER, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "max-dgram-reassembly", DHO_MAX_DGRAM_REASSEMBLY, - OPT_UINT16_TYPE, false, NO_RECORD_DEF }, - { "default-ip-ttl", DHO_DEFAULT_IP_TTL, OPT_UINT8_TYPE, false, NO_RECORD_DEF }, + OPT_UINT16_TYPE, false, NO_RECORD_DEF, "" }, + { "default-ip-ttl", DHO_DEFAULT_IP_TTL, OPT_UINT8_TYPE, false, NO_RECORD_DEF, "" }, { "path-mtu-aging-timeout", DHO_PATH_MTU_AGING_TIMEOUT, - OPT_UINT32_TYPE, false, NO_RECORD_DEF }, + OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, { "path-mtu-plateau-table", DHO_PATH_MTU_PLATEAU_TABLE, - OPT_UINT16_TYPE, true, NO_RECORD_DEF }, - { "interface-mtu", DHO_INTERFACE_MTU, OPT_UINT16_TYPE, false, NO_RECORD_DEF }, + OPT_UINT16_TYPE, true, NO_RECORD_DEF, "" }, + { "interface-mtu", DHO_INTERFACE_MTU, OPT_UINT16_TYPE, false, NO_RECORD_DEF, "" }, { "all-subnets-local", DHO_ALL_SUBNETS_LOCAL, - OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF }, + OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF, "" }, { "broadcast-address", DHO_BROADCAST_ADDRESS, - OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" }, { "perform-mask-discovery", DHO_PERFORM_MASK_DISCOVERY, - OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF }, - { "mask-supplier", DHO_MASK_SUPPLIER, OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF }, + OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF, "" }, + { "mask-supplier", DHO_MASK_SUPPLIER, OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF, "" }, { "router-discovery", DHO_ROUTER_DISCOVERY, - OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF }, + OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF, "" }, { "router-solicitation-address", DHO_ROUTER_SOLICITATION_ADDRESS, - OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" }, { "static-routes", DHO_STATIC_ROUTES, - OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "trailer-encapsulation", DHO_TRAILER_ENCAPSULATION, - OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF }, + OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF, "" }, { "arp-cache-timeout", DHO_ARP_CACHE_TIMEOUT, - OPT_UINT32_TYPE, false, NO_RECORD_DEF }, + OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, { "ieee802-3-encapsulation", DHO_IEEE802_3_ENCAPSULATION, - OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF }, - { "default-tcp-ttl", DHO_DEFAULT_TCP_TTL, OPT_UINT8_TYPE, false, NO_RECORD_DEF }, + OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF, "" }, + { "default-tcp-ttl", DHO_DEFAULT_TCP_TTL, OPT_UINT8_TYPE, false, NO_RECORD_DEF, "" }, { "tcp-keepalive-internal", DHO_TCP_KEEPALIVE_INTERVAL, - OPT_UINT32_TYPE, false, NO_RECORD_DEF }, + OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, { "tcp-keepalive-garbage", DHO_TCP_KEEPALIVE_GARBAGE, - OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF }, - { "nis-domain", DHO_NIS_DOMAIN, OPT_STRING_TYPE, false, NO_RECORD_DEF }, - { "nis-servers", DHO_NIS_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, - { "ntp-servers", DHO_NTP_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, + OPT_BOOLEAN_TYPE, false, NO_RECORD_DEF, "" }, + { "nis-domain", DHO_NIS_DOMAIN, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" }, + { "nis-servers", DHO_NIS_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, + { "ntp-servers", DHO_NTP_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "vendor-encapsulated-options", DHO_VENDOR_ENCAPSULATED_OPTIONS, - OPT_BINARY_TYPE, false, NO_RECORD_DEF }, + OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "vendor-encapsulated-options-space" }, { "netbios-name-servers", DHO_NETBIOS_NAME_SERVERS, - OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "netbios-dd-server", DHO_NETBIOS_DD_SERVER, - OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "netbios-node-type", DHO_NETBIOS_NODE_TYPE, - OPT_UINT8_TYPE, false, NO_RECORD_DEF }, - { "netbios-scope", DHO_NETBIOS_SCOPE, OPT_STRING_TYPE, false, NO_RECORD_DEF }, - { "font-servers", DHO_FONT_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, + OPT_UINT8_TYPE, false, NO_RECORD_DEF, "" }, + { "netbios-scope", DHO_NETBIOS_SCOPE, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" }, + { "font-servers", DHO_FONT_SERVERS, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "x-display-manager", DHO_X_DISPLAY_MANAGER, - OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "dhcp-requested-address", DHO_DHCP_REQUESTED_ADDRESS, - OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF }, - { "dhcp-lease-time", DHO_DHCP_LEASE_TIME, OPT_UINT32_TYPE, false, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" }, + { "dhcp-lease-time", DHO_DHCP_LEASE_TIME, OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, { "dhcp-option-overload", DHO_DHCP_OPTION_OVERLOAD, - OPT_UINT8_TYPE, false, NO_RECORD_DEF }, - { "dhcp-message-type", DHO_DHCP_MESSAGE_TYPE, OPT_UINT8_TYPE, false, NO_RECORD_DEF }, + OPT_UINT8_TYPE, false, NO_RECORD_DEF, "" }, + { "dhcp-message-type", DHO_DHCP_MESSAGE_TYPE, OPT_UINT8_TYPE, false, NO_RECORD_DEF, "" }, { "dhcp-server-identifier", DHO_DHCP_SERVER_IDENTIFIER, - OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" }, { "dhcp-parameter-request-list", DHO_DHCP_PARAMETER_REQUEST_LIST, - OPT_UINT8_TYPE, true, NO_RECORD_DEF }, - { "dhcp-message", DHO_DHCP_MESSAGE, OPT_STRING_TYPE, false, NO_RECORD_DEF }, + OPT_UINT8_TYPE, true, NO_RECORD_DEF, "" }, + { "dhcp-message", DHO_DHCP_MESSAGE, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" }, { "dhcp-max-message-size", DHO_DHCP_MAX_MESSAGE_SIZE, - OPT_UINT16_TYPE, false, NO_RECORD_DEF }, - { "dhcp-renewal-time", DHO_DHCP_RENEWAL_TIME, OPT_UINT32_TYPE, false, NO_RECORD_DEF }, + OPT_UINT16_TYPE, false, NO_RECORD_DEF, "" }, + { "dhcp-renewal-time", DHO_DHCP_RENEWAL_TIME, OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, { "dhcp-rebinding-time", DHO_DHCP_REBINDING_TIME, - OPT_UINT32_TYPE, false, NO_RECORD_DEF }, + OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, { "vendor-class-identifier", DHO_VENDOR_CLASS_IDENTIFIER, - OPT_BINARY_TYPE, false, NO_RECORD_DEF }, + OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, { "dhcp-client-identifier", DHO_DHCP_CLIENT_IDENTIFIER, - OPT_BINARY_TYPE, false, NO_RECORD_DEF }, - { "nwip-domain-name", DHO_NWIP_DOMAIN_NAME, OPT_STRING_TYPE, false, NO_RECORD_DEF }, - { "nwip-suboptions", DHO_NWIP_SUBOPTIONS, OPT_BINARY_TYPE, false, NO_RECORD_DEF }, - { "user-class", DHO_USER_CLASS, OPT_BINARY_TYPE, false, NO_RECORD_DEF }, - { "fqdn", DHO_FQDN, OPT_RECORD_TYPE, false, RECORD_DEF(FQDN_RECORDS) }, + OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, + { "nwip-domain-name", DHO_NWIP_DOMAIN_NAME, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" }, + { "nwip-suboptions", DHO_NWIP_SUBOPTIONS, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, + { "user-class", DHO_USER_CLASS, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, + { "fqdn", DHO_FQDN, OPT_RECORD_TYPE, false, RECORD_DEF(FQDN_RECORDS), "" }, { "dhcp-agent-options", DHO_DHCP_AGENT_OPTIONS, - OPT_BINARY_TYPE, false, NO_RECORD_DEF }, + OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "dhcp-agent-options-space" }, // Unfortunatelly the AUTHENTICATE option contains a 64-bit // data field called 'replay-detection' that can't be added // as a record field to a custom option. Also, there is no // dedicated option class to handle it so we simply return // binary option type for now. // @todo implement a class to handle AUTH option. - { "authenticate", DHO_AUTHENTICATE, OPT_BINARY_TYPE, false, NO_RECORD_DEF }, + { "authenticate", DHO_AUTHENTICATE, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, { "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 }, + OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, + { "associated-ip", DHO_ASSOCIATED_IP, OPT_IPV4_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "subnet-selection", DHO_SUBNET_SELECTION, - OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF }, + OPT_IPV4_ADDRESS_TYPE, false, NO_RECORD_DEF, "" }, // The following options need a special encoding of data // being carried by them. Therefore, there is no way they can // be handled by OptionCustom. We may need to implement // dedicated classes to handle them. Until that happens // let's treat them as 'binary' options. - { "domain-search", DHO_DOMAIN_SEARCH, OPT_BINARY_TYPE, false, NO_RECORD_DEF }, + { "domain-search", DHO_DOMAIN_SEARCH, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, { "vivco-suboptions", DHO_VIVCO_SUBOPTIONS, - OPT_BINARY_TYPE, false, NO_RECORD_DEF }, + OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, { "vivso-suboptions", DHO_VIVSO_SUBOPTIONS, OPT_BINARY_TYPE, - false, NO_RECORD_DEF } + false, NO_RECORD_DEF, "" } // @todo add definitions for all remaning options. }; @@ -222,8 +224,6 @@ RECORD_DECL(REMOTE_ID_RECORDS, OPT_UINT32_TYPE, OPT_BINARY_TYPE); RECORD_DECL(STATUS_CODE_RECORDS, OPT_UINT16_TYPE, OPT_STRING_TYPE); // vendor-class RECORD_DECL(VENDOR_CLASS_RECORDS, OPT_UINT32_TYPE, OPT_BINARY_TYPE); -// vendor-opts -RECORD_DECL(VENDOR_OPTS_RECORDS, OPT_UINT32_TYPE, OPT_BINARY_TYPE); /// Standard DHCPv6 option definitions. /// @@ -236,84 +236,84 @@ RECORD_DECL(VENDOR_OPTS_RECORDS, OPT_UINT32_TYPE, OPT_BINARY_TYPE); /// warning about lack of initializers for some struct members /// causing build to fail. const OptionDefParams OPTION_DEF_PARAMS6[] = { - { "clientid", D6O_CLIENTID, OPT_BINARY_TYPE, false, NO_RECORD_DEF }, - { "serverid", D6O_SERVERID, OPT_BINARY_TYPE, false, NO_RECORD_DEF }, - { "ia-na", D6O_IA_NA, OPT_RECORD_TYPE, false, RECORD_DEF(IA_NA_RECORDS) }, - { "ia-ta", D6O_IA_TA, OPT_UINT32_TYPE, false, NO_RECORD_DEF }, - { "iaaddr", D6O_IAADDR, OPT_RECORD_TYPE, false, RECORD_DEF(IAADDR_RECORDS) }, - { "oro", D6O_ORO, OPT_UINT16_TYPE, true, NO_RECORD_DEF }, - { "preference", D6O_PREFERENCE, OPT_UINT8_TYPE, false, NO_RECORD_DEF }, - { "elapsed-time", D6O_ELAPSED_TIME, OPT_UINT16_TYPE, false, NO_RECORD_DEF }, - { "relay-msg", D6O_RELAY_MSG, OPT_BINARY_TYPE, false, NO_RECORD_DEF }, + { "clientid", D6O_CLIENTID, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, + { "serverid", D6O_SERVERID, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, + { "ia-na", D6O_IA_NA, OPT_RECORD_TYPE, false, RECORD_DEF(IA_NA_RECORDS), "" }, + { "ia-ta", D6O_IA_TA, OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, + { "iaaddr", D6O_IAADDR, OPT_RECORD_TYPE, false, RECORD_DEF(IAADDR_RECORDS), "" }, + { "oro", D6O_ORO, OPT_UINT16_TYPE, true, NO_RECORD_DEF, "" }, + { "preference", D6O_PREFERENCE, OPT_UINT8_TYPE, false, NO_RECORD_DEF, "" }, + { "elapsed-time", D6O_ELAPSED_TIME, OPT_UINT16_TYPE, false, NO_RECORD_DEF, "" }, + { "relay-msg", D6O_RELAY_MSG, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, // Unfortunatelly the AUTH option contains a 64-bit data field // called 'replay-detection' that can't be added as a record // field to a custom option. Also, there is no dedicated // option class to handle it so we simply return binary // option type for now. // @todo implement a class to handle AUTH option. - { "auth", D6O_AUTH, OPT_BINARY_TYPE, false, NO_RECORD_DEF }, - { "unicast", D6O_UNICAST, OPT_IPV6_ADDRESS_TYPE, false, NO_RECORD_DEF }, + { "auth", D6O_AUTH, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, + { "unicast", D6O_UNICAST, OPT_IPV6_ADDRESS_TYPE, false, NO_RECORD_DEF, "" }, { "status-code", D6O_STATUS_CODE, OPT_RECORD_TYPE, false, - RECORD_DEF(STATUS_CODE_RECORDS) }, - { "rapid-commit", D6O_RAPID_COMMIT, OPT_EMPTY_TYPE, false, NO_RECORD_DEF }, - { "user-class", D6O_USER_CLASS, OPT_BINARY_TYPE, false, NO_RECORD_DEF }, + RECORD_DEF(STATUS_CODE_RECORDS), "" }, + { "rapid-commit", D6O_RAPID_COMMIT, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "" }, + { "user-class", D6O_USER_CLASS, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, { "vendor-class", D6O_VENDOR_CLASS, OPT_RECORD_TYPE, false, - RECORD_DEF(VENDOR_CLASS_RECORDS) }, - { "vendor-opts", D6O_VENDOR_OPTS, OPT_RECORD_TYPE, false, - RECORD_DEF(VENDOR_OPTS_RECORDS) }, - { "interface-id", D6O_INTERFACE_ID, OPT_BINARY_TYPE, false, NO_RECORD_DEF }, - { "reconf-msg", D6O_RECONF_MSG, OPT_UINT8_TYPE, false, NO_RECORD_DEF }, + RECORD_DEF(VENDOR_CLASS_RECORDS), "" }, + { "vendor-opts", D6O_VENDOR_OPTS, OPT_UINT32_TYPE, false, + NO_RECORD_DEF, "vendor-opts-space" }, + { "interface-id", D6O_INTERFACE_ID, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }, + { "reconf-msg", D6O_RECONF_MSG, OPT_UINT8_TYPE, false, NO_RECORD_DEF, "" }, { "reconf-accept", D6O_RECONF_ACCEPT, OPT_EMPTY_TYPE, false, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "sip-server-dns", D6O_SIP_SERVERS_DNS, OPT_FQDN_TYPE, true, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "sip-server-addr", D6O_SIP_SERVERS_ADDR, OPT_IPV6_ADDRESS_TYPE, true, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "dns-servers", D6O_NAME_SERVERS, OPT_IPV6_ADDRESS_TYPE, true, - NO_RECORD_DEF }, - { "domain-search", D6O_DOMAIN_SEARCH, OPT_FQDN_TYPE, true, NO_RECORD_DEF }, - { "ia-pd", D6O_IA_PD, OPT_RECORD_TYPE, false, RECORD_DEF(IA_PD_RECORDS) }, + NO_RECORD_DEF, "" }, + { "domain-search", D6O_DOMAIN_SEARCH, OPT_FQDN_TYPE, true, NO_RECORD_DEF, "" }, + { "ia-pd", D6O_IA_PD, OPT_RECORD_TYPE, false, RECORD_DEF(IA_PD_RECORDS), "" }, { "iaprefix", D6O_IAPREFIX, OPT_RECORD_TYPE, false, - RECORD_DEF(IA_PREFIX_RECORDS) }, + RECORD_DEF(IA_PREFIX_RECORDS), "" }, { "nis-servers", D6O_NIS_SERVERS, OPT_IPV6_ADDRESS_TYPE, true, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "nisp-servers", D6O_NISP_SERVERS, OPT_IPV6_ADDRESS_TYPE, true, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "nis-domain-name", D6O_NIS_DOMAIN_NAME, OPT_FQDN_TYPE, true, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "nisp-domain-name", D6O_NISP_DOMAIN_NAME, OPT_FQDN_TYPE, true, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "sntp-servers", D6O_SNTP_SERVERS, OPT_IPV6_ADDRESS_TYPE, true, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "information-refresh-time", D6O_INFORMATION_REFRESH_TIME, - OPT_UINT32_TYPE, false, NO_RECORD_DEF }, + OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, { "bcmcs-server-dns", D6O_BCMCS_SERVER_D, OPT_FQDN_TYPE, true, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "bcmcs-server-addr", D6O_BCMCS_SERVER_A, OPT_IPV6_ADDRESS_TYPE, true, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "geoconf-civic", D6O_GEOCONF_CIVIC, OPT_RECORD_TYPE, false, - RECORD_DEF(GEOCONF_CIVIC_RECORDS) }, + RECORD_DEF(GEOCONF_CIVIC_RECORDS), "" }, { "remote-id", D6O_REMOTE_ID, OPT_RECORD_TYPE, false, - RECORD_DEF(REMOTE_ID_RECORDS) }, + RECORD_DEF(REMOTE_ID_RECORDS), "" }, { "subscriber-id", D6O_SUBSCRIBER_ID, OPT_BINARY_TYPE, false, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "client-fqdn", D6O_CLIENT_FQDN, OPT_RECORD_TYPE, false, - RECORD_DEF(CLIENT_FQDN_RECORDS) }, + RECORD_DEF(CLIENT_FQDN_RECORDS), "" }, { "pana-agent", D6O_PANA_AGENT, OPT_IPV6_ADDRESS_TYPE, true, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "new-posix-timezone", D6O_NEW_POSIX_TIMEZONE, OPT_STRING_TYPE, false, - NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, { "new-tzdb-timezone", D6O_NEW_TZDB_TIMEZONE, OPT_STRING_TYPE, false, - NO_RECORD_DEF }, - { "ero", D6O_ERO, OPT_UINT16_TYPE, true, NO_RECORD_DEF }, + NO_RECORD_DEF, "" }, + { "ero", D6O_ERO, OPT_UINT16_TYPE, true, NO_RECORD_DEF, "" }, { "lq-query", D6O_LQ_QUERY, OPT_RECORD_TYPE, false, - RECORD_DEF(LQ_QUERY_RECORDS) }, - { "client-data", D6O_CLIENT_DATA, OPT_EMPTY_TYPE, false, NO_RECORD_DEF }, - { "clt-time", D6O_CLT_TIME, OPT_UINT32_TYPE, false, NO_RECORD_DEF }, + RECORD_DEF(LQ_QUERY_RECORDS), "" }, + { "client-data", D6O_CLIENT_DATA, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "" }, + { "clt-time", D6O_CLT_TIME, OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" }, { "lq-relay-data", D6O_LQ_RELAY_DATA, OPT_RECORD_TYPE, false, - RECORD_DEF(LQ_RELAY_DATA_RECORDS) }, + RECORD_DEF(LQ_RELAY_DATA_RECORDS), "" }, { "lq-client-link", D6O_LQ_CLIENT_LINK, OPT_IPV6_ADDRESS_TYPE, true, - NO_RECORD_DEF } + NO_RECORD_DEF, "" } // @todo There is still a bunch of options for which we have to provide // definitions but we don't do it because they are not really diff --git a/src/lib/dhcp/tests/libdhcp++_unittest.cc b/src/lib/dhcp/tests/libdhcp++_unittest.cc index a59da125b9..7ec2210ad8 100644 --- a/src/lib/dhcp/tests/libdhcp++_unittest.cc +++ b/src/lib/dhcp/tests/libdhcp++_unittest.cc @@ -68,12 +68,16 @@ public: /// used to create option instance. /// @param expected_type type of the option created by the /// factory function returned by the option definition. + /// @param encapsulates name of the option space being encapsulated + /// by the option. static void testStdOptionDefs4(const uint16_t code, const OptionBufferConstIter begin, const OptionBufferConstIter end, - const std::type_info& expected_type) { + const std::type_info& expected_type, + const std::string& encapsulates = "") { // Use V4 universe. - testStdOptionDefs(Option::V4, code, begin, end, expected_type); + testStdOptionDefs(Option::V4, code, begin, end, expected_type, + encapsulates); } /// @brief Test DHCPv6 option definition. @@ -88,12 +92,16 @@ public: /// used to create option instance. /// @param expected_type type of the option created by the /// factory function returned by the option definition. + /// @param encapsulates name of the option space being encapsulated + /// by the option. static void testStdOptionDefs6(const uint16_t code, const OptionBufferConstIter begin, const OptionBufferConstIter end, - const std::type_info& expected_type) { + const std::type_info& expected_type, + const std::string& encapsulates = "") { // Use V6 universe. - testStdOptionDefs(Option::V6, code, begin, end, expected_type); + testStdOptionDefs(Option::V6, code, begin, end, expected_type, + encapsulates); } private: @@ -109,11 +117,14 @@ private: /// used to create option instance. /// @param expected_type type of the option created by the /// factory function returned by the option definition. + /// @param encapsulates name of the option space being encapsulated + /// by the option. static void testStdOptionDefs(const Option::Universe u, const uint16_t code, const OptionBufferConstIter begin, const OptionBufferConstIter end, - const std::type_info& expected_type) { + const std::type_info& expected_type, + const std::string& encapsulates) { // Get all option definitions, we will use them to extract // the definition for a particular option code. // We don't have to initialize option definitions here because they @@ -141,6 +152,9 @@ private: ASSERT_NO_THROW(def->validate()) << "Option definition for the option code " << code << " is invalid"; + // Check that the valid encapsulated option space name + // has been specified. + EXPECT_EQ(encapsulates, def->getEncapsulatedSpace()); OptionPtr option; // Create the option. ASSERT_NO_THROW(option = def->optionFactory(u, code, begin, end)) @@ -648,7 +662,8 @@ TEST_F(LibDhcpTest, stdOptionDefs4) { typeid(Option4AddrLst)); LibDhcpTest::testStdOptionDefs4(DHO_VENDOR_ENCAPSULATED_OPTIONS, begin, end, - typeid(Option)); + typeid(Option), + "vendor-encapsulated-options-space"); LibDhcpTest::testStdOptionDefs4(DHO_NETBIOS_NAME_SERVERS, begin, end, typeid(Option4AddrLst)); @@ -717,7 +732,7 @@ TEST_F(LibDhcpTest, stdOptionDefs4) { typeid(OptionCustom)); LibDhcpTest::testStdOptionDefs4(DHO_DHCP_AGENT_OPTIONS, begin, end, - typeid(Option)); + typeid(Option), "dhcp-agent-options-space"); LibDhcpTest::testStdOptionDefs4(DHO_AUTHENTICATE, begin, end, typeid(Option)); @@ -816,7 +831,8 @@ TEST_F(LibDhcpTest, stdOptionDefs6) { typeid(OptionCustom)); LibDhcpTest::testStdOptionDefs6(D6O_VENDOR_OPTS, begin, end, - typeid(OptionCustom)); + typeid(OptionInt), + "vendor-opts-space"); LibDhcpTest::testStdOptionDefs6(D6O_INTERFACE_ID, begin, end, typeid(Option));