Browse Source

[master] Finished merge of (hex in integer options)

Francis Dupont 8 years ago
parent
commit
4cbf341f41

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+1242.	[func]		fdupont
+	Integer fields in options can now be specified in either
+	decimal or hexadecimal format.
+	(Trac $4540, git xxx)
+
 1241.	[func]		fdupont
 1241.	[func]		fdupont
 	Support for tuple-based options added. DHCPv6 option
 	Support for tuple-based options added. DHCPv6 option
 	bootfile-param (code 60) can now be set in a more convenient
 	bootfile-param (code 60) can now be set in a more convenient

+ 79 - 32
doc/examples/kea4/multiple-options.json

@@ -1,34 +1,35 @@
-# This is an example configuration file for the DHCPv4 server in Kea.
-# It demonstrates simple configuration of the options for a subnet.
+// This is an example configuration file for the DHCPv4 server in Kea.
+// It demonstrates simple configuration of the options for a subnet.
 
 
 { "Dhcp4":
 { "Dhcp4":
 
 
 {
 {
-# Kea is told to listen on ethX interface only.
+// Kea is told to listen on ethX interface only.
   "interfaces-config": {
   "interfaces-config": {
     "interfaces": [ "ethX" ]
     "interfaces": [ "ethX" ]
   },
   },
 
 
-# We need to specify the the database used to store leases. As of
-# September 2016, four database backends are supported: MySQL,
-# PostgreSQL, Cassandra, and the in-memory database, Memfile.
-# We'll use memfile  because it doesn't require any prior set up.
+// We need to specify the the database used to store leases. As of
+// September 2016, four database backends are supported: MySQL,
+// PostgreSQL, Cassandra, and the in-memory database, Memfile.
+// We'll use memfile  because it doesn't require any prior set up.
   "lease-database": {
   "lease-database": {
     "type": "memfile"
     "type": "memfile"
   },
   },
 
 
-# Addresses will be assigned with a lifetime of 4000 seconds.
+// Addresses will be assigned with a lifetime of 4000 seconds.
   "valid-lifetime": 4000,
   "valid-lifetime": 4000,
 
 
-# Renew and rebind timers are commented out. This implies that options
-# 58 and 59 will not be sent to the client. In this case it is up to
-# the client to pick the timer values according to RFC2131. Uncomment the
-# timers to send these options to the client.
-#  "renew-timer": 1000,
-#  "rebind-timer": 2000,
+// Renew and rebind timers are commented out. This implies that options
+// 58 and 59 will not be sent to the client. In this case it is up to
+// the client to pick the timer values according to RFC2131. Uncomment the
+// timers to send these options to the client.
+//  "renew-timer": 1000,
+//  "rebind-timer": 2000,
 
 
-// Defining a subnet. There are 3 DHCP options returned to the
+// Defining a subnet. There are some DHCP options returned to the
 // clients connected to this subnet. The first and third options are
 // clients connected to this subnet. The first and third options are
+// clients connected to this subnet. The first two options are
 // identified by the name. The third option is identified by the
 // identified by the name. The third option is identified by the
 // option code.
 // option code.
   "subnet4": [
   "subnet4": [
@@ -37,39 +38,85 @@
        "subnet": "192.0.2.0/24",
        "subnet": "192.0.2.0/24",
        "interface": "ethX",
        "interface": "ethX",
        "option-data": [
        "option-data": [
+            // When specifying options, you typically need to specify
+            // one of (name or code) and data. The full option specification
+            // covers name, code, space, csv-format and data.
+            // space defaults to "dhcp4" which is usually correct, unless you
+            // use encapsulate options. csv-format defaults to "true", so
+            // this is also correct, unless you want to specify the whole
+            // option value as long hex string. For example, to specify
+            // domain-name-servers you could do this:
+            // {
+            //     "name": "domain-name-servers",
+            //     "code": 6,
+            //     "csv-format": "true",
+            //     "space": "dhcp4",
+            //     "data": "192.0.2.1, 192.0.2.2"
+            // }
+            // but it's a lot of writing, so it's easier to do this instead:
          {
          {
              "name": "domain-name-servers",
              "name": "domain-name-servers",
              "data": "192.0.2.1, 192.0.2.2"
              "data": "192.0.2.1, 192.0.2.2"
          },
          },
+            // Note the Kea provides some of the options on its own. In
+            // particular:
+            // - IP address lease time (option 51) is governed by valid-lifetime
+            //   parameter, so you don't need to specify it as option.
+            // - Subnet mask (option 1) is calculated automatically from the
+            //   subnet parameter specified for each "subnet4" entry.
+            // - renewal-timer (option 58) is calculated from renew-timer
+            //   parameter
+            // - rebind timer (option 59) is calculated from rebind-timer
+            //   parameter
+
+            // For each IPv4 subnet you most likely need to specify at least
+            // one router.
          {
          {
              "name": "routers",
              "name": "routers",
              "data": "192.0.2.1"
              "data": "192.0.2.1"
          },
          },
+            // Typically people prefer to refer to options by their names, so they
+            // don't need to remember the code names. However, some people like
+            // to use numerical values. For example, option "domain-name" uses
+            // option code 15, so you can reference to it either by
+            // "name": "domain-name" or "code": 15.
+         {
+             "code": 15,
+             "data": "example.org"
+         },
+            // String options that have a comma in their values need to have
+            // it escaped (i.e. each comma is predeced by two backslashes).
+            // That's because commas are reserved for separating fields in
+            // compound options. At the same time, we need to be conformant
+            // with JSON spec, that does not allow "\,". Therefore the
+            // slightly uncommon double backslashes notation is needed.
+
+            // Legal JSON escapes are \ followed by "\/bfnrt character
+            // or \u followed by 4 hexa-decimal numbers (currently Kea
+            // supports only \u0000 to \u00ff code points).
+            // CSV processing translates '\\' into '\' and '\,' into ','
+            // only so for instance '\x' is translated into '\x'. But
+            // as it works on a JSON string value each of these '\'
+            // characters must be doubled on JSON input.
          {
          {
-             // String options that have a comma in their values need to have
-             // it escaped (i.e. each comma is predeced by two backslashes).
-             // That's because commas are reserved for separating fields in
-             // compound options. At the same time, we need to be conformant
-             // with JSON spec, that does not allow "\,". Therefore the
-             // slightly uncommon double backslashes notation is needed.
-             "name": "boot-file-name",
-             "data": "EST5EDT4\\,M3.2.0/02:00\\,M11.1.0/02:00"
+            "name": "boot-file-name",
+            "data": "EST5EDT4\\,M3.2.0/02:00\\,M11.1.0/02:00"
 
 
-             // Legal JSON escapes are \ followed by "\/bfnrt character
-             // or \u followed by 4 hexa-decimal numbers (currently Kea
-             // supports only \u0000 to \u00ff code points).
-             // CSV processing translates '\\' into '\' and '\,' into ','
-             // only so for instance '\x' is translated into '\x'. But
-             // as it works on a JSON string value each of these '\'
-             // characters must be doubled on JSON input.
+         },
+            // Options that take integer values can either be specified in
+            // dec or hex format. Hex format could be either plain (e.g. abcd)
+            // or prefixed with 0x (e.g. 0xabcd).
+         {
+            "name": "default-ip-ttl",
+            "data": "0xf0"
          }
          }
        ]
        ]
     } 
     } 
   ]
   ]
 },
 },
 
 
