|
@@ -26,6 +26,7 @@
|
|
|
#include <dhcp/option_int_array.h>
|
|
|
#include <dhcp/option_space.h>
|
|
|
#include <dhcp/option_string.h>
|
|
|
+#include <dhcp/option_vendor.h>
|
|
|
#include <util/encode/hex.h>
|
|
|
#include <util/strutil.h>
|
|
|
#include <boost/algorithm/string/classification.hpp>
|
|
@@ -115,7 +116,19 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
|
|
|
OptionBufferConstIter begin,
|
|
|
OptionBufferConstIter end,
|
|
|
UnpackOptionsCallback callback) const {
|
|
|
+
|
|
|
try {
|
|
|
+ // Some of the options are represented by the specialized classes derived
|
|
|
+ // from Option class (e.g. IA_NA, IAADDR). Although, they can be also
|
|
|
+ // represented by the generic classes, we want the object of the specialized
|
|
|
+ // type to be returned. Therefore, we first check that if we are dealing
|
|
|
+ // with such an option. If the instance is returned we just exit at this
|
|
|
+ // point. If not, we will search for a generic option type to return.
|
|
|
+ OptionPtr option = factorySpecialFormatOption(u, begin, end, callback);
|
|
|
+ if (option) {
|
|
|
+ return (option);
|
|
|
+ }
|
|
|
+
|
|
|
switch(type_) {
|
|
|
case OPT_EMPTY_TYPE:
|
|
|
return (factoryEmpty(u, type));
|
|
@@ -180,37 +193,10 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
|
|
|
return (OptionPtr(new OptionString(u, type, begin, end)));
|
|
|
|
|
|
default:
|
|
|
- if (u == Option::V6) {
|
|
|
- if ((code_ == D6O_IA_NA || code_ == D6O_IA_PD) &&
|
|
|
- haveIA6Format()) {
|
|
|
- // Return Option6IA instance for IA_PD and IA_NA option
|
|
|
- // types only. We don't want to return Option6IA for other
|
|
|
- // options that comprise 3 UINT32 data fields because
|
|
|
- // Option6IA accessors' and modifiers' names are derived
|
|
|
- // from the IA_NA and IA_PD options' field names: IAID,
|
|
|
- // T1, T2. Using functions such as getIAID, getT1 etc. for
|
|
|
- // options other than IA_NA and IA_PD would be bad practice
|
|
|
- // and cause confusion.
|
|
|
- return (factoryIA6(type, begin, end));
|
|
|
-
|
|
|
- } else if (code_ == D6O_IAADDR && haveIAAddr6Format()) {
|
|
|
- // Rerurn Option6IAAddr option instance for the IAADDR
|
|
|
- // option only for the same reasons as described in
|
|
|
- // for IA_NA and IA_PD above.
|
|
|
- return (factoryIAAddr6(type, begin, end));
|
|
|
- } else if (code_ == D6O_CLIENT_FQDN && haveClientFqdnFormat()) {
|
|
|
- // FQDN option requires special processing. Thus, there is
|
|
|
- // a specialized class to handle it.
|
|
|
- return (OptionPtr(new Option6ClientFqdn(begin, end)));
|
|
|
- }
|
|
|
- } else {
|
|
|
- if ((code_ == DHO_FQDN) && haveFqdn4Format()) {
|
|
|
- return (OptionPtr(new Option4ClientFqdn(begin, end)));
|
|
|
- }
|
|
|
- }
|
|
|
+ // Do nothing. We will return generic option a few lines down.
|
|
|
+ ;
|
|
|
}
|
|
|
return (OptionPtr(new OptionCustom(*this, u, begin, end)));
|
|
|
-
|
|
|
} catch (const Exception& ex) {
|
|
|
isc_throw(InvalidOptionValue, ex.what());
|
|
|
}
|
|
@@ -568,6 +554,45 @@ OptionDefinition::factoryIAAddr6(uint16_t type,
|
|
|
return (option);
|
|
|
}
|
|
|
|
|
|
+OptionPtr
|
|
|
+OptionDefinition::factorySpecialFormatOption(Option::Universe u,
|
|
|
+ OptionBufferConstIter begin,
|
|
|
+ OptionBufferConstIter end,
|
|
|
+ UnpackOptionsCallback) const {
|
|
|
+ if (u == Option::V6) {
|
|
|
+ if ((getCode() == D6O_IA_NA || getCode() == D6O_IA_PD) &&
|
|
|
+ haveIA6Format()) {
|
|
|
+ // Return Option6IA instance for IA_PD and IA_NA option
|
|
|
+ // types only. We don't want to return Option6IA for other
|
|
|
+ // options that comprise 3 UINT32 data fields because
|
|
|
+ // Option6IA accessors' and modifiers' names are derived
|
|
|
+ // from the IA_NA and IA_PD options' field names: IAID,
|
|
|
+ // T1, T2. Using functions such as getIAID, getT1 etc. for
|
|
|
+ // options other than IA_NA and IA_PD would be bad practice
|
|
|
+ // and cause confusion.
|
|
|
+ return (factoryIA6(getCode(), begin, end));
|
|
|
+
|
|
|
+ } else if (getCode() == D6O_IAADDR && haveIAAddr6Format()) {
|
|
|
+ // Rerurn Option6IAAddr option instance for the IAADDR
|
|
|
+ // option only for the same reasons as described in
|
|
|
+ // for IA_NA and IA_PD above.
|
|
|
+ return (factoryIAAddr6(getCode(), begin, end));
|
|
|
+ } else if (getCode() == D6O_CLIENT_FQDN && haveClientFqdnFormat()) {
|
|
|
+ // FQDN option requires special processing. Thus, there is
|
|
|
+ // a specialized class to handle it.
|
|
|
+ return (OptionPtr(new Option6ClientFqdn(begin, end)));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if ((getCode() == DHO_FQDN) && haveFqdn4Format()) {
|
|
|
+ return (OptionPtr(new Option4ClientFqdn(begin, end)));
|
|
|
+
|
|
|
+ } else if (getCode() == DHO_VIVSO_SUBOPTIONS) {
|
|
|
+ return (OptionPtr(new OptionVendor(Option::V4, begin, end)));
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return (OptionPtr());
|
|
|
+}
|
|
|
|
|
|
} // end of isc::dhcp namespace
|
|
|
} // end of isc namespace
|