}
}
+ /// @brief checks if the given token is a TokenRelay6Option with
+ /// the correct nesting level, option code and representation.
+ /// @param token token to be checked
+ /// @param expected_level expected nesting level
+ /// @param expected_code expected option code
+ /// @param expected_repr expected representation (text, hex, exists)
+ void checkTokenRelay6Option(const TokenPtr& token,
+ uint8_t expected_level,
+ uint16_t expected_code,
+ TokenOption::RepresentationType expected_repr) {
+ ASSERT_TRUE(token);
+ boost::shared_ptr<TokenRelay6Option> opt =
+ boost::dynamic_pointer_cast<TokenRelay6Option>(token);
+ ASSERT_TRUE(opt);
+
+ EXPECT_EQ(expected_level, opt->getNest());
+ EXPECT_EQ(expected_code, opt->getCode());
+ EXPECT_EQ(expected_repr, opt->getRepresentation());
+ }
+
+ /// @brief This tests attempts to parse the expression then checks
+ /// if the number of tokens is correct and the TokenRelay6Option
+ /// is as expected.
+ ///
+ /// @param expr expression to be parsed
+ /// @param exp_level expected level to be parsed
+ /// @param exp_code expected option code to be parsed
+ /// @param exp_repr expected representation to be parsed
+ /// @param exp_tokens expected number of tokens
+ void testRelay6Option(std::string expr,
+ uint8_t exp_level,
+ uint16_t exp_code,
+ TokenOption::RepresentationType exp_repr,
+ int exp_tokens) {
+ EvalContext eval(Option::V6);
+
+ // parse the expression
+ try {
+ parsed_ = eval.parseString(expr);
+ }
+ catch (const EvalParseError& ex) {
+ FAIL() <<"Exception thrown: " << ex.what();
+ return;
+ }
+
+ // Parsing should succed and return a token.
+ EXPECT_TRUE(parsed_);
+
+ // There should be the expected number of tokens.
+ ASSERT_EQ(exp_tokens, eval.expression.size());
+
+ // checkt that the first token is TokenRelay6Option and that
+ // is has the correct attributes
+ checkTokenRelay6Option(eval.expression.at(0), exp_level, exp_code, exp_repr);
+ }
+
/// @brief checks if the given token is Pkt4 of specified type
/// @param token token to be checked
/// @param type expected type of the Pkt4 field
checkTokenPkt4(eval.expression.at(0), exp_type);
}
- /// @brief checks if the given token is a substring operator
- void checkTokenSubstring(const TokenPtr& token) {
+ /// @brief checks if the given token is Pkt6 of specified type
+ /// @param token token to be checked
+ /// @param exp_type expected type of the Pkt6 field
+ void checkTokenPkt6(const TokenPtr& token,
+ TokenPkt6::FieldType exp_type) {
ASSERT_TRUE(token);
- boost::shared_ptr<TokenSubstring> sub =
- boost::dynamic_pointer_cast<TokenSubstring>(token);
- EXPECT_TRUE(sub);
- }
- /// @brief checks if the given token is a concat operator
- void checkTokenConcat(const TokenPtr& token) {
- ASSERT_TRUE(token);
- boost::shared_ptr<TokenConcat> conc =
- boost::dynamic_pointer_cast<TokenConcat>(token);
- EXPECT_TRUE(conc);
- }
+ boost::shared_ptr<TokenPkt6> pkt =
+ boost::dynamic_pointer_cast<TokenPkt6>(token);
- /// @brief checks if the given token is a TokenRelay6Option with
- /// the correct nesting level, option code and representation.
- /// @param token token to be checked
- /// @param expected_level expected nesting level
- /// @param expected_code expected option code
- /// @param expected_repr expected representation (text, hex, exists)
- void checkTokenRelay6Option(const TokenPtr& token,
- uint8_t expected_level,
- uint16_t expected_code,
- TokenOption::RepresentationType expected_repr) {
- ASSERT_TRUE(token);
- boost::shared_ptr<TokenRelay6Option> opt =
- boost::dynamic_pointer_cast<TokenRelay6Option>(token);
- ASSERT_TRUE(opt);
+ ASSERT_TRUE(pkt);
- EXPECT_EQ(expected_level, opt->getNest());
- EXPECT_EQ(expected_code, opt->getCode());
- EXPECT_EQ(expected_repr, opt->getRepresentation());
+ EXPECT_EQ(exp_type, pkt->getType());
}
- /// @brief This tests attempts to parse the expression then checks
- /// if the number of tokens is correct and the TokenRelay6Option
- /// is as expected.
+ /// @brief Test that verifies access to the DHCPv6 packet fields.
+ ///
+ /// This test attempts to parse the expression, will check if the number
+ /// of tokens is exactly as planned and then will try to verify if the
+ /// first token represents expected the field in DHCPv6 packet.
///
/// @param expr expression to be parsed
- /// @param exp_level expected level to be parsed
- /// @param exp_code expected option code to be parsed
- /// @param exp_repr expected representation to be parsed
+ /// @param exp_type expected field type to be parsed
/// @param exp_tokens expected number of tokens
- void testRelay6Option(std::string expr,
- uint8_t exp_level,
- uint16_t exp_code,
- TokenOption::RepresentationType exp_repr,
- int exp_tokens) {
+ void testPkt6Field(std::string expr, TokenPkt6::FieldType exp_type,
+ int exp_tokens) {
EvalContext eval(Option::V6);
- // parse the expression
+ // Parse the expression.
try {
parsed_ = eval.parseString(expr);
}
catch (const EvalParseError& ex) {
- FAIL() <<"Exception thrown: " << ex.what();
+ FAIL() << "Exception thrown: " << ex.what();
return;
}
- // Parsing should succed and return a token.
+ // Parsing should succeed and return a token.
EXPECT_TRUE(parsed_);
- // There should be the expected number of tokens.
+ // There should be the requested number of tokens
ASSERT_EQ(exp_tokens, eval.expression.size());
- // checkt that the first token is TokenRelay6Option and that
- // is has the correct attributes
- checkTokenRelay6Option(eval.expression.at(0), exp_level, exp_code, exp_repr);
+ // Check that the first token is TokenPkt6 instance and has correct type.
+ checkTokenPkt6(eval.expression.at(0), exp_type);
}
/// @brief checks if the given token is a TokenRelay with the
checkTokenRelay6Field(eval.expression.at(0), exp_level, exp_type);
}
- /// @brief checks if the given token is Pkt6 of specified type
- /// @param token token to be checked
- /// @param exp_type expected type of the Pkt6 field
- void checkTokenPkt6(const TokenPtr& token,
- TokenPkt6::FieldType exp_type) {
+ /// @brief checks if the given token is a substring operator
+ void checkTokenSubstring(const TokenPtr& token) {
ASSERT_TRUE(token);
+ boost::shared_ptr<TokenSubstring> sub =
+ boost::dynamic_pointer_cast<TokenSubstring>(token);
+ EXPECT_TRUE(sub);
+ }
- boost::shared_ptr<TokenPkt6> pkt =
- boost::dynamic_pointer_cast<TokenPkt6>(token);
-
- ASSERT_TRUE(pkt);
-
- EXPECT_EQ(exp_type, pkt->getType());
+ /// @brief checks if the given token is a concat operator
+ void checkTokenConcat(const TokenPtr& token) {
+ ASSERT_TRUE(token);
+ boost::shared_ptr<TokenConcat> conc =
+ boost::dynamic_pointer_cast<TokenConcat>(token);
+ EXPECT_TRUE(conc);
}
/// @brief checks if the given expression raises the expected message
universe_ = universe;
}
- /// @brief Test that verifies access to the DHCPv6 packet fields.
- ///
- /// This test attempts to parse the expression, will check if the number
- /// of tokens is exactly as planned and then will try to verify if the
- /// first token represents expected the field in DHCPv6 packet.
- ///
- /// @param expr expression to be parsed
- /// @param exp_type expected field type to be parsed
- /// @param exp_tokens expected number of tokens
- void testPkt6Field(std::string expr, TokenPkt6::FieldType exp_type,
- int exp_tokens) {
- EvalContext eval(Option::V6);
-
- // Parse the expression.
- try {
- parsed_ = eval.parseString(expr);
- }
- catch (const EvalParseError& ex) {
- FAIL() << "Exception thrown: " << ex.what();
- return;
- }
-
- // Parsing should succeed and return a token.
- EXPECT_TRUE(parsed_);
-
- // There should be the requested number of tokens
- ASSERT_EQ(exp_tokens, eval.expression.size());
-
- // Check that the first token is TokenPkt6 instance and has correct type.
- checkTokenPkt6(eval.expression.at(0), exp_type);
- }
-
Option::Universe universe_;
bool parsed_; ///< Parsing status
};
"<string>:1.1-6: relay4 can only be used in DHCPv4.");
}
+// Test the parsing of a relay6 option
+TEST_F(EvalContextTest, relay6Option) {
+ EvalContext eval(Option::V6);
+
+ testRelay6Option("relay6[0].option[123].text == 'foo'",
+ 0, 123, TokenOption::TEXTUAL, 3);
+}
+
+// Test the parsing of existence for a relay6 option
+TEST_F(EvalContextTest, relay6OptionExists) {
+ EvalContext eval(Option::V6);
+
+ testRelay6Option("relay6[1].option[75].exists",
+ 1, 75, TokenOption::EXISTS, 1);
+}
+
+// Test the parsing of hex for a relay6 option
+TEST_F(EvalContextTest, relay6OptionHex) {
+ EvalContext eval(Option::V6);
+
+ testRelay6Option("relay6[2].option[85].hex == 'foo'",
+ 2, 85, TokenOption::HEXADECIMAL, 3);
+}
+
// Tests whether chaddr field in DHCPv4 can be accessed.
TEST_F(EvalContextTest, pkt4FieldChaddr) {
testPkt4Field("pkt4.mac == 0x000102030405", TokenPkt4::CHADDR, 3);
testPkt6Field("pkt6.transid == '1'", TokenPkt6::TRANSID, 3);
}
+// Tests if the linkaddr field in a Relay6 encapsulation can be accessed.
+TEST_F(EvalContextTest, relay6FieldLinkAddr) {
+ testRelay6Field("relay6[0].linkaddr == ::",
+ 0, TokenRelay6Field::LINKADDR, 3);
+}
+
+// Tests if the peeraddr field in a Relay6 encapsulation can be accessed.
+TEST_F(EvalContextTest, relay6FieldPeerAddr) {
+ testRelay6Field("relay6[1].peeraddr == ::",
+ 1, TokenRelay6Field::PEERADDR, 3);
+}
+
// Test parsing of logical operators
TEST_F(EvalContextTest, logicalOps) {
// option.exists
checkTokenConcat(tmp3);
}
-// Test the parsing of a relay6 option
-TEST_F(EvalContextTest, relay6Option) {
- EvalContext eval(Option::V6);
-
- testRelay6Option("relay6[0].option[123].text == 'foo'",
- 0, 123, TokenOption::TEXTUAL, 3);
-}
-
-// Test the parsing of existence for a relay6 option
-TEST_F(EvalContextTest, relay6OptionExists) {
- EvalContext eval(Option::V6);
-
- testRelay6Option("relay6[1].option[75].exists",
- 1, 75, TokenOption::EXISTS, 1);
-}
-
-// Test the parsing of hex for a relay6 option
-TEST_F(EvalContextTest, relay6OptionHex) {
- EvalContext eval(Option::V6);
-
- testRelay6Option("relay6[2].option[85].hex == 'foo'",
- 2, 85, TokenOption::HEXADECIMAL, 3);
-}
-
-// Tests if the linkaddr field in a Relay6 encapsulation can be accessed.
-TEST_F(EvalContextTest, relay6FieldLinkAddr) {
- testRelay6Field("relay6[0].linkaddr == ::",
- 0, TokenRelay6Field::LINKADDR, 3);
-}
-
-// Tests if the peeraddr field in a Relay6 encapsulation can be accessed.
-TEST_F(EvalContextTest, relay6FieldPeerAddr) {
- testRelay6Field("relay6[1].peeraddr == ::",
- 1, TokenRelay6Field::PEERADDR, 3);
-}
-
//
// Test some scanner error cases
TEST_F(EvalContextTest, scanErrors) {
EXPECT_TRUE(checkFile());
}
+// This test checks if we can properly extract an option
+// from relay encapsulations. Our packet has two relay
+// encapsulations. Both include a common option with the
+// original message (option 100) and both include their
+// own option (101 and 102). We attempt to extract the
+// options and compare them to expected values. We also
+// try to extract an option from an encapsulation
+// that doesn't exist (level 2), this should result in an empty
+// string.
+TEST_F(TokenTest, relay6Option) {
+ // We start by adding a set of relay encapsulations to the
+ // basic v6 packet.
+ addRelay6Encapsulations();
+
+ // Then we work our way through the set of choices
+ // Level 0 both options it has and the check that
+ // the checking for an option it doesn't have results
+ // in an empty string.
+ verifyRelay6Option(0, 100, TokenOption::TEXTUAL, "hundred.zero");
+ verifyRelay6Option(0, 100, TokenOption::EXISTS, "true");
+ verifyRelay6Option(0, 101, TokenOption::TEXTUAL, "hundredone.zero");
+ verifyRelay6Option(0, 102, TokenOption::TEXTUAL, "");
+ verifyRelay6Option(0, 102, TokenOption::EXISTS, "false");
+
+ // Level 1, again both options it has and the one for level 0
+ verifyRelay6Option(1, 100, TokenOption::TEXTUAL, "hundred.one");
+ verifyRelay6Option(1, 101, TokenOption::TEXTUAL, "");
+ verifyRelay6Option(1, 102, TokenOption::TEXTUAL, "hundredtwo.one");
+
+ // Level 2, no encapsulation so no options
+ verifyRelay6Option(2, 100, TokenOption::TEXTUAL, "");
+
+ // Check that the debug output was correct. Add the strings
+ // to the test vector in the class and then call checkFile
+ // for comparison
+ addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'hundred.zero'");
+ addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'true'");
+ addString("EVAL_DEBUG_OPTION Pushing option 101 with value 'hundredone.zero'");
+ addString("EVAL_DEBUG_OPTION Pushing option 102 with value ''");
+ addString("EVAL_DEBUG_OPTION Pushing option 102 with value 'false'");
+
+ addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'hundred.one'");
+ addString("EVAL_DEBUG_OPTION Pushing option 101 with value ''");
+ addString("EVAL_DEBUG_OPTION Pushing option 102 with value 'hundredtwo.one'");
+
+ addString("EVAL_DEBUG_OPTION Pushing option 100 with value ''");
+
+ EXPECT_TRUE(checkFile());
+}
+
// Verifies if the DHCPv4 packet fields can be extracted.
TEST_F(TokenTest, pkt4Fields) {
pkt4_->setGiaddr(IOAddress("192.0.2.1"));
EXPECT_TRUE(checkFile());
}
+// Verifies if the DHCPv6 packet fields can be extracted.
+TEST_F(TokenTest, pkt6Fields) {
+ // The default test creates a v6 DHCPV6_SOLICIT packet with a
+ // transaction id of 12345.
+
+ // Check the message type
+ ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::MSGTYPE)));
+ EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
+ ASSERT_EQ(1, values_.size());
+ 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());
+ expected = htonl(12345);
+ EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
+
+ // Check that working with a v4 packet generates an error
+ clearStack();
+ ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+
+ // Check that the debug output was correct. Add the strings
+ // to the test vector in the class and then call checkFile
+ // for comparison
+ addString("EVAL_DEBUG_PKT6 Pushing PKT6 field msgtype with value 0x00000001");
+ addString("EVAL_DEBUG_PKT6 Pushing PKT6 field transid with value 0x00003039");
+
+ EXPECT_TRUE(checkFile());
+}
+
+// This test checks if we can properly extract the link and peer
+// address fields from relay encapsulations. Our packet has
+// two relay encapsulations. We attempt to extract the two
+// fields from both of the encapsulations and compare them.
+// We also try to extract one of the fields from an encapsulation
+// that doesn't exist (level 2), this should result in an empty
+// string.
+TEST_F(TokenTest, relay6Field) {
+ // Values for the address results
+ uint8_t zeroaddr[] = { 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 };
+ uint8_t linkaddr[] = { 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1 };
+ uint8_t peeraddr[] = { 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2 };
+
+ // We start by adding a set of relay encapsulations to the
+ // basic v6 packet.
+ addRelay6Encapsulations();
+
+ // Then we work our way through the set of choices
+ // Level 0 both link and peer address should be 0::0
+ verifyRelay6Eval(0, TokenRelay6Field::LINKADDR, 16, zeroaddr);
+ verifyRelay6Eval(0, TokenRelay6Field::PEERADDR, 16, zeroaddr);
+
+ // Level 1 link and peer should have different non-zero addresses
+ verifyRelay6Eval(1, TokenRelay6Field::LINKADDR, 16, linkaddr);
+ verifyRelay6Eval(1, TokenRelay6Field::PEERADDR, 16, peeraddr);
+
+ // Level 2 has no encapsulation so the address should be zero length
+ verifyRelay6Eval(2, TokenRelay6Field::LINKADDR, 0, zeroaddr);
+
+ // Lets check that the layout of the address returned by the
+ // token matches that of the TokenIpAddress
+ TokenPtr trelay;
+ TokenPtr taddr;
+ TokenPtr tequal;
+ ASSERT_NO_THROW(trelay.reset(new TokenRelay6Field(1, TokenRelay6Field::LINKADDR)));
+ ASSERT_NO_THROW(taddr.reset(new TokenIpAddress("1::1")));
+ ASSERT_NO_THROW(tequal.reset(new TokenEqual()));
+
+ EXPECT_NO_THROW(trelay->evaluate(*pkt6_, values_));
+ EXPECT_NO_THROW(taddr->evaluate(*pkt6_, values_));
+ EXPECT_NO_THROW(tequal->evaluate(*pkt6_, values_));
+
+ // We should have a single value on the stack and it should be "true"
+ ASSERT_EQ(1, values_.size());
+ EXPECT_EQ("true", values_.top());
+
+ // be tidy
+ clearStack();
+
+ // Check that the debug output was correct. Add the strings
+ // to the test vector in the class and then call checkFile
+ // for comparison
+ addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 0 "
+ "with value 0x00000000000000000000000000000000");
+ addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field peeraddr nest 0 "
+ "with value 0x00000000000000000000000000000000");
+ addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 1 "
+ "with value 0x00010000000000000000000000000001");
+ addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field peeraddr nest 1 "
+ "with value 0x00010000000000000000000000000002");
+ addString("EVAL_DEBUG_RELAY6_RANGE Pushing PKT6 relay field linkaddr nest 2 "
+ "with value 0x");
+
+ addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 1 "
+ "with value 0x00010000000000000000000000000001");
+ addString("EVAL_DEBUG_IPADDRESS Pushing IPAddress "
+ "0x00010000000000000000000000000001");
+ addString("EVAL_DEBUG_EQUAL Popping 0x00010000000000000000000000000001 "
+ "and 0x00010000000000000000000000000001 pushing result 'true'");
+
+ EXPECT_TRUE(checkFile());
+}
+
// This test checks if a token representing an == operator is able to
// compare two values (with incorrectly built stack).
TEST_F(TokenTest, optionEqualInvalid) {
EXPECT_TRUE(checkFile());
}
-// This test checks if a token representing a not is able to
-// negate a boolean value (with incorrectly built stack).
-TEST_F(TokenTest, operatorNotInvalid) {
-
- ASSERT_NO_THROW(t_.reset(new TokenNot()));
+// This test checks if a token representing a substring request
+// throws an exception if there aren't enough values on the stack.
+// The stack from the top is: length, start, string.
+// The actual packet is not used.
+TEST_F(TokenTest, substringNotEnoughValues) {
+ ASSERT_NO_THROW(t_.reset(new TokenSubstring()));
- // CASE 1: The stack is empty.
+ // Subsring requires three values on the stack, try
+ // with 0, 1 and 2 all should throw an exception
EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
- // CASE 2: The top value is not a boolean
- values_.push("foo");
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
-}
-
-// This test checks if a token representing a not operator is able to
-// negate a boolean value.
-TEST_F(TokenTest, operatorNot) {
+ values_.push("");
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
- ASSERT_NO_THROW(t_.reset(new TokenNot()));
+ values_.push("0");
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
- values_.push("true");
+ // Three should work
+ values_.push("0");
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
- // After evaluation there should be the negation of the value.
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ("false", values_.top());
-
- // Double negation is identity.
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+ // As we had an empty string to start with we should have an empty
+ // one after the evaluate
ASSERT_EQ(1, values_.size());
- EXPECT_EQ("true", values_.top());
+ EXPECT_EQ("", values_.top());
// Check that the debug output was correct. Add the strings
// to the test vector in the class and then call checkFile
// for comparison
- addString("EVAL_DEBUG_NOT Popping 'true' pushing 'false'");
- addString("EVAL_DEBUG_NOT Popping 'false' pushing 'true'");
+ addString("EVAL_DEBUG_SUBSTRING_EMPTY Popping length 0, start 0, "
+ "string 0x pushing result 0x");
EXPECT_TRUE(checkFile());
}
-// This test checks if a token representing an and is able to
-// conjugate two values (with incorrectly built stack).
-TEST_F(TokenTest, operatorAndInvalid) {
-
- ASSERT_NO_THROW(t_.reset(new TokenAnd()));
+// Test getting the whole string in different ways
+TEST_F(TokenTest, substringWholeString) {
+ // Get the whole string
+ verifySubstringEval("foobar", "0", "6", "foobar");
- // CASE 1: There's not enough values on the stack. and is an operator that
- // takes two parameters. There are 0 on the stack.
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
+ // Get the whole string with "all"
+ verifySubstringEval("foobar", "0", "all", "foobar");
- // CASE 2: One value is still not enough.
- values_.push("foo");
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
+ // Get the whole string with an extra long number
+ verifySubstringEval("foobar", "0", "123456", "foobar");
- // CASE 3: The two values must be logical
- values_.push("true");
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+ // Get the whole string counting from the back
+ verifySubstringEval("foobar", "-6", "all", "foobar");
- // Swap the 2 values
- values_.push("true");
- values_.push("foo");
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+ // Check that the debug output was correct. Add the strings
+ // to the test vector in the class and then call checkFile
+ // for comparison
+ addString("EVAL_DEBUG_SUBSTRING Popping length 6, start 0, "
+ "string 0x666F6F626172 pushing result 0x666F6F626172");
+ addString("EVAL_DEBUG_SUBSTRING Popping length all, start 0, "
+ "string 0x666F6F626172 pushing result 0x666F6F626172");
+ addString("EVAL_DEBUG_SUBSTRING Popping length 123456, start 0, "
+ "string 0x666F6F626172 pushing result 0x666F6F626172");
+ addString("EVAL_DEBUG_SUBSTRING Popping length all, start -6, "
+ "string 0x666F6F626172 pushing result 0x666F6F626172");
+ EXPECT_TRUE(checkFile());
}
-// This test checks if a token representing an and operator is able to
-// conjugate false with another logical
-TEST_F(TokenTest, operatorAndFalse) {
-
- ASSERT_NO_THROW(t_.reset(new TokenAnd()));
-
- values_.push("true");
- values_.push("false");
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
-
- // After evaluation there should be a single "false" value
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ("false", values_.top());
-
- // After true and false, check false and true
- values_.push("true");
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ("false", values_.top());
-
- // And false and false
- values_.push("false");
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ("false", values_.top());
-
- // Check that the debug output was correct. Add the strings
- // to the test vector in the class and then call checkFile
- // for comparison
- addString("EVAL_DEBUG_AND Popping 'false' and 'true' pushing 'false'");
- addString("EVAL_DEBUG_AND Popping 'true' and 'false' pushing 'false'");
- addString("EVAL_DEBUG_AND Popping 'false' and 'false' pushing 'false'");
- EXPECT_TRUE(checkFile());
-}
-
-// This test checks if a token representing an and is able to
-// conjugate two true values.
-TEST_F(TokenTest, operatorAndTrue) {
-
- ASSERT_NO_THROW(t_.reset(new TokenAnd()));
-
- values_.push("true");
- values_.push("true");
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
-
- // After evaluation there should be a single "true" value
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ("true", values_.top());
-
- // Check that the debug output was correct. Add the strings
- // to the test vector in the class and then call checkFile
- // for comparison
- addString("EVAL_DEBUG_AND Popping 'true' and 'true' pushing 'true'");
- EXPECT_TRUE(checkFile());
-}
-
-// This test checks if a token representing an or is able to
-// combinate two values (with incorrectly built stack).
-TEST_F(TokenTest, operatorOrInvalid) {
-
- ASSERT_NO_THROW(t_.reset(new TokenOr()));
-
- // CASE 1: There's not enough values on the stack. or is an operator that
- // takes two parameters. There are 0 on the stack.
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
-
- // CASE 2: One value is still not enough.
- values_.push("foo");
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
-
- // CASE 3: The two values must be logical
- values_.push("true");
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
-
- // Swap the 2 values
- values_.push("true");
- values_.push("foo");
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
-}
-
-// This test checks if a token representing an or is able to
-// conjugate two false values.
-TEST_F(TokenTest, operatorOrFalse) {
-
- ASSERT_NO_THROW(t_.reset(new TokenOr()));
-
- values_.push("false");
- values_.push("false");
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
-
- // After evaluation there should be a single "false" value
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ("false", values_.top());
-
- // Check that the debug output was correct. Add the strings
- // to the test vector in the class and then call checkFile
- // for comparison
- addString("EVAL_DEBUG_OR Popping 'false' and 'false' pushing 'false'");
- EXPECT_TRUE(checkFile());
-}
-
-// This test checks if a token representing an == operator is able to
-// conjugate true with another logical
-TEST_F(TokenTest, operatorOrTrue) {
-
- ASSERT_NO_THROW(t_.reset(new TokenOr()));
-
- values_.push("false");
- values_.push("true");
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
-
- // After evaluation there should be a single "true" value
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ("true", values_.top());
-
- // After false or true, checks true or false
- values_.push("false");
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ("true", values_.top());
-
- // And true or true
- values_.push("true");
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ("true", values_.top());
-
- // Check that the debug output was correct. Add the strings
- // to the test vector in the class and then call checkFile
- // for comparison
- addString("EVAL_DEBUG_OR Popping 'true' and 'false' pushing 'true'");
- addString("EVAL_DEBUG_OR Popping 'false' and 'true' pushing 'true'");
- addString("EVAL_DEBUG_OR Popping 'true' and 'true' pushing 'true'");
- EXPECT_TRUE(checkFile());
-}
-
-// This test checks if a token representing a substring request
-// throws an exception if there aren't enough values on the stack.
-// The stack from the top is: length, start, string.
-// The actual packet is not used.
-TEST_F(TokenTest, substringNotEnoughValues) {
- ASSERT_NO_THROW(t_.reset(new TokenSubstring()));
-
- // Subsring requires three values on the stack, try
- // with 0, 1 and 2 all should throw an exception
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
-
- values_.push("");
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
-
- values_.push("0");
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
-
- // Three should work
- values_.push("0");
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
-
- // As we had an empty string to start with we should have an empty
- // one after the evaluate
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ("", values_.top());
-
- // Check that the debug output was correct. Add the strings
- // to the test vector in the class and then call checkFile
- // for comparison
- addString("EVAL_DEBUG_SUBSTRING_EMPTY Popping length 0, start 0, "
- "string 0x pushing result 0x");
- EXPECT_TRUE(checkFile());
-}
-
-// Test getting the whole string in different ways
-TEST_F(TokenTest, substringWholeString) {
- // Get the whole string
- verifySubstringEval("foobar", "0", "6", "foobar");
-
- // Get the whole string with "all"
- verifySubstringEval("foobar", "0", "all", "foobar");
-
- // Get the whole string with an extra long number
- verifySubstringEval("foobar", "0", "123456", "foobar");
-
- // Get the whole string counting from the back
- verifySubstringEval("foobar", "-6", "all", "foobar");
-
- // Check that the debug output was correct. Add the strings
- // to the test vector in the class and then call checkFile
- // for comparison
- addString("EVAL_DEBUG_SUBSTRING Popping length 6, start 0, "
- "string 0x666F6F626172 pushing result 0x666F6F626172");
- addString("EVAL_DEBUG_SUBSTRING Popping length all, start 0, "
- "string 0x666F6F626172 pushing result 0x666F6F626172");
- addString("EVAL_DEBUG_SUBSTRING Popping length 123456, start 0, "
- "string 0x666F6F626172 pushing result 0x666F6F626172");
- addString("EVAL_DEBUG_SUBSTRING Popping length all, start -6, "
- "string 0x666F6F626172 pushing result 0x666F6F626172");
- EXPECT_TRUE(checkFile());
-}
-
-// Test getting a suffix, in this case the last 3 characters
-TEST_F(TokenTest, substringTrailer) {
- verifySubstringEval("foobar", "3", "3", "bar");
- verifySubstringEval("foobar", "3", "all", "bar");
- verifySubstringEval("foobar", "-3", "all", "bar");
- verifySubstringEval("foobar", "-3", "123", "bar");
+// Test getting a suffix, in this case the last 3 characters
+TEST_F(TokenTest, substringTrailer) {
+ verifySubstringEval("foobar", "3", "3", "bar");
+ verifySubstringEval("foobar", "3", "all", "bar");
+ verifySubstringEval("foobar", "-3", "all", "bar");
+ verifySubstringEval("foobar", "-3", "123", "bar");
// Check that the debug output was correct. Add the strings
// to the test vector in the class and then call checkFile
EXPECT_TRUE(checkFile());
}
-// This test checks if we can properly extract the link and peer
-// address fields from relay encapsulations. Our packet has
-// two relay encapsulations. We attempt to extract the two
-// fields from both of the encapsulations and compare them.
-// We also try to extract one of the fields from an encapsulation
-// that doesn't exist (level 2), this should result in an empty
-// string.
-TEST_F(TokenTest, relay6Field) {
- // Values for the address results
- uint8_t zeroaddr[] = { 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0 };
- uint8_t linkaddr[] = { 0, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1 };
- uint8_t peeraddr[] = { 0, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 2 };
+// This test checks if a token representing a not is able to
+// negate a boolean value (with incorrectly built stack).
+TEST_F(TokenTest, operatorNotInvalid) {
- // We start by adding a set of relay encapsulations to the
- // basic v6 packet.
- addRelay6Encapsulations();
+ ASSERT_NO_THROW(t_.reset(new TokenNot()));
- // Then we work our way through the set of choices
- // Level 0 both link and peer address should be 0::0
- verifyRelay6Eval(0, TokenRelay6Field::LINKADDR, 16, zeroaddr);
- verifyRelay6Eval(0, TokenRelay6Field::PEERADDR, 16, zeroaddr);
+ // CASE 1: The stack is empty.
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
- // Level 1 link and peer should have different non-zero addresses
- verifyRelay6Eval(1, TokenRelay6Field::LINKADDR, 16, linkaddr);
- verifyRelay6Eval(1, TokenRelay6Field::PEERADDR, 16, peeraddr);
+ // CASE 2: The top value is not a boolean
+ values_.push("foo");
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+}
- // Level 2 has no encapsulation so the address should be zero length
- verifyRelay6Eval(2, TokenRelay6Field::LINKADDR, 0, zeroaddr);
+// This test checks if a token representing a not operator is able to
+// negate a boolean value.
+TEST_F(TokenTest, operatorNot) {
- // Lets check that the layout of the address returned by the
- // token matches that of the TokenIpAddress
- TokenPtr trelay;
- TokenPtr taddr;
- TokenPtr tequal;
- ASSERT_NO_THROW(trelay.reset(new TokenRelay6Field(1, TokenRelay6Field::LINKADDR)));
- ASSERT_NO_THROW(taddr.reset(new TokenIpAddress("1::1")));
- ASSERT_NO_THROW(tequal.reset(new TokenEqual()));
+ ASSERT_NO_THROW(t_.reset(new TokenNot()));
- EXPECT_NO_THROW(trelay->evaluate(*pkt6_, values_));
- EXPECT_NO_THROW(taddr->evaluate(*pkt6_, values_));
- EXPECT_NO_THROW(tequal->evaluate(*pkt6_, values_));
+ values_.push("true");
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
- // We should have a single value on the stack and it should be "true"
+ // After evaluation there should be the negation of the value.
ASSERT_EQ(1, values_.size());
- EXPECT_EQ("true", values_.top());
+ EXPECT_EQ("false", values_.top());
- // be tidy
- clearStack();
+ // Double negation is identity.
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+ ASSERT_EQ(1, values_.size());
+ EXPECT_EQ("true", values_.top());
// Check that the debug output was correct. Add the strings
// to the test vector in the class and then call checkFile
// for comparison
- addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 0 "
- "with value 0x00000000000000000000000000000000");
- addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field peeraddr nest 0 "
- "with value 0x00000000000000000000000000000000");
- addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 1 "
- "with value 0x00010000000000000000000000000001");
- addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field peeraddr nest 1 "
- "with value 0x00010000000000000000000000000002");
- addString("EVAL_DEBUG_RELAY6_RANGE Pushing PKT6 relay field linkaddr nest 2 "
- "with value 0x");
+ addString("EVAL_DEBUG_NOT Popping 'true' pushing 'false'");
+ addString("EVAL_DEBUG_NOT Popping 'false' pushing 'true'");
+ EXPECT_TRUE(checkFile());
+}
- addString("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 1 "
- "with value 0x00010000000000000000000000000001");
- addString("EVAL_DEBUG_IPADDRESS Pushing IPAddress "
- "0x00010000000000000000000000000001");
- addString("EVAL_DEBUG_EQUAL Popping 0x00010000000000000000000000000001 "
- "and 0x00010000000000000000000000000001 pushing result 'true'");
+// This test checks if a token representing an and is able to
+// conjugate two values (with incorrectly built stack).
+TEST_F(TokenTest, operatorAndInvalid) {
+
+ ASSERT_NO_THROW(t_.reset(new TokenAnd()));
+
+ // CASE 1: There's not enough values on the stack. and is an operator that
+ // takes two parameters. There are 0 on the stack.
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
+
+ // CASE 2: One value is still not enough.
+ values_.push("foo");
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
+
+ // CASE 3: The two values must be logical
+ values_.push("true");
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+
+ // Swap the 2 values
+ values_.push("true");
+ values_.push("foo");
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+}
+
+// This test checks if a token representing an and operator is able to
+// conjugate false with another logical
+TEST_F(TokenTest, operatorAndFalse) {
+
+ ASSERT_NO_THROW(t_.reset(new TokenAnd()));
+ values_.push("true");
+ values_.push("false");
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+
+ // After evaluation there should be a single "false" value
+ ASSERT_EQ(1, values_.size());
+ EXPECT_EQ("false", values_.top());
+
+ // After true and false, check false and true
+ values_.push("true");
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+ ASSERT_EQ(1, values_.size());
+ EXPECT_EQ("false", values_.top());
+
+ // And false and false
+ values_.push("false");
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+ ASSERT_EQ(1, values_.size());
+ EXPECT_EQ("false", values_.top());
+
+ // Check that the debug output was correct. Add the strings
+ // to the test vector in the class and then call checkFile
+ // for comparison
+ addString("EVAL_DEBUG_AND Popping 'false' and 'true' pushing 'false'");
+ addString("EVAL_DEBUG_AND Popping 'true' and 'false' pushing 'false'");
+ addString("EVAL_DEBUG_AND Popping 'false' and 'false' pushing 'false'");
EXPECT_TRUE(checkFile());
}
-// This test checks if we can properly extract an option
-// from relay encapsulations. Our packet has two relay
-// encapsulations. Both include a common option with the
-// original message (option 100) and both include their
-// own option (101 and 102). We attempt to extract the
-// options and compare them to expected values. We also
-// try to extract an option from an encapsulation
-// that doesn't exist (level 2), this should result in an empty
-// string.
-TEST_F(TokenTest, relay6Option) {
- // We start by adding a set of relay encapsulations to the
- // basic v6 packet.
- addRelay6Encapsulations();
+// This test checks if a token representing an and is able to
+// conjugate two true values.
+TEST_F(TokenTest, operatorAndTrue) {
- // Then we work our way through the set of choices
- // Level 0 both options it has and the check that
- // the checking for an option it doesn't have results
- // in an empty string.
- verifyRelay6Option(0, 100, TokenOption::TEXTUAL, "hundred.zero");
- verifyRelay6Option(0, 100, TokenOption::EXISTS, "true");
- verifyRelay6Option(0, 101, TokenOption::TEXTUAL, "hundredone.zero");
- verifyRelay6Option(0, 102, TokenOption::TEXTUAL, "");
- verifyRelay6Option(0, 102, TokenOption::EXISTS, "false");
+ ASSERT_NO_THROW(t_.reset(new TokenAnd()));
- // Level 1, again both options it has and the one for level 0
- verifyRelay6Option(1, 100, TokenOption::TEXTUAL, "hundred.one");
- verifyRelay6Option(1, 101, TokenOption::TEXTUAL, "");
- verifyRelay6Option(1, 102, TokenOption::TEXTUAL, "hundredtwo.one");
+ values_.push("true");
+ values_.push("true");
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
- // Level 2, no encapsulation so no options
- verifyRelay6Option(2, 100, TokenOption::TEXTUAL, "");
+ // After evaluation there should be a single "true" value
+ ASSERT_EQ(1, values_.size());
+ EXPECT_EQ("true", values_.top());
// Check that the debug output was correct. Add the strings
// to the test vector in the class and then call checkFile
// for comparison
- addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'hundred.zero'");
- addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'true'");
- addString("EVAL_DEBUG_OPTION Pushing option 101 with value 'hundredone.zero'");
- addString("EVAL_DEBUG_OPTION Pushing option 102 with value ''");
- addString("EVAL_DEBUG_OPTION Pushing option 102 with value 'false'");
+ addString("EVAL_DEBUG_AND Popping 'true' and 'true' pushing 'true'");
+ EXPECT_TRUE(checkFile());
+}
- addString("EVAL_DEBUG_OPTION Pushing option 100 with value 'hundred.one'");
- addString("EVAL_DEBUG_OPTION Pushing option 101 with value ''");
- addString("EVAL_DEBUG_OPTION Pushing option 102 with value 'hundredtwo.one'");
+// This test checks if a token representing an or is able to
+// combinate two values (with incorrectly built stack).
+TEST_F(TokenTest, operatorOrInvalid) {
- addString("EVAL_DEBUG_OPTION Pushing option 100 with value ''");
+ ASSERT_NO_THROW(t_.reset(new TokenOr()));
+
+ // CASE 1: There's not enough values on the stack. or is an operator that
+ // takes two parameters. There are 0 on the stack.
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
+
+ // CASE 2: One value is still not enough.
+ values_.push("foo");
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
+
+ // CASE 3: The two values must be logical
+ values_.push("true");
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+
+ // Swap the 2 values
+ values_.push("true");
+ values_.push("foo");
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+}
+
+// This test checks if a token representing an or is able to
+// conjugate two false values.
+TEST_F(TokenTest, operatorOrFalse) {
+
+ ASSERT_NO_THROW(t_.reset(new TokenOr()));
+
+ values_.push("false");
+ values_.push("false");
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+ // After evaluation there should be a single "false" value
+ ASSERT_EQ(1, values_.size());
+ EXPECT_EQ("false", values_.top());
+
+ // Check that the debug output was correct. Add the strings
+ // to the test vector in the class and then call checkFile
+ // for comparison
+ addString("EVAL_DEBUG_OR Popping 'false' and 'false' pushing 'false'");
EXPECT_TRUE(checkFile());
}
-// Verifies if the DHCPv6 packet fields can be extracted.
-TEST_F(TokenTest, pkt6Fields) {
- // The default test creates a v6 DHCPV6_SOLICIT packet with a
- // transaction id of 12345.
+// This test checks if a token representing an == operator is able to
+// conjugate true with another logical
+TEST_F(TokenTest, operatorOrTrue) {
- // Check the message type
- ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::MSGTYPE)));
- EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
+ ASSERT_NO_THROW(t_.reset(new TokenOr()));
+
+ values_.push("false");
+ values_.push("true");
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+
+ // After evaluation there should be a single "true" value
ASSERT_EQ(1, values_.size());
- uint32_t expected = htonl(1);
- EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
+ EXPECT_EQ("true", values_.top());
- // Check the transaction id field
- clearStack();
- ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
- EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
+ // After false or true, checks true or false
+ values_.push("false");
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
- expected = htonl(12345);
- EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
+ EXPECT_EQ("true", values_.top());
- // Check that working with a v4 packet generates an error
- clearStack();
- ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
- EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+ // And true or true
+ values_.push("true");
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+ ASSERT_EQ(1, values_.size());
+ EXPECT_EQ("true", values_.top());
// Check that the debug output was correct. Add the strings
// to the test vector in the class and then call checkFile
// for comparison
- addString("EVAL_DEBUG_PKT6 Pushing PKT6 field msgtype with value 0x00000001");
- addString("EVAL_DEBUG_PKT6 Pushing PKT6 field transid with value 0x00003039");
-
+ addString("EVAL_DEBUG_OR Popping 'true' and 'false' pushing 'true'");
+ addString("EVAL_DEBUG_OR Popping 'false' and 'true' pushing 'true'");
+ addString("EVAL_DEBUG_OR Popping 'true' and 'true' pushing 'true'");
EXPECT_TRUE(checkFile());
}
+
};
/// The order where Token subtypes are declared should be:
/// - literal terminals
/// - option & co
-/// - pkt & co
+/// - pkt field & co
/// - ==
/// - substring & co
/// - not, and, or
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
+ virtual OptionPtr getOption(const Pkt& pkt);
+
+ uint8_t nest_level_; ///< nesting level of the relay block to use
+};
+
/// @brief Token that represents fields of a DHCPv4 packet.
///
/// For example in the expression pkt4.chaddr == 0x0102030405
FieldType type_;
};
+/// @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);
+
+ /// @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(const 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"
void evaluate(const 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(const 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(const 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(const 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