-# The following configures logging. It assumes that messages with at least
-# informational level (info, warn, error and fatal) should be logged to stdout.
+// The following configures logging. It assumes that messages with at least
+// informational level (info, warn, error and fatal) should be logged to stdout.
 "Logging": {
 "Logging": {
     "loggers": [
     "loggers": [
         {
         {

+ 79 - 45
doc/examples/kea6/multiple-options.json

@@ -1,66 +1,88 @@
-# This is an example configuration file for DHCPv6 server in Kea.
-# It demonstrates simple configuration of the options for a subnet.
+// This is an example configuration file for DHCPv6 server in Kea.
+// It demonstrates simple configuration of the options for a subnet.
 
 
 { "Dhcp6":
 { "Dhcp6":
 
 
 {
 {
-# Kea is told to listen on ethX interface only.
+// Kea is told to listen on ethX interface only.
   "interfaces-config": {
   "interfaces-config": {
     "interfaces": [ "ethX" ]
     "interfaces": [ "ethX" ]
   },
   },
 
 
-# We need to specify the the database used to store leases. As of
-# September 2016, four database backends are supported: MySQL,
-# PostgreSQL, Cassandra, and the in-memory database, Memfile.
-# We'll use memfile  because it doesn't require any prior set up.
+// We need to specify the the database used to store leases. As of
+// September 2016, four database backends are supported: MySQL,
+// PostgreSQL, Cassandra, and the in-memory database, Memfile.
+// We'll use memfile  because it doesn't require any prior set up.
   "lease-database": {
   "lease-database": {
     "type": "memfile"
     "type": "memfile"
   },
   },
 
 
-# Addresses will be assigned with preferred and valid lifetimes
-# being 3000 and 4000, respectively. Client is told to start
-# renewing after 1000 seconds. If the server does not respond
-# after 2000 seconds since the lease was granted, client is supposed
-# to start REBIND procedure (emergency renewal that allows switching
-# to a different server).
+// Addresses will be assigned with preferred and valid lifetimes
+// being 3000 and 4000, respectively. Client is told to start
+// renewing after 1000 seconds. If the server does not respond
+// after 2000 seconds since the lease was granted, client is supposed
+// to start REBIND procedure (emergency renewal that allows switching
+// to a different server).
   "preferred-lifetime": 3000,
   "preferred-lifetime": 3000,
   "valid-lifetime": 4000,
   "valid-lifetime": 4000,
   "renew-timer": 1000,
   "renew-timer": 1000,
   "rebind-timer": 2000,
   "rebind-timer": 2000,
 
 
-# Defining a subnet. There are 3 DHCP options returned to the
-# clients connected to this subnet. The first option is identified
-# by the name. The second option is identified by the code.
-# There are two address pools defined within this subnet. Pool
-# specific value for option 12 is defined for the pool:
-# 2001:db8:1::1 - 2001:db8:1::100. Clients obtaining an address
-# from this pool will be assigned option 12 with a value of
-# 3001:cafe::21. Clients belonging to this subnet but obtaining
-# addresses from the other pool, or the clients obtaining
-# stateless configuration will be assigned subnet specific value
-# of option 12, i.e. 2001:db8:1:0:ff00::1.
-# For DHCPv6 subnets can have prefix delegation pools too so
-# a pd-pools with an option-data is defined too.
+// Defining a subnet. There are some DHCP options returned to the
+// clients connected to this subnet. The first option is identified
+// by the name. The second option is identified by the code.
+// There are two address pools defined within this subnet. Pool
+// specific value for option 12 is defined for the pool:
+// 2001:db8:1::1 - 2001:db8:1::100. Clients obtaining an address
+// from this pool will be assigned option 12 with a value of
+// 3001:cafe::21. Clients belonging to this subnet but obtaining
+// addresses from the other pool, or the clients obtaining
+// stateless configuration will be assigned subnet specific value
+// of option 12, i.e. 2001:db8:1:0:ff00::1.
+// For DHCPv6 subnets can have prefix delegation pools too so
+// a pd-pools with an option-data is defined too.
   "subnet6": [
   "subnet6": [
     {
     {
-      "option-data": [
-        {
-            "name": "dns-servers",
-            "data": "2001:db8:2::45, 2001:db8:2::100"
-        },
-        {
-            "code": 12,
-            "data": "2001:db8:1:0:ff00::1"
-        },
-        {
+        // This is how option values are defined for this particular subnet.
+        "option-data": [
+            // When specifying options, you typically need to specify
+            // one of (name or code) and data. The full option specification
+            // covers name, code, space, csv-format and data.
+            // space defaults to "dhcp6" which is usually correct, unless you
+            // use encapsulate options. csv-format defaults to "true", so
+            // this is also correct, unless you want to specify the whole
+            // option value as long hex string. For example, to specify
+            // domain-name-servers you could do this:
+            // {
+            //     "name": "dns-servers",
+            //     "code": 23,
+            //     "csv-format": "true",
+            //     "space": "dhcp6",
+            //     "data": "2001:db8:2::45, 2001:db8:2::100"
+            // }
+            // but it's a lot of writing, so it's easier to do this instead:
+            {
+                "name": "dns-servers",
+                "data": "2001:db8:2::45, 2001:db8:2::100"
+            },
+
+            // Typically people prefer to refer to options by their names, so they
+            // don't need to remember the code names. However, some people like
+            // to use numerical values. For example, DHCPv6 can optionally use
+            // server unicast communication, if extra option is present. Option
+            // "unicast" uses option code 12, so you can reference to it either
+            // by "name": "unicast" or "code": 12.
+            {
+                "code": 12,
+                "data": "2001:db8:1:0:ff00::1"
+            },
+
             // String options that have a comma in their values need to have
             // String options that have a comma in their values need to have
             // it escaped (i.e. each comma is predeced by two backslashes).
             // it escaped (i.e. each comma is predeced by two backslashes).
             // That's because commas are reserved for separating fields in
             // That's because commas are reserved for separating fields in
             // compound options. At the same time, we need to be conformant
             // compound options. At the same time, we need to be conformant
             // with JSON spec, that does not allow "\,". Therefore the
             // with JSON spec, that does not allow "\,". Therefore the
             // slightly uncommon double backslashes notation is needed.
             // slightly uncommon double backslashes notation is needed.
-            "name": "new-posix-timezone",
-            "data": "EST5EDT4\\,M3.2.0/02:00\\,M11.1.0/02:00"
 
 
             // Legal JSON escapes are \ followed by "\/bfnrt character
             // Legal JSON escapes are \ followed by "\/bfnrt character
             // or \u followed by 4 hexa-decimal numbers (currently Kea
             // or \u followed by 4 hexa-decimal numbers (currently Kea
@@ -69,14 +91,26 @@
             // only so for instance '\x' is translated into '\x'. But
             // only so for instance '\x' is translated into '\x'. But
             // as it works on a JSON string value each of these '\'
             // as it works on a JSON string value each of these '\'
             // characters must be doubled on JSON input.
             // characters must be doubled on JSON input.
-        },
-        {
+            {
+                "name": "new-posix-timezone",
+                "data": "EST5EDT4\\,M3.2.0/02:00\\,M11.1.0/02:00"
+            },
+
+            // Options that take integer values can either be specified in
+            // dec or hex format. Hex format could be either plain (e.g. abcd)
+            // or prefixed with 0x (e.g. 0xabcd).
+            {
+                "name": "preference",
+                "data": "0xf0"
+            },
+
             // A few options are encoded in (length, string) tuples
             // A few options are encoded in (length, string) tuples
             // which can be defined using only strings as the CSV
             // which can be defined using only strings as the CSV
             // processing computes lengths.
             // processing computes lengths.
-            "name": "bootfile-param",
-            "data": "root=/dev/sda2, quiet, splash"
-        }
+            {
+                "name": "bootfile-param",
+                "data": "root=/dev/sda2, quiet, splash"
+            }
       ],
       ],
       "pools": [
       "pools": [
         {
         {
@@ -111,8 +145,8 @@
   ]
   ]
 },
 },
 
 
-# The following configures logging. It assumes that messages with at least
-# informational level (info, warn, error and fatal) should be logged to stdout.
+// The following configures logging. It assumes that messages with at least
+// informational level (info, warn, error and fatal) should be logged to stdout.
 "Logging": {
 "Logging": {
     "loggers": [
     "loggers": [
         {
         {

+ 36 - 41
doc/guide/dhcp4-srv.xml

@@ -957,22 +957,38 @@ temporarily override a list of interface names and listen on all interfaces.
         ...
         ...
     ]
     ]
 }
 }
-</screen>
+        </screen>
+        Note that only one of name or code is required, you don't need to
+        specify both. Space has a default value of "dhcp4", so you can skip this
+        as well if you define a regular (not encapsulated) DHCPv4 option.
+        Finally, csv-format defaults to true, so it too can be skipped, unless
+        you want to specify the option value as hexstring. Therefore the
+        above example can be simplified to:
+        <screen>
+"Dhcp4": {
+    "option-data": [
+        {
+           <userinput>"name": "domain-name-servers",
+           "data": "192.0.2.1, 192.0.2.2"</userinput>
+        },
+        ...
+    ]
+} </screen>
+
       </para>
       </para>
     <para>
     <para>
-      The <command>name</command> parameter specifies the
-      option name. For a list of currently supported names, see
-      <xref linkend="dhcp4-std-options-list"/> below.
-      The <command>code</command> parameter specifies the option code, which must match one of the
-      values from that list. The next line specifies the option space, which must always
-      be set to "dhcp4" as these are standard DHCPv4 options. For
-      other option spaces, including custom option spaces, see <xref
+      The <command>name</command> parameter specifies the option name. For a
+      list of currently supported names, see <xref
+      linkend="dhcp4-std-options-list"/> below.  The <command>code</command>
+      parameter specifies the option code, which must match one of the values
+      from that list. The next line specifies the option space, which must
+      always be set to "dhcp4" as these are standard DHCPv4 options. For other
+      option spaces, including custom option spaces, see <xref
       linkend="dhcp4-option-spaces"/>. The next line specifies the format in
       linkend="dhcp4-option-spaces"/>. The next line specifies the format in
-      which the data will be entered: use of CSV (comma
-      separated values) is recommended. The sixth line gives the actual value to
-      be sent to clients. Data is specified as normal text, with
-      values separated by commas if more than one value is
-      allowed.
+      which the data will be entered: use of CSV (comma separated values) is
+      recommended. The sixth line gives the actual value to be sent to
+      clients. Data is specified as normal text, with values separated by commas
+      if more than one value is allowed.
     </para>
     </para>
 
 
     <para>
     <para>
@@ -1043,8 +1059,7 @@ temporarily override a list of interface names and listen on all interfaces.
 
 
       <para>
       <para>
         The currently supported standard DHCPv4 options are
         The currently supported standard DHCPv4 options are
-        listed in <xref linkend="dhcp4-std-options-list"/>
-        and <xref linkend="dhcp4-std-options-list-part2"/>.
+        listed in <xref linkend="dhcp4-std-options-list"/>.
         The "Name" and "Code"
         The "Name" and "Code"
         are the values that should be used as a name in the option-data
         are the values that should be used as a name in the option-data
         structures. "Type" designates the format of the data: the meanings of
         structures. "Type" designates the format of the data: the meanings of
@@ -1165,32 +1180,6 @@ This rather belong to the DDNS configuration
 <row><entry>default-tcp-ttl</entry><entry>37</entry><entry>uint8</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>default-tcp-ttl</entry><entry>37</entry><entry>uint8</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>tcp-keepalive-interval</entry><entry>38</entry><entry>uint32</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>tcp-keepalive-interval</entry><entry>38</entry><entry>uint32</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>tcp-keepalive-garbage</entry><entry>39</entry><entry>boolean</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>tcp-keepalive-garbage</entry><entry>39</entry><entry>boolean</entry><entry>false</entry><entry>false</entry></row>
-
-          </tbody>
-          </tgroup>
-        </table>
-      </para>
-
-      <para>
-        <table frame="all" id="dhcp4-std-options-list-part2">
-          <title>List of standard DHCPv4 options (continued)</title>
-          <tgroup cols='5'>
-          <colspec colname='name'/>
-          <colspec colname='code' align='center'/>
-          <colspec colname='type' align='center'/>
-          <colspec colname='array' align='center'/>
-          <colspec colname='always-returned' align='center'/>
-          <thead>
-            <row>
-              <entry>Name</entry>
-              <entry>Code</entry>
-              <entry>Type</entry>
-              <entry>Array?</entry>
-              <entry>Returned if not requested?</entry>
-            </row>
-          </thead>
-          <tbody>
-
 <row><entry>nis-domain</entry><entry>40</entry><entry>string</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>nis-domain</entry><entry>40</entry><entry>string</entry><entry>false</entry><entry>false</entry></row>
 <row><entry>nis-servers</entry><entry>41</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>nis-servers</entry><entry>41</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>ntp-servers</entry><entry>42</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
 <row><entry>ntp-servers</entry><entry>42</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
@@ -1414,6 +1403,12 @@ It is merely echoed by the server
        <command>"1"</command>. Future versions of Kea will accept all those values
        <command>"1"</command>. Future versions of Kea will accept all those values
        for all boolean parameters.</para>
        for all boolean parameters.</para>
      </note>
      </note>
+     <note>
+       <para>Numbers can be specified in decimal or hexadecimal format.
+        The hexadecimal format can be either plain (e.g. abcd) or
+        prefixed with 0x (e.g. 0xabcd).
+       </para>
+     </note>
     </section>
     </section>
 
 
     <section id="dhcp4-vendor-opts">
     <section id="dhcp4-vendor-opts">

+ 20 - 3
doc/guide/dhcp6-srv.xml

@@ -982,9 +982,26 @@ temporarily override a list of interface names and listen on all interfaces.
       </para>
       </para>
 
 
       <para>
       <para>
-        Most of the parameters in the "option-data" structure are optional and
-        can be omitted in some circumstances as discussed in the
-        <xref linkend="dhcp6-option-data-defaults"/>.
+        Most of the parameters in the "option-data" structure are
+        optional and can be omitted in some circumstances as discussed
+        in the <xref linkend="dhcp6-option-data-defaults"/>. Only one
+        of name or code is required, so you don't need to specify
+        both. Space has a default value of "dhcp6", so you can skip
+        this as well if you define a regular (not encapsulated) DHCPv6
+        option.  Finally, csv-format defaults to true, so it too can
+        be skipped, unless you want to specify the option value as
+        hexstring. Therefore the above example can be simplified to:
+        <screen>
+"Dhcp4": {
+    "option-data": [
+        {
+           <userinput>"name": "dns-servers",
+           "data": "2001:db8::cafe, 2001:db8::babe"</userinput>
+        },
+        ...
+    ]
+} </screen>
+
       </para>
       </para>
 
 
 
 

+ 10 - 2
src/lib/dhcp/option_definition.cc

@@ -29,6 +29,7 @@
 #include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/dynamic_bitset.hpp>
 #include <boost/dynamic_bitset.hpp>
+#include <sstream>
 
 
 using namespace std;
 using namespace std;
 using namespace isc::util;
 using namespace isc::util;
@@ -496,8 +497,15 @@ OptionDefinition::lexicalCastWithRangeCheck(const std::string& value_str)
         result = boost::lexical_cast<int64_t>(value_str);
         result = boost::lexical_cast<int64_t>(value_str);
 
 
     } catch (const boost::bad_lexical_cast&) {
     } catch (const boost::bad_lexical_cast&) {
-        isc_throw(BadDataTypeCast, "unable to convert the value '"
-                  << value_str << "' to integer data type");
+        // boost::lexical_cast does not handle hexadecimal
+        // but stringstream does so do it the hard way.
+        std::stringstream ss;
+        ss << std::hex << value_str;
+        ss >> result;
+        if (ss.fail() || !ss.eof()) {
+            isc_throw(BadDataTypeCast, "unable to convert the value '"
+                      << value_str << "' to integer data type");
+        }
     }
     }
     // Perform range checks.
     // Perform range checks.
     if (OptionDataTypeTraits<T>::integer_type) {
     if (OptionDataTypeTraits<T>::integer_type) {

+ 1 - 1
src/lib/dhcp/option_definition.h

@@ -641,7 +641,7 @@ private:
     /// This function performs lexical cast of a string value to integer
     /// This function performs lexical cast of a string value to integer
     /// value and checks if the resulting value is within a range of a
     /// value and checks if the resulting value is within a range of a
     /// target type. The target type should be one of the supported
     /// target type. The target type should be one of the supported
-    /// integer types.
+    /// integer types. Hexadecimal input is supported.
     ///
     ///
     /// @param value_str input value given as string.
     /// @param value_str input value given as string.
     /// @tparam T target integer type for lexical cast.
     /// @tparam T target integer type for lexical cast.

+ 2 - 1
src/lib/dhcp/tests/option_definition_unittest.cc

@@ -1191,7 +1191,8 @@ TEST_F(OptionDefinitionTest, uint32ArrayTokenized) {
     OptionPtr option_v6;
     OptionPtr option_v6;
     std::vector<std::string> str_values;
     std::vector<std::string> str_values;
     str_values.push_back("123456");
     str_values.push_back("123456");
-    str_values.push_back("7");
+    // Try with hexadecimal
+    str_values.push_back("0x7");
     str_values.push_back("256");
     str_values.push_back("256");
     str_values.push_back("1111");
     str_values.push_back("1111");