]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[master] Finished merge of trac4272a (meta-info in classification)
authorFrancis Dupont <fdupont@isc.org>
Tue, 16 Aug 2016 15:04:34 +0000 (17:04 +0200)
committerFrancis Dupont <fdupont@isc.org>
Tue, 16 Aug 2016 15:04:34 +0000 (17:04 +0200)
1  2 
ChangeLog
src/lib/eval/token.cc
src/lib/eval/token.h

diff --cc ChangeLog
index dfb0ea1f36b9d8f8b26ac8b1e19442f902ef143f,5d1e9f815176e0fc033b7cf6b23c2783a8a37016..9b4e4f2e293abf448e06a91ece23fc656d48fdbe
+++ b/ChangeLog
-       (Trac #4533 git 874e3a3f5cb10313856284646fcee7cf86e4fcce)
++1148. [func]          fdupont
++      Added the pkt classification token to extract incoming packet
++      meta-data (receiving interface name, source and destination
++      address, length).
++      (Trac #4272, git ...)
++
 +1147. [func]          stephen
 +      -Werror is no longer the default for compilation.  Promotion of all
 +      compilation warnings to errors now requires the --with-werror switch
 +      to be specified when running configure.
-       (Trac #4511 git 0bb39840a3cbdaf815819f846120c90d9ca038ff)
++      (Trac #4533, git 874e3a3f5cb10313856284646fcee7cf86e4fcce)
 +
 +1146. [func]          sar
 +      Add the forensic hook library documentation to the admin guide.
-       The Postgresql backend now supports host reservations for both DHCPv4 and
-       DHCPv6, with options and IPv6 reservations.
++      (Trac #4511, git 0bb39840a3cbdaf815819f846120c90d9ca038ff)
 +
 +1145. [func]          tmark
++      The Postgresql backend now supports host reservations for both
++      DHCPv4 and DHCPv6, with options and IPv6 reservations.
 +      (Trac #4277 git ac1eaa1026987c2d86d57b4aa0dc9a4d093787f0)
 +
 +1144. [bug]           mihu
 +      Response to DHCPINFORM is generally sent to port 68, rather
 +      than port 67. Thanks to Michal Humpula for providing a patch.
 +      (github #23, git 4216a4bedf8a884df087c68d48c88ee9ffa444dc)
 +
 +1143. [doc]           fdupont
 +      User's Guide has been updated with DHCPv4-over-DHCPv6 support
 +      details.
 +      (Trac #4273, git fe8cb64adeabe00d84ee390b579a8328717ae521)
 +
 +1142. [doc]           sar
 +      Uncomment the example columns in some rows in the table
 +      listing the classificaiton examples.
 +      (None, git dee442a64f57c8d9dd87636f9e39084ed1b11e03)
 +
 +1141. [func]          marcin
 +      Pkt4, Pkt6 and Pkt4o6 objects passed to hooks libraries
 +      return copies of DHCP options to avoid unintended modification
 +      of the options stored in the server configuration.
 +      (Trac #4497, git e50d2ebe998ec3faad8ade22b6971d6584c81044)
 +
 +1140. [func]          marcin
 +      DHCPv6 server supports assigning multiple reserved addresses
 +      and/or prefixes to a single client.
 +      (Trac #4321, git 0bfb2a9093174e4424051c01beeee7637ac95be0)
 +
 +1139. [doc]           tomek
 +      New features of host reservations have been documented: ability
 +      to reserve standard and vendor options in host reservations. Separate
 +      sections for each backend added.
 +      (Trac #4518, git 99a40fead28f4324dfb55f1962a8bf3e85ab70e2)
 +
 +1138. [build]         fdupont
 +      Compilation problem on FreeBSD caused by unused parameter in
 +      certain version of boost headers is now resolved. Also, INSTALL
 +      file has been updated and now lists dependencies.
 +      (Trac #4283, git 7dbd95651c308527f2e42c533fdc0a12aeec5308)
 +
 +1137. [doc]           fdupont
 +      Developer's Guide has been updated with DHCPv4-over-DHCPv6 support
 +      details.
 +      (Trac #4274, git b3eda594e055f03a9a601bacf0c72c3db0ef8e3c)
 +
 +1136. [doc]           tomek
 +      Included full text of MPL 2.0 and Apache licenses.
 +      (Trac #4529, git baefb4b3e2078a0a0f794b42ef52d6b7d53c9dab)
 +
 +1135. [func]          fdupont
 +      Integrated the DHCPv4 service part of DHCPv4-over-DHCPv6 support.
 +      (Trac #4110, git 7d36aebe14db10b0cbac8e6c0e82160b9d5d7ecd)
 +
 +1134. [func]          fdupont
 +      Integrated the DHCPv6 service part of DHCPv4-over-DHCPv6 support.
 +      (Trac #4109, git 8d1f330d9b0a44039a8b9e0b479f8da1743b9504)
 +
 +1133. [func]          razvan
 +      The initial support for CQL (Cassandra) backend added. It is able
 +      to store leases information.
 +      (Github #21, git d3a412d4b090bfd84ec5bc5d7817b1dfcc92602e)
 +
 +1132. [func]          tmark
 +      The Postgresql schema has been updated to support host
 +      reservations and its version number has been bumped to 3.0.
 +      This schema is content equivlent to the MySQL schema version 4.2.
 +      (Trac #4275, git 6f8e646bee9de22c921ed26409f3d1856ebce9e6)
 +
 +1131. [func]          fdupont
 +      Update the DHCPv4-over-DHCPv6 inter-process communication code.
 +      (Trac #4106, git 1ce1cba00af5d81822d5bbe26ddd28b718f51d54)
 +
 +1130. [func]          marcin
 +      DHCPv6 server assigns DHCP options specified for hosts. Host
 +      specific options take precedence over class specific options,
 +      subnet specific options and global options.
 +      (Trac #3573, git c29551e43010a345cfa2efda46389f4433d84650)
 +
 +1129. [bug]           marcin
 +      libdhcp++: Removed unnecessary copies of the container holding
 +      option definitions to improve performance of both DHCPv4 and
 +      DHCPv6 server.
 +      (Trac #4498, git 14716853a92e08c4cc5be75ae85c5e84d6356a1e)
 +
  1128. [func]          tomek
        Subnet selection in DHCPv4 will now work, even if the addresses
        configured on interface are not in range of the subnet definition
index c9f5c969b7ba44dad6fe220a8ef7a45fa8a38d5e,7b5c3385afc24d0e5b76673f9871de838330f998..bda146f272dc647567988fe26dfab92f1f84cc7b
  #include <string>
  
  using namespace isc::dhcp;
+ using namespace isc::util;
  using namespace std;
  
+ using isc::util::encode::toHex;
  void
 -TokenString::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
 +TokenString::evaluate(Pkt& /*pkt*/, ValueStack& values) {
      // Literals only push, nothing to pop
      values.push(value_);
  
@@@ -153,8 -154,86 +154,86 @@@ OptionPtr TokenRelay4Option::getOption(
      return (rai->getOption(option_code_));
  }
  
 -OptionPtr TokenRelay6Option::getOption(const Pkt& pkt) {
++OptionPtr TokenRelay6Option::getOption(Pkt& pkt) {
+     try {
+         // Check if it's a Pkt6.  If it's not the dynamic_cast will
+         // throw std::bad_cast.
+         const Pkt6& pkt6 = dynamic_cast<const Pkt6&>(pkt);
+         try {
+             // Now that we have the right type of packet we can
+             // get the option and return it.
+             return(pkt6.getRelayOption(option_code_, nest_level_));
+         }
+         catch (const isc::OutOfRange&) {
+             // The only exception we expect is OutOfRange if the nest
+             // level is out of range of the encapsulations, for example
+             // if nest_level_ is 4 and there are only 2 encapsulations.
+             // We return a NULL in that case.
+            return (OptionPtr());
+         }
+     } catch (const std::bad_cast&) {
+         isc_throw(EvalTypeError, "Specified packet is not Pkt6");
+     }
+ }
+ void
 -TokenPkt::evaluate(const Pkt& pkt, ValueStack& values) {
++TokenPkt::evaluate(Pkt& pkt, ValueStack& values) {
+     string value;
+     vector<uint8_t> binary;
+     string type_str;
+     uint32_t len;
+     bool is_binary = true;
+     switch (type_) {
+     case IFACE:
+         is_binary = false;
+         value = pkt.getIface();
+         type_str = "iface";
+         break;
+     case SRC:
+         binary = pkt.getRemoteAddr().toBytes();
+         type_str = "src";
+         break;
+     case DST:
+         binary = pkt.getLocalAddr().toBytes();
+         type_str = "dst";
+         break;
+     case LEN:
+         // len() returns a size_t but in fact it can't be very large
+         // (with UDP transport it fits in 16 bits)
+         // the len() method is not const because of DHCPv6 relays.
+         // We assume here it has no bad side effects...
+         len = static_cast<uint32_t>(const_cast<Pkt&>(pkt).len());
+         binary.resize(sizeof(uint32_t));
+         static_cast<void>(writeUint32(len, &binary[0], binary.size()));
+         type_str = "len";
+         break;
+     default:
+         isc_throw(EvalTypeError, "Bad meta data specified: "
+                   << static_cast<int>(type_) );
+     }
+     if (is_binary) {
+         value.resize(binary.size());
+         if (!binary.empty()) {
+             memmove(&value[0], &binary[0], binary.size());
+         }
+     }
+     values.push(value);
+     // Log what we pushed
+     LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_PKT)
+         .arg(type_str)
+         .arg(is_binary ? toHex(value) : value);
+ }
  void
 -TokenPkt4::evaluate(const Pkt& pkt, ValueStack& values) {
 +TokenPkt4::evaluate(Pkt& pkt, ValueStack& values) {
  
      vector<uint8_t> binary;
      string type_str;
      // Log what we pushed
      LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_PKT4)
          .arg(type_str)
-         .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(value.begin(),
-                                                                  value.end())));
+         .arg(toHex(value));
+ }
+ void
 -TokenPkt6::evaluate(const Pkt& pkt, ValueStack& values) {
++TokenPkt6::evaluate(Pkt& pkt, ValueStack& values) {
+     vector<uint8_t> binary;
+     string type_str;
+     try {
+       // Check if it's a Pkt6.  If it's not the dynamic_cast will throw
+       // std::bad_cast (failed dynamic_cast returns NULL for pointers and
+       // throws for references).
+       const Pkt6& pkt6 = dynamic_cast<const Pkt6&>(pkt);
+       switch (type_) {
+       case MSGTYPE: {
+           // msg type is an uint8_t integer.  We want a 4 byte string so 0 pad.
+           binary.push_back(0);
+           binary.push_back(0);
+           binary.push_back(0);
+           binary.push_back(pkt6.getType());
+           type_str = "msgtype";
+           break;
+       }
+       case TRANSID: {
+           // transaction id is an uint32_t integer.  We want a 4 byte string so copy
+           uint32_t transid = pkt6.getTransid();
+           binary.push_back(transid >> 24);
+           binary.push_back((transid >> 16) & 0xFF);
+           binary.push_back((transid >> 8) & 0xFF);
+           binary.push_back(transid & 0xFF);
+           type_str = "transid";
+           break;
+       }
+       default:
+           isc_throw(EvalTypeError, "Bad field specified: "
+                     << static_cast<int>(type_) );
+       }
+     } catch (const std::bad_cast&) {
+         isc_throw(EvalTypeError, "Specified packet is not Pkt6");
+     }
+     string value;
+     value.resize(binary.size());
+     memmove(&value[0], &binary[0], binary.size());
+     values.push(value);
+     // Log what we pushed
+     LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_PKT6)
+         .arg(type_str)
+         .arg(toHex(value));
+ }
+ void
 -TokenRelay6Field::evaluate(const Pkt& pkt, ValueStack& values) {
++TokenRelay6Field::evaluate(Pkt& pkt, ValueStack& values) {
+     vector<uint8_t> binary;
+     string type_str;
+     try {
+         // Check if it's a Pkt6.  If it's not the dynamic_cast will
+         // throw std::bad_cast.
+         const Pkt6& pkt6 = dynamic_cast<const Pkt6&>(pkt);
+         try {
+         switch (type_) {
+             // Now that we have the right type of packet we can
+             // get the option and return it.
+             case LINKADDR:
+                 type_str = "linkaddr";
+                 binary = pkt6.getRelay6LinkAddress(nest_level_).toBytes();
+                 break;
+             case PEERADDR:
+                 type_str = "peeraddr";
+                 binary = pkt6.getRelay6PeerAddress(nest_level_).toBytes();
+                 break;
+             }
+         } catch (const isc::OutOfRange&) {
+             // The only exception we expect is OutOfRange if the nest
+             // level is invalid.  We push "" in that case.
+             values.push("");
+             // Log what we pushed
+             LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_RELAY6_RANGE)
+               .arg(type_str)
+               .arg(unsigned(nest_level_))
+               .arg("0x");
+             return;
+         }
+     } catch (const std::bad_cast&) {
+         isc_throw(EvalTypeError, "Specified packet is not Pkt6");
+     }
+     string value;
+     value.resize(binary.size());
+     if (!binary.empty()) {
+         memmove(&value[0], &binary[0], binary.size());
+     }
+     values.push(value);
+     // Log what we pushed
+     LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_RELAY6)
+         .arg(type_str)
+         .arg(unsigned(nest_level_))
+         .arg(toHex(value));
  }
  
  void
index 4b7812e6642bc0302e212e73287fe4e5f75cf0f7,df9075bc3dfb5fa2e812b3c6fe8ba56f95558b0d..ff2e78c2cd3832debd3e02bb225fa449455a18b0
@@@ -285,9 -285,102 +285,102 @@@ protected
      /// @brief Attempts to obtain specified sub-option of option 82 from the packet
      /// @param pkt DHCPv4 packet (that hopefully contains option 82)
      /// @return found sub-option from option 82
 -    virtual OptionPtr getOption(const Pkt& pkt);
 +    virtual OptionPtr getOption(Pkt& pkt);
  };
  
 -    virtual OptionPtr getOption(const Pkt& pkt);
+ /// @brief Token that represents a value of an option within a DHCPv6 relay
+ /// encapsulation
+ ///
+ /// This represents a reference to a given option similar to TokenOption
+ /// but from within the information from a relay.  In the expresssion
+ /// relay6[nest-level].option[option-code], nest-level indicates which
+ /// of the relays to examine and option-code which option to extract.
+ ///
+ /// During the evaluation it tries to extract the value of the specified
+ /// option from the requested relay block.  If the relay block doesn't
+ /// exist or the option is not found an empty string ("") is returned
+ /// (or "false" when the representation is EXISTS).
+ ///
+ /// The nesting level can go from 0 (closest to the server) to 31
+ class TokenRelay6Option : public TokenOption {
+ public:
+     /// @brief Constructor that takes a nesting level and an option
+     /// code as paramaters.
+     ///
+     /// @param nest_level the nesting for which relay to examine.
+     /// @param option_code code of the option.
+     /// @param rep_type Token representation type.
+     TokenRelay6Option(const uint8_t nest_level, const uint16_t option_code,
+                       const RepresentationType& rep_type)
+         :TokenOption(option_code, rep_type), nest_level_(nest_level) {}
+     /// @brief Returns nest-level
+     ///
+     /// This method is used in testing to determine if the parser has
+     /// instantiated TokenRelay6Option with correct parameters.
+     ///
+     /// @return nest-level of the relay block this token expects to use
+     /// for extraction.
+     uint8_t getNest() const {
+         return (nest_level_);
+     }
+ protected:
+     /// @brief Attempts to obtain specified option from the specified relay block
+     /// @param pkt DHCPv6 packet that hopefully contains the proper relay block
+     /// @return option instance if available
 -    void evaluate(const Pkt& pkt, ValueStack& values);
++    virtual OptionPtr getOption(Pkt& pkt);
+     uint8_t nest_level_; ///< nesting level of the relay block to use
+ };
+ /// @brief Token that represents meta data of a DHCP packet.
+ ///
+ /// For example in the expression pkt.iface == 'eth0'
+ /// this token represents the pkt.iface expression.
+ ///
+ /// Currently supported meta datas are:
+ /// - iface (incoming/outgoinginterface name)
+ /// - src   (source IP address, 4 or 16 octets)
+ /// - dst   (destination IP address, 4 or 16 octets)
+ /// - len   (length field in the UDP header, padded to 4 octets)
+ class TokenPkt : public Token {
+ public:
+     /// @brief enum value that determines the field.
+     enum MetadataType {
+         IFACE, ///< interface name (string)
+         SRC,   ///< source (IP address)
+         DST,   ///< destination (IP address)
+         LEN    ///< length (4 octets)
+     };
+     /// @brief Constructor (does nothing)
+     TokenPkt(const MetadataType type)
+         : type_(type) {}
+     /// @brief Gets a value from the specified packet.
+     ///
+     /// Evaluation uses metadatas available in the packet. It does not
+     /// require any values to be present on the stack.
+     ///
+     /// @param pkt - metadatas will be extracted from here
+     /// @param values - stack of values (1 result will be pushed)
++    void evaluate(Pkt& pkt, ValueStack& values);
+     /// @brief Returns metadata type
+     ///
+     /// This method is used only in tests.
+     /// @return type of the metadata.
+     MetadataType getType() {
+         return (type_);
+     }
+ private:
+     /// @brief Specifies metadata of the DHCP packet
+     MetadataType type_;
+ };
  /// @brief Token that represents fields of a DHCPv4 packet.
  ///
  /// For example in the expression pkt4.chaddr == 0x0102030405
@@@ -343,6 -436,119 +436,119 @@@ private
      FieldType type_;
  };
  
 -    void evaluate(const Pkt& pkt, ValueStack& values);
+ /// @brief Token that represents fields of DHCPv6 packet.
+ ///
+ /// For example in the expression pkt6.msgtype == 1
+ /// this token represents the message type of the DHCPv6 packet.
+ /// The integer values are placed on the value stack as 4 byte
+ /// strings.
+ ///
+ /// Currently supported fields are:
+ /// - msgtype
+ /// - transid
+ class TokenPkt6 : public Token {
+ public:
+     /// @brief enum value that determines the field.
+     enum FieldType {
+         MSGTYPE, ///< msg type
+         TRANSID  ///< transaction id (integer but manipulated as a string)
+     };
+     /// @brief Constructor (does nothing)
+     TokenPkt6(const FieldType type)
+         : type_(type) {}
+     /// @brief Gets a value of the specified packet.
+     ///
+     /// The evaluation uses fields that are availabe in the packet.  It does not
+     /// require any values to be present on the stack.
+     ///
+     /// @throw EvalTypeError when called for a DHCPv4 packet
+     ///
+     /// @param pkt - packet from which to extract the fields
+     /// @param values - stack of values, 1 result will be pushed
 -    void evaluate(const Pkt& pkt, ValueStack& values);
++    void evaluate(Pkt& pkt, ValueStack& values);
+     /// @brief Returns field type
+     ///
+     /// This method is used only in tests.
+     /// @return type of the field.
+     FieldType getType() {
+         return(type_);
+     }
+ private:
+     /// @brief Specifies field of the DHCPv6 packet to get
+     FieldType type_;
+ };
+ /// @brief Token that represents a value of a field within a DHCPv6 relay
+ /// encapsulation
+ ///
+ /// This represents a reference to a field with a given DHCPv6 relay encapsulation.
+ /// In the expression relay6[nest-level].field-name, nest-level indicates which of
+ /// the relays to examine and field-name which of the fields to extract.
+ ///
+ /// During the evaluation it tries to extract the value of the specified
+ /// field from the requested relay block.  If the relay block doesn't exist
+ /// an empty string ("") is returned.  If the relay block does exist the field
+ /// is always returned as a 16 byte IPv6 address.  As the relay may not have
+ /// set the field it may be 0s.
+ ///
+ /// The nesting level can go from 0 (closest to the server) to 31.
+ class TokenRelay6Field : public Token {
+ public:
+     /// @brief enum value that determines the field.
+     enum FieldType {
+         PEERADDR, ///< Peer address field (IPv6 address)
+         LINKADDR  ///< Link address field (IPv6 address)
+     };
+     /// @brief Constructor that takes a nesting level and field type
+     /// as parameters.
+     ///
+     /// @param nest_level the nesting level for which relay to examine.
+     /// @param type which field to extract.
+     TokenRelay6Field(const uint8_t nest_level, const FieldType type)
+       : nest_level_(nest_level), type_(type) {}
+     /// @brief Extracts the specified field from the requested relay
+     ///
+     /// Evaluation uses fields available in the packet.  It does not require
+     /// any values to be present on the stack.
+     ///
+     /// @param pkt fields will be extracted from here
+     /// @param values - stack of values (1 result will be pushed)
++    void evaluate(Pkt& pkt, ValueStack& values);
+     /// @brief Returns nest-level
+     ///
+     /// This method is used in testing to determine if the parser has
+     /// instantiated TokenRelay6Field with correct parameters.
+     ///
+     /// @return nest-level of the relay block this token expects to use
+     /// for extraction.
+     uint8_t getNest() const {
+         return (nest_level_);
+     }
+     /// @brief Returns field type
+     ///
+     /// This method is used only in testing to determine if the parser has
+     /// instantiated TokenRelay6Field with correct parameters.
+     ///
+     /// @return type of the field.
+     FieldType getType() {
+         return (type_);
+     }
+ protected:
+     /// @brief Specifies field of the DHCPv6 relay option to get
+     uint8_t nest_level_; ///< nesting level of the relay block to use
+     FieldType type_; ///< field to get
+ };
  /// @brief Token that represents equality operator (compares two other tokens)
  ///
  /// For example in the expression option[vendor-class].text == "MSFT"
@@@ -519,168 -725,9 +725,9 @@@ public
      /// @param pkt (unused)
      /// @param values - stack of values (2 arguments will be popped, 1 result
      ///        will be pushed)
 -    void evaluate(const Pkt& pkt, ValueStack& values);
 +    void evaluate(Pkt& pkt, ValueStack& values);
  };
  
- /// @brief Token that represents a value of an option within a DHCPv6 relay
- /// encapsulation
- ///
- /// This represents a reference to a given option similar to TokenOption
- /// but from within the information from a relay.  In the expresssion
- /// relay6[nest-level].option[option-code], nest-level indicates which
- /// of the relays to examine and option-code which option to extract.
- ///
- /// During the evaluation it tries to extract the value of the specified
- /// option from the requested relay block.  If the relay block doesn't
- /// exist or the option is not found an empty string ("") is returned
- /// (or "false" when the representation is EXISTS).
- ///
- /// The nesting level can go from 0 (closest to the server) to 31
- class TokenRelay6Option : public TokenOption {
- public:
-     /// @brief Constructor that takes a nesting level and an option
-     /// code as paramaters.
-     ///
-     /// @param nest_level the nesting for which relay to examine.
-     /// @param option_code code of the option.
-     /// @param rep_type Token representation type.
-     TokenRelay6Option(const uint8_t nest_level, const uint16_t option_code,
-                       const RepresentationType& rep_type)
-         :TokenOption(option_code, rep_type), nest_level_(nest_level) {}
-     /// @brief Returns nest-level
-     ///
-     /// This method is used in testing to determine if the parser has
-     /// instantiated TokenRelay6Option with correct parameters.
-     ///
-     /// @return nest-level of the relay block this token expects to use
-     /// for extraction.
-     uint8_t getNest() const {
-         return (nest_level_);
-     }
- protected:
-     /// @brief Attempts to obtain specified option from the specified relay block
-     /// @param pkt DHCPv6 packet that hopefully contains the proper relay block
-     /// @return option instance if available
-     virtual OptionPtr getOption(Pkt& pkt);
-     uint8_t nest_level_; ///< nesting level of the relay block to use
- };
- /// @brief Token that represents a value of a field within a DHCPv6 relay
- /// encapsulation
- ///
- /// This represents a reference to a field with a given DHCPv6 relay encapsulation.
- /// In the expression relay6[nest-level].field-name, nest-level indicates which of
- /// the relays to examine and field-name which of the fields to extract.
- ///
- /// During the evaluation it tries to extract the value of the specified
- /// field from the requested relay block.  If the relay block doesn't exist
- /// an empty string ("") is returned.  If the relay block does exist the field
- /// is always returned as a 16 byte IPv6 address.  As the relay may not have
- /// set the field it may be 0s.
- ///
- /// The nesting level can go from 0 (closest to the server) to 31.
- class TokenRelay6Field : public Token {
- public:
-     /// @brief enum value that determines the field.
-     enum FieldType {
-         PEERADDR, ///< Peer address field (IPv6 address)
-         LINKADDR  ///< Link address field (IPv6 address)
-     };
-     /// @brief Constructor that takes a nesting level and field type
-     /// as parameters.
-     ///
-     /// @param nest_level the nesting level for which relay to examine.
-     /// @param type which field to extract.
-     TokenRelay6Field(const uint8_t nest_level, const FieldType type)
-       : nest_level_(nest_level), type_(type) {}
-     /// @brief Extracts the specified field from the requested relay
-     ///
-     /// Evaluation uses fields available in the packet.  It does not require
-     /// any values to be present on the stack.
-     ///
-     /// @param pkt fields will be extracted from here
-     /// @param values - stack of values (1 result will be pushed)
-     void evaluate(Pkt& pkt, ValueStack& values);
-     /// @brief Returns nest-level
-     ///
-     /// This method is used in testing to determine if the parser has
-     /// instantiated TokenRelay6Field with correct parameters.
-     ///
-     /// @return nest-level of the relay block this token expects to use
-     /// for extraction.
-     uint8_t getNest() const {
-         return (nest_level_);
-     }
-     /// @brief Returns field type
-     ///
-     /// This method is used only in testing to determine if the parser has
-     /// instantiated TokenRelay6Field with correct parameters.
-     ///
-     /// @return type of the field.
-     FieldType getType() {
-         return (type_);
-     }
- protected:
-     /// @brief Specifies field of the DHCPv6 relay option to get
-     uint8_t nest_level_; ///< nesting level of the relay block to use
-     FieldType type_; ///< field to get
- };
- /// @brief Token that represents fields of DHCPv6 packet.
- ///
- /// For example in the expression pkt6.msgtype == 1
- /// this token represents the message type of the DHCPv6 packet.
- /// The integer values are placed on the value stack as 4 byte
- /// strings.
- ///
- /// Currently supported fields are:
- /// - msgtype
- /// - transid
- class TokenPkt6 : public Token {
- public:
-     /// @brief enum value that determines the field.
-     enum FieldType {
-         MSGTYPE, ///< msg type
-         TRANSID  ///< transaction id (integer but manipulated as a string)
-     };
-     /// @brief Constructor (does nothing)
-     TokenPkt6(const FieldType type)
-         : type_(type) {}
-     /// @brief Gets a value of the specified packet.
-     ///
-     /// The evaluation uses fields that are availabe in the packet.  It does not
-     /// require any values to be present on the stack.
-     ///
-     /// @throw EvalTypeError when called for a DHCPv4 packet
-     ///
-     /// @param pkt - packet from which to extract the fields
-     /// @param values - stack of values, 1 result will be pushed
-     void evaluate(Pkt& pkt, ValueStack& values);
-     /// @brief Returns field type
-     ///
-     /// This method is used only in tests.
-     /// @return type of the field.
-     FieldType getType() {
-         return(type_);
-     }
- private:
-     /// @brief Specifies field of the DHCPv6 packet to get
-     FieldType type_;
- };
  }; // end of isc::dhcp namespace
  }; // end of isc namespace