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
d92e7686
Commit
d92e7686
authored
Oct 29, 2014
by
Tomek Mrugalski
🛰
Browse files
[master] Merge branch 'trac3549' (extract MAC from link-local address)
parents
8b34dcb7
16b7fb6d
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/lib/dhcp/pkt.cc
View file @
d92e7686
...
...
@@ -14,6 +14,8 @@
#include
<utility>
#include
<dhcp/pkt.h>
#include
<dhcp/iface_mgr.h>
#include
<vector>
namespace
isc
{
namespace
dhcp
{
...
...
@@ -125,6 +127,8 @@ Pkt::setHWAddrMember(const uint8_t htype, const uint8_t,
HWAddrPtr
Pkt
::
getMAC
(
uint32_t
hw_addr_src
)
{
HWAddrPtr
mac
;
// Method 1: from raw sockets.
if
(
hw_addr_src
&
HWADDR_SOURCE_RAW
)
{
mac
=
getRemoteHWAddr
();
if
(
mac
)
{
...
...
@@ -136,11 +140,79 @@ Pkt::getMAC(uint32_t hw_addr_src) {
}
}
// Method 2: Extracted from DUID-LLT or DUID-LL
// Method 3: Extracted from source IPv6 link-local address
if
(
hw_addr_src
&
HWADDR_SOURCE_IPV6_LINK_LOCAL
)
{
mac
=
getMACFromSrcLinkLocalAddr
();
if
(
mac
)
{
return
(
mac
);
}
else
if
(
hw_addr_src
==
HWADDR_SOURCE_IPV6_LINK_LOCAL
)
{
// If we're interested only in link-local addr as source of that
// info, there's no point in trying other options.
return
(
HWAddrPtr
());
}
}
// Method 4: From client link-layer address option inserted by a relay
// Method 5: From remote-id option inserted by a relay
// Method 6: From subscriber-id option inserted by a relay
// Method 7: From docsis options
/// @todo: add other MAC acquisition methods here
// Ok, none of the methods were suitable. Return NULL.
return
(
HWAddrPtr
());
}
HWAddrPtr
Pkt
::
getMACFromIPv6
(
const
isc
::
asiolink
::
IOAddress
&
addr
)
{
if
(
!
addr
.
isV6LinkLocal
())
{
return
(
HWAddrPtr
());
}
std
::
vector
<
uint8_t
>
bin
=
addr
.
toBytes
();
// Double check that it's of appropriate size
if
((
bin
.
size
()
!=
isc
::
asiolink
::
V6ADDRESS_LEN
)
||
// Check that it's link-local (starts with fe80).
(
bin
[
0
]
!=
0xfe
)
||
(
bin
[
1
]
!=
0x80
)
||
// Check that u bit is set and g is clear. See Section 2.5.1 of RFC2373
// for details.
((
bin
[
8
]
&
3
)
!=
2
)
||
// And that the IID is of EUI-64 type.
(
bin
[
11
]
!=
0xff
)
||
(
bin
[
12
]
!=
0xfe
))
{
return
(
HWAddrPtr
());
}
// Remove 8 most significant bytes
bin
.
erase
(
bin
.
begin
(),
bin
.
begin
()
+
8
);
// Ok, we're down to EUI-64 only now: XX:XX:XX:ff:fe:XX:XX:XX
bin
.
erase
(
bin
.
begin
()
+
3
,
bin
.
begin
()
+
5
);
// MAC-48 to EUI-64 involves inverting u bit (see explanation in Section
// 2.5.1 of RFC2373). We need to revert that.
bin
[
0
]
=
bin
[
0
]
^
2
;
// Let's get the interface this packet was received on. We need it to get
// hardware type
Iface
*
iface
=
IfaceMgr
::
instance
().
getIface
(
iface_
);
uint16_t
hwtype
=
0
;
// not specified
if
(
iface
)
{
hwtype
=
iface
->
getHWType
();
}
return
(
HWAddrPtr
(
new
HWAddr
(
bin
,
hwtype
)));
}
};
};
src/lib/dhcp/pkt.h
View file @
d92e7686
...
...
@@ -62,7 +62,7 @@ public:
/// Extracted from IPv6 link-local address. Not 100% reliable, as the
/// client can use different IID other than EUI-64, e.g. Windows supports
/// RFC4941 and uses random values instead of EUI-64.
//
static const uint32_t HWADDR_SOURCE_IPV6_LINK_LOCAL = 0x0004;
static
const
uint32_t
HWADDR_SOURCE_IPV6_LINK_LOCAL
=
0x0004
;
/// Get it from RFC6939 option. (A relay agent can insert client link layer
/// address option). Note that a skilled attacker can fake that by sending
...
...
@@ -503,6 +503,43 @@ public:
protected:
/// @brief Attempts to obtain MAC address from source link-local
/// IPv6 address
///
/// This method is called from getMAC(HWADDR_SOURCE_IPV6_LINK_LOCAL)
/// and should not be called directly. It is not 100% reliable.
/// The source IPv6 address does not necessarily have to be link-local
/// (may be global or ULA) and even if it's link-local, it doesn't
/// necessarily be based on EUI-64. For example, Windows supports
/// RFC4941, which randomized IID part of the link-local address.
/// If this method fails, it will return NULL.
///
/// For direct message, it attempts to use remote_addr_ field. For relayed
/// message, it uses peer-addr of the first relay.
///
/// @note This is a pure virtual method and must be implemented in
/// the derived classes. The @c Pkt6 class have respective implementation.
/// This method is not applicable to DHCPv4.
///
/// @return hardware address (or NULL)
virtual
HWAddrPtr
getMACFromSrcLinkLocalAddr
()
=
0
;
/// @brief Attempts to convert IPv6 address into MAC.
///
/// Utility method that attempts to convert link-local IPv6 address to the
/// MAC address. That works only for link-local IPv6 addresses that are
/// based on EUI-64.
///
/// @note This method uses hardware type of the interface the packet was
/// received on. If you have multiple access technologies in your network
/// (e.g. client connected to WiFi that relayed the traffic to the server
/// over Ethernet), hardware type may be invalid.
///
/// @param addr IPv6 address to be converted
/// @return hardware address (or NULL)
HWAddrPtr
getMACFromIPv6
(
const
isc
::
asiolink
::
IOAddress
&
addr
);
/// Transaction-id (32 bits for v4, 24 bits for v6)
uint32_t
transid_
;
...
...
src/lib/dhcp/pkt4.h
View file @
d92e7686
...
...
@@ -390,6 +390,18 @@ protected:
uint8_t
DHCPTypeToBootpType
(
uint8_t
dhcpType
);
/// @brief No-op
///
/// This method returns hardware address generated from the IPv6 link-local
/// address. As there is no IPv4-equivalent, it always returns NULL.
/// We need this stub implementation here, to keep all the get hardware
/// address logic in the base class.
///
/// @return always NULL
virtual
HWAddrPtr
getMACFromSrcLinkLocalAddr
()
{
return
(
HWAddrPtr
());
}
/// local HW address (dst if receiving packet, src if sending packet)
HWAddrPtr
local_hwaddr_
;
...
...
src/lib/dhcp/pkt6.cc
View file @
d92e7686
...
...
@@ -542,5 +542,17 @@ void Pkt6::copyRelayInfo(const Pkt6Ptr& question) {
}
}
HWAddrPtr
Pkt6
::
getMACFromSrcLinkLocalAddr
()
{
if
(
relay_info_
.
empty
())
{
// This is a direct message, use source address
return
(
getMACFromIPv6
(
remote_addr_
));
}
// This is a relayed message, get the peer-addr from the first relay-forw
return
(
getMACFromIPv6
(
relay_info_
[
relay_info_
.
size
()
-
1
].
peeraddr_
));
}
}
// end of isc::dhcp namespace
}
// end of isc namespace
src/lib/dhcp/pkt6.h
View file @
d92e7686
...
...
@@ -268,17 +268,33 @@ public:
/// @param question client's packet
void
copyRelayInfo
(
const
Pkt6Ptr
&
question
);
///
r
elay information
///
@brief R
elay information
.
///
///
t
his is a public field. Otherwise we hit one of the two problems:
///
T
his is a public field. Otherwise we hit one of the two problems:
/// we return reference to an internal field (and that reference could
/// be potentially used past Pkt6 object lifetime causing badness) or
/// we return a copy (which is inefficient and also causes any updates
/// to be impossible). Therefore public field is considered the best
/// (or least bad) solution.
///
/// This vector is arranged in the order packet is encapsulated, i.e.
/// relay[0] was the outermost encapsulation (relay closest to the server),
/// relay[last] was the innermost encapsulation (relay closest to the
/// client).
std
::
vector
<
RelayInfo
>
relay_info_
;
protected:
/// @brief Attempts to generate MAC/Hardware address from IPv6 link-local
/// address.
///
/// This method uses source IPv6 address for direct messages and the
/// peeraddr or the first relay that saw that packet. It may fail if the
/// address is not link-local or does not use EUI-64 identifier.
///
/// @return Hardware address (or NULL)
virtual
HWAddrPtr
getMACFromSrcLinkLocalAddr
();
/// @brief Builds on wire packet for TCP transmission.
///
/// @todo This function is not implemented yet.
...
...
src/lib/dhcp/tests/pkt6_unittest.cc
View file @
d92e7686
...
...
@@ -21,6 +21,7 @@
#include
<dhcp/option6_ia.h>
#include
<dhcp/option_int.h>
#include
<dhcp/option_int_array.h>
#include
<dhcp/iface_mgr.h>
#include
<dhcp/pkt6.h>
#include
<dhcp/hwaddr.h>
#include
<dhcp/docsis3_option_defs.h>
...
...
@@ -86,8 +87,8 @@ public:
// callback has been actually called.
executed_
=
true
;
// Use default implementation of the unpack algorithm to parse options.
return
(
LibDHCP
::
unpackOptions6
(
buf
,
option_space
,
options
,
relay_msg_offset
,
relay_msg_len
));
return
(
LibDHCP
::
unpackOptions6
(
buf
,
option_space
,
options
,
relay_msg_offset
,
relay_msg_len
));
}
/// A flag which indicates if callback function has been called.
...
...
@@ -99,7 +100,8 @@ public:
Pkt6Test
()
{
}
/// @brief generates an option with given code (and length) and random content
/// @brief generates an option with given code (and length) and
/// random content
///
/// @param code option code
/// @param len data length (data will be randomized)
...
...
@@ -252,13 +254,13 @@ Pkt6* capture2() {
// string exported from Wireshark
string
hex_string
=
"0c01200108880db800010000000000000000fe80000000000000020021fffe5c
18a900
"
"09007d0c0000000000000000000000000000000000fe80000000000000
020021fffe5c
"
"18a9001200154953414d3134342065746820312f312f30352f30
310025000400000de9
"
"00090036016b4fe20001000e0001000118b03341000021
5c18a90003000c00000001ff
"
"ffffffffffffff00080002000000060006001700
f200f30012001c4953414d3134347c
"
"3239397c697076367c6e743a76703a313a
313130002500120000197f0001000118b033
"
"410000215c18a9"
;
"0c01200108880db800010000000000000000fe80000000000000020021fffe5c"
"
18a900
09007d0c0000000000000000000000000000000000fe80000000000000"
"
020021fffe5c
18a9001200154953414d3134342065746820312f312f30352f30"
"
310025000400000de9
00090036016b4fe20001000e0001000118b03341000021"
"
5c18a90003000c00000001ff
ffffffffffffff00080002000000060006001700"
"
f200f30012001c4953414d3134347c
3239397c697076367c6e743a76703a313a"
"
313130002500120000197f0001000118b033
410000215c18a9"
;
std
::
vector
<
uint8_t
>
bin
;
...
...
@@ -319,7 +321,8 @@ TEST_F(Pkt6Test, packUnpack) {
// Checks if the code is able to handle malformed packet
TEST_F
(
Pkt6Test
,
unpackMalformed
)
{
// Get a packet. We're really interested in its on-wire representation only.
// Get a packet. We're really interested in its on-wire
// representation only.
scoped_ptr
<
Pkt6
>
donor
(
capture1
());
// That's our original content. It should be sane.
...
...
@@ -586,8 +589,9 @@ TEST_F(Pkt6Test, relayUnpack) {
uint32_t
vendor_id
=
custom
->
readInteger
<
uint32_t
>
(
0
);
EXPECT_EQ
(
6527
,
vendor_id
);
// 6527 = Panthera Networks
uint8_t
expected_remote_id
[]
=
{
0x00
,
0x01
,
0x00
,
0x01
,
0x18
,
0xb0
,
0x33
,
0x41
,
0x00
,
0x00
,
0x21
,
0x5c
,
0x18
,
0xa9
};
uint8_t
expected_remote_id
[]
=
{
0x00
,
0x01
,
0x00
,
0x01
,
0x18
,
0xb0
,
0x33
,
0x41
,
0x00
,
0x00
,
0x21
,
0x5c
,
0x18
,
0xa9
};
OptionBuffer
remote_id
=
custom
->
readBinary
(
1
);
ASSERT_EQ
(
sizeof
(
expected_remote_id
),
remote_id
.
size
());
ASSERT_EQ
(
0
,
memcmp
(
expected_remote_id
,
&
remote_id
[
0
],
remote_id
.
size
()));
...
...
@@ -623,8 +627,9 @@ TEST_F(Pkt6Test, relayUnpack) {
ASSERT_TRUE
(
opt
=
msg
->
getOption
(
D6O_CLIENTID
));
EXPECT_EQ
(
18
,
opt
->
len
());
// 14 bytes of data + 4 bytes of header
uint8_t
expected_client_id
[]
=
{
0x00
,
0x01
,
0x00
,
0x01
,
0x18
,
0xb0
,
0x33
,
0x41
,
0x00
,
0x00
,
0x21
,
0x5c
,
0x18
,
0xa9
};
uint8_t
expected_client_id
[]
=
{
0x00
,
0x01
,
0x00
,
0x01
,
0x18
,
0xb0
,
0x33
,
0x41
,
0x00
,
0x00
,
0x21
,
0x5c
,
0x18
,
0xa9
};
data
=
opt
->
getData
();
ASSERT_EQ
(
data
.
size
(),
sizeof
(
expected_client_id
));
ASSERT_EQ
(
0
,
memcmp
(
&
data
[
0
],
expected_client_id
,
data
.
size
()));
...
...
@@ -689,7 +694,8 @@ TEST_F(Pkt6Test, relayPack) {
EXPECT_NO_THROW
(
parent
->
pack
());
EXPECT_EQ
(
Pkt6
::
DHCPV6_PKT_HDR_LEN
+
3
*
Option
::
OPTION6_HDR_LEN
// ADVERTISE
EXPECT_EQ
(
Pkt6
::
DHCPV6_PKT_HDR_LEN
+
3
*
Option
::
OPTION6_HDR_LEN
// ADVERTISE
+
Pkt6
::
DHCPV6_RELAY_HDR_LEN
// Relay header
+
Option
::
OPTION6_HDR_LEN
// Relay-msg
+
optRelay1
->
len
(),
...
...
@@ -727,7 +733,8 @@ TEST_F(Pkt6Test, relayPack) {
EXPECT_EQ
(
opt
->
len
(),
optRelay1
->
len
());
OptionBuffer
data
=
opt
->
getData
();
ASSERT_EQ
(
data
.
size
(),
sizeof
(
relay_opt_data
));
EXPECT_EQ
(
0
,
memcmp
(
relay_opt_data
,
relay_opt_data
,
sizeof
(
relay_opt_data
)));
EXPECT_EQ
(
0
,
memcmp
(
relay_opt_data
,
relay_opt_data
,
sizeof
(
relay_opt_data
)));
}
...
...
@@ -756,7 +763,8 @@ TEST_F(Pkt6Test, getAnyRelayOption) {
OptionPtr
relay2_opt1
(
new
Option
(
Option
::
V6
,
100
));
OptionPtr
relay2_opt2
(
new
Option
(
Option
::
V6
,
101
));
OptionPtr
relay2_opt3
(
new
Option
(
Option
::
V6
,
102
));
OptionPtr
relay2_opt4
(
new
Option
(
Option
::
V6
,
200
));
// the same code as relay1_opt3
OptionPtr
relay2_opt4
(
new
Option
(
Option
::
V6
,
200
));
// the same code as relay1_opt3
relay2
.
options_
.
insert
(
make_pair
(
100
,
relay2_opt1
));
relay2
.
options_
.
insert
(
make_pair
(
101
,
relay2_opt2
));
relay2
.
options_
.
insert
(
make_pair
(
102
,
relay2_opt3
));
...
...
@@ -775,7 +783,8 @@ TEST_F(Pkt6Test, getAnyRelayOption) {
// First check that the getAnyRelayOption does not confuse client options
// and relay options
// 300 is a client option, present in the message itself.
OptionPtr
opt
=
msg
->
getAnyRelayOption
(
300
,
Pkt6
::
RELAY_SEARCH_FROM_CLIENT
);
OptionPtr
opt
=
msg
->
getAnyRelayOption
(
300
,
Pkt6
::
RELAY_SEARCH_FROM_CLIENT
);
EXPECT_FALSE
(
opt
);
opt
=
msg
->
getAnyRelayOption
(
300
,
Pkt6
::
RELAY_SEARCH_FROM_SERVER
);
EXPECT_FALSE
(
opt
);
...
...
@@ -877,6 +886,19 @@ TEST_F(Pkt6Test, getMAC) {
EXPECT_FALSE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_ANY
));
EXPECT_FALSE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_RAW
));
// We haven't specified source IPv6 address, so this method should
// fail, too
EXPECT_FALSE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_IPV6_LINK_LOCAL
));
// Let's check if setting IPv6 address improves the situation.
IOAddress
linklocal_eui64
(
"fe80::204:06ff:fe08:0a0c"
);
pkt
.
setRemoteAddr
(
linklocal_eui64
);
EXPECT_TRUE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_ANY
));
EXPECT_TRUE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_IPV6_LINK_LOCAL
));
EXPECT_TRUE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_IPV6_LINK_LOCAL
|
Pkt
::
HWADDR_SOURCE_RAW
));
pkt
.
setRemoteAddr
(
IOAddress
(
"::"
));
// Let's invent a MAC
const
uint8_t
hw
[]
=
{
2
,
4
,
6
,
8
,
10
,
12
};
// MAC
const
uint8_t
hw_type
=
123
;
// hardware type
...
...
@@ -888,10 +910,144 @@ TEST_F(Pkt6Test, getMAC) {
// Now we should be able to get something
ASSERT_TRUE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_ANY
));
ASSERT_TRUE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_RAW
));
EXPECT_TRUE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_IPV6_LINK_LOCAL
|
Pkt
::
HWADDR_SOURCE_RAW
));
// Check that the returned MAC is indeed the expected one
ASSERT_TRUE
(
*
dummy_hwaddr
==
*
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_ANY
));
ASSERT_TRUE
(
*
dummy_hwaddr
==
*
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_RAW
));
}
// Test checks whether getMACFromIPv6LinkLocal() returns the hardware (MAC)
// address properly (for direct message).
TEST_F
(
Pkt6Test
,
getMACFromIPv6LinkLocal_direct
)
{
Pkt6
pkt
(
DHCPV6_ADVERTISE
,
1234
);
// Let's get the first interface
Iface
*
iface
=
IfaceMgr
::
instance
().
getIface
(
1
);
ASSERT_TRUE
(
iface
);
// and set source interface data properly. getMACFromIPv6LinkLocal attempts
// to use source interface to obtain hardware type
pkt
.
setIface
(
iface
->
getName
());
pkt
.
setIndex
(
iface
->
getIndex
());
// Note that u and g bits (the least significant ones of the most
// significant byte) have special meaning and must not be set in MAC.
// u bit is always set in EUI-64. g is always cleared.
IOAddress
global
(
"2001:db8::204:06ff:fe08:0a:0c"
);
IOAddress
linklocal_eui64
(
"fe80::f204:06ff:fe08:0a0c"
);
IOAddress
linklocal_noneui64
(
"fe80::f204:0608:0a0c:0e10"
);
// If received from a global address, this method should fail
pkt
.
setRemoteAddr
(
global
);
EXPECT_FALSE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_IPV6_LINK_LOCAL
));
// If received from link-local that is EUI-64 based, it should succeed
pkt
.
setRemoteAddr
(
linklocal_eui64
);
HWAddrPtr
found
=
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_IPV6_LINK_LOCAL
);
ASSERT_TRUE
(
found
);
stringstream
tmp
;
tmp
<<
"hwtype="
<<
(
int
)
iface
->
getHWType
()
<<
" f0:04:06:08:0a:0c"
;
EXPECT_EQ
(
tmp
.
str
(),
found
->
toText
(
true
));
}
// Test checks whether getMACFromIPv6LinkLocal() returns the hardware (MAC)
// address properly (for relayed message).
TEST_F
(
Pkt6Test
,
getMACFromIPv6LinkLocal_singleRelay
)
{
// Let's create a Solicit first...
Pkt6
pkt
(
DHCPV6_SOLICIT
,
1234
);
// ... and pretend it was relayed by a single relay.
Pkt6
::
RelayInfo
info
;
pkt
.
addRelayInfo
(
info
);
ASSERT_EQ
(
1
,
pkt
.
relay_info_
.
size
());
// Let's get the first interface
Iface
*
iface
=
IfaceMgr
::
instance
().
getIface
(
1
);
ASSERT_TRUE
(
iface
);
// and set source interface data properly. getMACFromIPv6LinkLocal attempts
// to use source interface to obtain hardware type
pkt
.
setIface
(
iface
->
getName
());
pkt
.
setIndex
(
iface
->
getIndex
());
IOAddress
global
(
"2001:db8::204:06ff:fe08:0a:0c"
);
// global address
IOAddress
linklocal_noneui64
(
"fe80::f204:0608:0a0c:0e10"
);
// no fffe
IOAddress
linklocal_eui64
(
"fe80::f204:06ff:fe08:0a0c"
);
// valid EUI-64
// If received from a global address, this method should fail
pkt
.
relay_info_
[
0
].
peeraddr_
=
global
;
EXPECT_FALSE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_IPV6_LINK_LOCAL
));
// If received from a link-local that does not use EUI-64, it should fail
pkt
.
relay_info_
[
0
].
peeraddr_
=
linklocal_noneui64
;
EXPECT_FALSE
(
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_IPV6_LINK_LOCAL
));
// If received from link-local that is EUI-64 based, it should succeed
pkt
.
relay_info_
[
0
].
peeraddr_
=
linklocal_eui64
;
HWAddrPtr
found
=
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_IPV6_LINK_LOCAL
);
ASSERT_TRUE
(
found
);
stringstream
tmp
;
tmp
<<
"hwtype="
<<
(
int
)
iface
->
getHWType
()
<<
" f0:04:06:08:0a:0c"
;
EXPECT_EQ
(
tmp
.
str
(),
found
->
toText
(
true
));
}
// Test checks whether getMACFromIPv6LinkLocal() returns the hardware (MAC)
// address properly (for a message relayed multiple times).
TEST_F
(
Pkt6Test
,
getMACFromIPv6LinkLocal_multiRelay
)
{
// Let's create a Solicit first...
Pkt6
pkt
(
DHCPV6_SOLICIT
,
1234
);
// ... and pretend it was relayed via 3 relays. Keep in mind that
// the relays are stored in relay_info_ in the encapsulation order
// rather than in traverse order. The following simulates:
// client --- relay1 --- relay2 --- relay3 --- server
IOAddress
linklocal1
(
"fe80::200:ff:fe00:1"
);
// valid EUI-64
IOAddress
linklocal2
(
"fe80::200:ff:fe00:2"
);
// valid EUI-64
IOAddress
linklocal3
(
"fe80::200:ff:fe00:3"
);
// valid EUI-64
// Let's add info about relay3. This was the last relay, so it added the
// outermost encapsulation layer, so it was parsed first during reception.
// Its peer-addr field contains an address of relay2, so it's useless for
// this method.
Pkt6
::
RelayInfo
info
;
info
.
peeraddr_
=
linklocal3
;
pkt
.
addRelayInfo
(
info
);
// Now add info about relay2. Its peer-addr contains an address of the
// previous relay (relay1). Still useless for us.
info
.
peeraddr_
=
linklocal2
;
pkt
.
addRelayInfo
(
info
);
// Finally add the first relay. This is the relay that received the packet
// from the client directly, so its peer-addr field contains an address of
// the client. The method should get that address and build MAC from it.
info
.
peeraddr_
=
linklocal1
;
pkt
.
addRelayInfo
(
info
);
ASSERT_EQ
(
3
,
pkt
.
relay_info_
.
size
());
// Let's get the first interface
Iface
*
iface
=
IfaceMgr
::
instance
().
getIface
(
1
);
ASSERT_TRUE
(
iface
);
// and set source interface data properly. getMACFromIPv6LinkLocal attempts
// to use source interface to obtain hardware type
pkt
.
setIface
(
iface
->
getName
());
pkt
.
setIndex
(
iface
->
getIndex
());
// The method should return MAC based on the first relay that was closest
HWAddrPtr
found
=
pkt
.
getMAC
(
Pkt
::
HWADDR_SOURCE_IPV6_LINK_LOCAL
);
ASSERT_TRUE
(
found
);
// Let's check the info now.
stringstream
tmp
;
tmp
<<
"hwtype="
<<
iface
->
getHWType
()
<<
" 00:00:00:00:00:01"
;
EXPECT_EQ
(
tmp
.
str
(),
found
->
toText
(
true
));
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment