Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
7e468146
Commit
7e468146
authored
Apr 04, 2016
by
Shawn Routhier
Browse files
[trac4265] Add test code, tidy up main code
parent
ce3d4e3c
Changes
9
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
7e468146
1xxx. [func] sar
Added access to the peer address, link address and option
information added by relays in a DHCPv6 message.
(Trac $4269, git tbd)
1098. [func] kalmus, marcin
Implemented IPv6 address/prefix reservations in MySQL.
(Trac #4212, git 79481043935789fc6898d4743bede1606f82eb75)
...
...
doc/guide/classify.xml
View file @
7e468146
...
...
@@ -170,6 +170,24 @@
sub-option
</entry><entry>
relay4[code].hex
</entry><entry>
The value of
sub-option with code "code" from the DHCPv4 Relay Agent Information option
(option 82)
</entry></row>
<row>
<entry>
DHCPv6 Relay Options
</entry>
<entry>
relay6[nest].option[code].hex
</entry>
<!-- <entry>Value of the option</entry> -->
<entry>
The value of the option with code "code" from the relay encapsulation "nest"
</entry>
</row>
<row>
<entry>
DHCPv6 Relay Peer Address
</entry>
<entry>
relay6[nest].peeraddr
</entry>
<!-- <entry>2001:DB8::1</entry> -->
n
<entry>
The value of the peer address field from the relay encapsulation "nest"
</entry>
</row>
<row>
<entry>
DHCPv6 Relay Link Address
</entry>
<entry>
relay6[nest].linkaddr
</entry>
<!-- <entry>2001:DB8::1</entry> -->
n
<entry>
The value of the link address field from the relay encapsulation "nest"
</entry>
</row>
</tbody>
</tgroup>
</table>
...
...
@@ -211,10 +229,24 @@ sub-option with code "code" from the DHCPv4 Relay Agent Information option
</para>
<para>
"relay4" shares the same representation types
than
"option", for
"relay4" shares the same representation types
as
"option", for
instance "relay4[code].exists" is supported.
</para>
<para>
"relay6[nest]" allows access to the encapsulations used by any DHCPv6
relays that forwarded the packet. The "nest" level specifies the relay
from which to extract the information, with a value of 0 indicating
the relay closest to the DHCPv6 server. If the requested encapsulation
doesn't exist an empty string "" is returned. This expression is
allowed in DHCPv6 only.
</para>
<para>
"relay6[nest].option[code]" shares the same representation types as
"option", for instance "relay6[nest].option[code].exists" is supported.
</para>
<para>
<table
frame=
"all"
id=
"classification-expressions-list"
>
<title>
List of Classification Expressions
</title>
...
...
src/lib/dhcp/pkt6.cc
View file @
7e468146
...
...
@@ -119,13 +119,33 @@ OptionPtr Pkt6::getRelayOption(uint16_t opt_type, uint8_t relay_level) const {
}
OptionCollection
::
const_iterator
x
=
relay_info_
[
relay_level
].
options_
.
find
(
opt_type
);
if
(
x
!=
options_
.
end
())
{
if
(
x
!=
relay_info_
[
relay_level
].
options_
.
end
())
{
return
(
*
x
).
second
;
}
return
(
OptionPtr
());
}
const
isc
::
asiolink
::
IOAddress
&
Pkt6
::
getRelay6LinkAddress
(
uint8_t
relay_level
)
const
{
if
(
relay_level
>=
relay_info_
.
size
())
{
isc_throw
(
OutOfRange
,
"This message was relayed "
<<
relay_info_
.
size
()
<<
" time(s)."
<<
" There is no info about "
<<
relay_level
+
1
<<
" relay."
);
}
return
(
relay_info_
[
relay_level
].
linkaddr_
);
}
const
isc
::
asiolink
::
IOAddress
&
Pkt6
::
getRelay6PeerAddress
(
uint8_t
relay_level
)
const
{
if
(
relay_level
>=
relay_info_
.
size
())
{
isc_throw
(
OutOfRange
,
"This message was relayed "
<<
relay_info_
.
size
()
<<
" time(s)."
<<
" There is no info about "
<<
relay_level
+
1
<<
" relay."
);
}
return
(
relay_info_
[
relay_level
].
peeraddr_
);
}
uint16_t
Pkt6
::
getRelayOverhead
(
const
RelayInfo
&
relay
)
const
{
uint16_t
len
=
DHCPV6_RELAY_HDR_LEN
// fixed header
+
Option
::
OPTION6_HDR_LEN
;
// header of the relay-msg option
...
...
src/lib/dhcp/pkt6.h
View file @
7e468146
...
...
@@ -253,6 +253,39 @@ public:
/// @return option pointer (or NULL if no option matches specified criteria)
OptionPtr
getAnyRelayOption
(
uint16_t
option_code
,
RelaySearchOrder
order
);
/// @brief return the link address field from a relay option
///
/// As with @c Pkt6::getRelayOption this returns information from the
/// specified relay scope. The relay_level specifies which relay
/// scope is to be used. 0 is the outermost encapsulation (relay closest
/// to the server). pkt->relay_info_.size() -1 is the innermost encapsulation
/// (relay closest to the client).
///
/// @throw isc::OutOfRange if relay level has an invalid value.
///
/// @param relay_level see description above
///
/// @return pointer to the link address field
const
isc
::
asiolink
::
IOAddress
&
getRelay6LinkAddress
(
uint8_t
relay_level
)
const
;
/// @brief return the peer address field from a relay option
///
/// As with @c Pkt6::getRelayOption this returns information from the
/// specified relay scope. The relay_level specifies which relay
/// scope is to be used. 0 is the outermost encapsulation (relay closest
/// to the server). pkt->relay_info_.size() -1 is the innermost encapsulation
/// (relay closest to the client).
///
/// @throw isc::OutOfRange if relay level has an invalid value.
///
/// @param relay_level see description above
///
/// @return pointer to the peer address field
const
isc
::
asiolink
::
IOAddress
&
getRelay6PeerAddress
(
uint8_t
relay_level
)
const
;
///
/// @brief Returns all instances of specified type.
///
/// Returns all instances of options of the specified type. DHCPv6 protocol
...
...
@@ -279,13 +312,13 @@ public:
/// @param type DHCPv6 message type which name should be returned.
///
/// @return Pointer to "const" string containing the message name. If
/// the message type is unkn
n
own the "UNKNOWN" is returned. The caller
/// the message type is unknown the "UNKNOWN" is returned. The caller
/// must not release the returned pointer.
static
const
char
*
getName
(
const
uint8_t
type
);
/// @brief Returns name of the DHCPv6 message.
///
/// This method requires an object. There is also static version, which
/// This method requires an object. There is also
a
static version, which
/// requires one parameter (type).
///
/// @return Pointer to "const" string containing the message name. If
...
...
src/lib/dhcp/tests/pkt6_unittest.cc
View file @
7e468146
...
...
@@ -763,7 +763,7 @@ TEST_F(Pkt6Test, relayPack) {
Pkt6
::
RelayInfo
relay1
;
relay1
.
msg_type_
=
DHCPV6_RELAY_REPL
;
relay1
.
hop_count_
=
17
;
// not very m
i
ningful, but useful for testing
relay1
.
hop_count_
=
17
;
// not very m
ea
ningful, but useful for testing
relay1
.
linkaddr_
=
IOAddress
(
"2001:db8::1"
);
relay1
.
peeraddr_
=
IOAddress
(
"fe80::abcd"
);
...
...
@@ -830,6 +830,16 @@ TEST_F(Pkt6Test, relayPack) {
OptionBuffer
data
=
opt
->
getData
();
ASSERT_EQ
(
data
.
size
(),
sizeof
(
relay_opt_data
));
EXPECT_EQ
(
0
,
memcmp
(
&
data
[
0
],
relay_opt_data
,
sizeof
(
relay_opt_data
)));
// As we have a nicely built relay packet we can check
// that the functions to get the peer and link addreses work
EXPECT_EQ
(
"2001:db8::1"
,
clone
->
getRelay6LinkAddress
(
0
).
toText
());
EXPECT_EQ
(
"fe80::abcd"
,
clone
->
getRelay6PeerAddress
(
0
).
toText
());
vector
<
uint8_t
>
binary
=
clone
->
getRelay6LinkAddress
(
0
).
toBytes
();
uint8_t
expected0
[]
=
{
0x20
,
1
,
0x0d
,
0xb8
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
};
EXPECT_EQ
(
0
,
memcmp
(
expected0
,
&
binary
[
0
],
16
));
}
...
...
src/lib/eval/tests/context_unittest.cc
View file @
7e468146
...
...
@@ -148,6 +148,114 @@ public:
EXPECT_TRUE
(
conc
);
}
/// @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 a TokenRelay with the
/// correct nesting level and field type.
/// @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
checkTokenRelay6
(
const
TokenPtr
&
token
,
uint8_t
expected_level
,
TokenRelay6
::
FieldType
expected_type
)
{
ASSERT_TRUE
(
token
);
boost
::
shared_ptr
<
TokenRelay6
>
opt
=
boost
::
dynamic_pointer_cast
<
TokenRelay6
>
(
token
);
ASSERT_TRUE
(
opt
);
EXPECT_EQ
(
expected_level
,
opt
->
getNest
());
EXPECT_EQ
(
expected_type
,
opt
->
getType
());
}
/// @brief This tests attempts to parse the expression then checks
/// if the number of tokens is correct and the TokenRelay6 is as
/// expected.
///
/// @param expr expression to be parsed
/// @param exp_level expected level to be parsed
/// @param exp_type expected field type to be parsed
/// @param exp_tokens expected number of tokens
void
testRelay6Field
(
std
::
string
expr
,
uint8_t
exp_level
,
TokenRelay6
::
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 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 TokenRelay6 and that
// is has the correct attributes
checkTokenRelay6
(
eval
.
expression
.
at
(
0
),
exp_level
,
exp_type
);
}
/// @brief checks if the given expression raises the expected message
/// when it is parsed.
void
checkError
(
const
string
&
expr
,
const
string
&
msg
)
{
...
...
@@ -576,6 +684,43 @@ TEST_F(EvalContextTest, concat) {
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
,
TokenRelay6
::
LINKADDR
,
3
);
}
// Tests if the peeraddr field in a Relay6 encapsulation can be accessed.
TEST_F
(
EvalContextTest
,
relay6FieldPeerAddr
)
{
testRelay6Field
(
"relay6[1].peeraddr == ::"
,
1
,
TokenRelay6
::
PEERADDR
,
3
);
}
//
// Test some scanner error cases
TEST_F
(
EvalContextTest
,
scanErrors
)
{
checkError
(
"'"
,
"<string>:1.1: Invalid character: '"
);
...
...
src/lib/eval/tests/token_unittest.cc
View file @
7e468146
...
...
@@ -62,6 +62,111 @@ public:
pkt4_
->
addOption
(
rai
);
}
/// @brief Adds relay encapsulations with some suboptions
///
/// This will add 2 relay encapsulations all will have
/// msg_type of RELAY_FORW
/// Relay 0 (closest to server) will have
/// linkaddr = peeraddr = 0, hop-count = 1
/// option 100 "hundred.zero", option 101 "hundredone.zero"
/// Relay 1 (closest to client) will have
/// linkaddr 1::1= peeraddr = 1::2, hop-count = 0
/// option 100 "hundred.one", option 102 "hundredtwo.one"
void
addRelay6Encapsulations
()
{
// First relay
Pkt6
::
RelayInfo
relay0
;
relay0
.
msg_type_
=
DHCPV6_RELAY_FORW
;
relay0
.
hop_count_
=
1
;
relay0
.
linkaddr_
=
isc
::
asiolink
::
IOAddress
(
"::"
);
relay0
.
peeraddr_
=
isc
::
asiolink
::
IOAddress
(
"::"
);
OptionPtr
optRelay01
(
new
OptionString
(
Option
::
V6
,
100
,
"hundred.zero"
));
OptionPtr
optRelay02
(
new
OptionString
(
Option
::
V6
,
101
,
"hundredone.zero"
));
relay0
.
options_
.
insert
(
make_pair
(
optRelay01
->
getType
(),
optRelay01
));
relay0
.
options_
.
insert
(
make_pair
(
optRelay02
->
getType
(),
optRelay02
));
pkt6_
->
addRelayInfo
(
relay0
);
// Second relay
Pkt6
::
RelayInfo
relay1
;
relay1
.
msg_type_
=
DHCPV6_RELAY_FORW
;
relay1
.
hop_count_
=
0
;
relay1
.
linkaddr_
=
isc
::
asiolink
::
IOAddress
(
"1::1"
);
relay1
.
peeraddr_
=
isc
::
asiolink
::
IOAddress
(
"1::2"
);
OptionPtr
optRelay11
(
new
OptionString
(
Option
::
V6
,
100
,
"hundred.one"
));
OptionPtr
optRelay12
(
new
OptionString
(
Option
::
V6
,
102
,
"hundredtwo.one"
));
relay1
.
options_
.
insert
(
make_pair
(
optRelay11
->
getType
(),
optRelay11
));
relay1
.
options_
.
insert
(
make_pair
(
optRelay12
->
getType
(),
optRelay12
));
pkt6_
->
addRelayInfo
(
relay1
);
}
/// @brief Verify that the relay6 option evaluatiosn work properly
///
/// Given the nesting level and option code extract the option
/// and compare it to the expected string.
///
/// @param test_level The nesting level
/// @param test_code The code of the option to extract
/// @param result_addr The expected result of the address as a string
void
verifyRelay6Option
(
const
uint8_t
test_level
,
const
uint16_t
test_code
,
const
TokenOption
::
RepresentationType
&
test_rep
,
const
std
::
string
&
result_string
)
{
// Create the token
ASSERT_NO_THROW
(
t_
.
reset
(
new
TokenRelay6Option
(
test_level
,
test_code
,
test_rep
)));
// We should be able to evaluate it
EXPECT_NO_THROW
(
t_
->
evaluate
(
*
pkt6_
,
values_
));
// We should have one value on the stack
ASSERT_EQ
(
1
,
values_
.
size
());
// And it should match the expected result
// Invalid nesting levels result in a 0 length string
EXPECT_EQ
(
result_string
,
values_
.
top
());
// Then we clear the stack
clearStack
();
}
/// @brief Verify that the relay6 field evaluations work properly
///
/// Given the nesting level, the field to extract and the expected
/// address create a token and evaluate it then compare the addresses
///
/// @param test_level The nesting level
/// @param test_field The type of the field to extract
/// @param result_addr The expected result of the address as a string
void
verifyRelay6Eval
(
const
uint8_t
test_level
,
const
TokenRelay6
::
FieldType
test_field
,
const
int
result_len
,
const
uint8_t
result_addr
[])
{
// Create the token
ASSERT_NO_THROW
(
t_
.
reset
(
new
TokenRelay6
(
test_level
,
test_field
)));
// We should be able to evaluate it
EXPECT_NO_THROW
(
t_
->
evaluate
(
*
pkt6_
,
values_
));
// We should have one value on the stack
ASSERT_EQ
(
1
,
values_
.
size
());
// And it should match the expected result
// Invalid nesting levels result in a 0 length string
EXPECT_EQ
(
result_len
,
values_
.
top
().
size
());
if
(
result_len
!=
0
)
{
EXPECT_EQ
(
0
,
memcmp
(
result_addr
,
&
values_
.
top
()[
0
],
result_len
));
}
// Then we clear the stack
clearStack
();
}
/// @brief Convenience function. Removes token and values stacks.
void
clearStack
()
{
while
(
!
values_
.
empty
())
{
...
...
@@ -1012,3 +1117,89 @@ TEST_F(TokenTest, concat) {
ASSERT_EQ
(
1
,
values_
.
size
());
EXPECT_EQ
(
"foobar"
,
values_
.
top
());
}
// 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
,
TokenRelay6
::
LINKADDR
,
16
,
zeroaddr
);
verifyRelay6Eval
(
0
,
TokenRelay6
::
PEERADDR
,
16
,
zeroaddr
);
// Level 1 link and peer should have different non-zero addresses
verifyRelay6Eval
(
1
,
TokenRelay6
::
LINKADDR
,
16
,
linkaddr
);
verifyRelay6Eval
(
1
,
TokenRelay6
::
PEERADDR
,
16
,
peeraddr
);
// Level 2 has no encapsulation so the address should be zero length
verifyRelay6Eval
(
2
,
TokenRelay6
::
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
TokenRelay6
(
1
,
TokenRelay6
::
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
();
}
// 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
,
""
);
}
src/lib/eval/token.cc
View file @
7e468146
...
...
@@ -322,7 +322,39 @@ OptionPtr TokenRelay6Option::getOption(const Pkt& pkt) {
}
void
TokenRelay6
::
evaluate
(
const
Pkt
&
/*pkt*/
,
ValueStack
&
values
)
{
// test routine, need to add code in pkt6 to get the proper fields
values
.
push
(
""
);
TokenRelay6
::
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.
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
:
binary
=
pkt6
.
getRelay6LinkAddress
(
nest_level_
).
toBytes
();
break
;
case
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
(
""
);
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
);
}
src/lib/eval/token.h
View file @
7e468146
...
...
@@ -490,7 +490,7 @@ public:
/// @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
)
const
RepresentationType
&
rep_type
)
:
TokenOption
(
option_code
,
rep_type
),
nest_level_
(
nest_level
)
{}
/// @brief Returns nest-level
...
...
@@ -529,7 +529,7 @@ protected:
/// The nesting level can go from 0 (closest to the server) to 31.
class
TokenRelay6
:
public
Token
{
public:
/// @brief enum value that determines the field.
enum
FieldType
{
PEERADDR
,
///< Peer address field (IPv6 address)
...
...
@@ -553,6 +553,17 @@ public:
/// @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 TokenRelay6 with correct parameters.
///
/// @return nest-level of the relay block this token expects to use