Browse Source

[trac4269] Update to put 4 byte strings on the value stack for integers

Shawn Routhier 9 years ago
parent
commit
75063d9b41
4 changed files with 33 additions and 20 deletions
  1. 5 5
      doc/guide/classify.xml
  2. 4 2
      src/lib/eval/tests/token_unittest.cc
  3. 20 11
      src/lib/eval/token.cc
  4. 4 2
      src/lib/eval/token.h

+ 5 - 5
doc/guide/classify.xml

@@ -172,14 +172,14 @@ sub-option with code "code" from the DHCPv4 Relay Agent Information option
 <row>
   <entry>Message Type in DHCPv6 packet</entry>
   <entry>pkt6.msgtype</entry>
-<!--  <entry>'1'</entry>
+<!--  <entry>1</entry>
 -->
   <entry>The value of the message type field in the DHCPv6 packet.</entry>
 </row>
 <row>
   <entry>Transaction ID in DHCPv6 packet</entry>
   <entry>pkt6.transid</entry>
-<!--  <entry>'12345'</entry>
+<!--  <entry>12345</entry>
 -->
   <entry>The value of the transaction id in the DHCPv6 packet.</entry>
 </row>
@@ -226,9 +226,9 @@ sub-option with code "code" from the DHCPv4 Relay Agent Information option
       <para>
        "pkt6" refers to information from the client request.  To access any
        information from an intermediate relay use "relay6".  "pkt6.msgtype"
-       outputs the string representation of the integer value for the message
-       type, for example SOLICIT will be '1'.  "pkt6.transid" outputs the string
-       representation of the value of the transaction ID.
+       and "pkt6.transid" output a 4 byte binary string for the message type
+       or transaction id.  For example the message type SOLICIT will be
+       "0x00000001" or simply 1 as in "pkt6.msgtype == 1".
       </para>
 
       <para>

+ 4 - 2
src/lib/eval/tests/token_unittest.cc

@@ -977,14 +977,16 @@ TEST_F(TokenTest, pkt6Fields) {
     ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::MSGTYPE)));
     EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
     ASSERT_EQ(1, values_.size());
-    EXPECT_EQ("1", values_.top());
+    uint32_t expected = htonl(1);
+    EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
 
     // Check the transaction id field
     clearStack();
     ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
     EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
     ASSERT_EQ(1, values_.size());
-    EXPECT_EQ("12345", values_.top());
+    expected = htonl(12345);
+    EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
 
     // Check that working with a v4 packet generates an error
     clearStack();

+ 20 - 11
src/lib/eval/token.cc

@@ -278,6 +278,7 @@ TokenOr::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
 void
 TokenPkt6::evaluate(const Pkt& pkt, ValueStack& values) {
 
+    vector<uint8_t> binary;
     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
@@ -286,24 +287,32 @@ TokenPkt6::evaluate(const Pkt& pkt, ValueStack& values) {
 
       switch (type_) {
       case MSGTYPE: {
-          // msg type is an uint8_t integer.  We need to represent it as a string.
-          stringstream tmp;
-          tmp << static_cast<int>(pkt6.getType());
-          values.push(tmp.str());
-          return;
+          // 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());
+          break;
       }
       case TRANSID: {
-          // transaction id is an uint32_t integer.  We need to represent it as a string.
-          stringstream tmp;
-          tmp << static_cast<int>(pkt6.getTransid());
-          values.push(tmp.str());
-          return;
+          // 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);
+          break;
       }
       default:
-          isc_throw(EvalTypeError, "Bad filed specified: "
+          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);
 };

+ 4 - 2
src/lib/eval/token.h

@@ -446,8 +446,10 @@ public:
 
 /// @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
+/// 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