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
1eb11784
Commit
1eb11784
authored
Apr 04, 2013
by
Tomek Mrugalski
🛰
Browse files
[master] Merge branch 'trac2827' (relay support in dhcp/Pkt6)
Conflicts: ChangeLog
parents
d538f9ed
29c3f7f4
Changes
8
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
1eb11784
599. [func] tomek
libdhcp++: Pkt6 class is now able to parse and build relayed DHCPv6
messages.
(Trac #2827, git 29c3f7f4e82d7e85f0f5fb692345fd55092796b4)
bind10-1.0.0beta1 released on April 4, 2013
598. [func]* jinmei
...
...
src/lib/dhcp/libdhcp++.cc
View file @
1eb11784
// Copyright (C) 2011-201
2
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-201
3
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -128,7 +128,9 @@ LibDHCP::optionFactory(Option::Universe u,
size_t
LibDHCP
::
unpackOptions6
(
const
OptionBuffer
&
buf
,
isc
::
dhcp
::
Option
::
OptionCollection
&
options
)
{
isc
::
dhcp
::
Option
::
OptionCollection
&
options
,
size_t
*
relay_msg_offset
/* = 0 */
,
size_t
*
relay_msg_len
/* = 0 */
)
{
size_t
offset
=
0
;
size_t
length
=
buf
.
size
();
...
...
@@ -143,6 +145,7 @@ size_t LibDHCP::unpackOptions6(const OptionBuffer& buf,
while
(
offset
+
4
<=
length
)
{
uint16_t
opt_type
=
isc
::
util
::
readUint16
(
&
buf
[
offset
]);
offset
+=
2
;
uint16_t
opt_len
=
isc
::
util
::
readUint16
(
&
buf
[
offset
]);
offset
+=
2
;
...
...
@@ -151,6 +154,16 @@ size_t LibDHCP::unpackOptions6(const OptionBuffer& buf,
return
(
offset
);
}
if
(
opt_type
==
D6O_RELAY_MSG
&&
relay_msg_offset
&&
relay_msg_len
)
{
// remember offset of the beginning of the relay-msg option
*
relay_msg_offset
=
offset
;
*
relay_msg_len
=
opt_len
;
// do not create that relay-msg option
offset
+=
opt_len
;
continue
;
}
// Get all definitions with the particular option code. Note that option
// code is non-unique within this container however at this point we
// expect to get one option definition with the particular code. If more
...
...
@@ -193,7 +206,7 @@ size_t LibDHCP::unpackOptions6(const OptionBuffer& buf,
}
size_t
LibDHCP
::
unpackOptions4
(
const
OptionBuffer
&
buf
,
isc
::
dhcp
::
Option
::
OptionCollection
&
options
)
{
isc
::
dhcp
::
Option
::
OptionCollection
&
options
)
{
size_t
offset
=
0
;
// Get the list of stdandard option definitions.
...
...
src/lib/dhcp/libdhcp++.h
View file @
1eb11784
// Copyright (C) 2011-201
2
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-201
3
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -115,14 +115,27 @@ public:
/// @brief Parses provided buffer as DHCPv6 options and creates Option objects.
///
/// Parses provided buffer and stores created Option objects
/// in options container.
/// Parses provided buffer and stores created Option objects in options
/// container. The last two parameters are optional and are used in
/// relay parsing. If they are specified, relay-msg option is not created,
/// but rather those two parameters are specified to point out where
/// the relay-msg option resides and what is its length. This is perfromance
/// optimization that avoids unnecessary copying of potentially large
/// relay-msg option. It is not used for anything, except in the next
/// iteration its content will be treated as buffer to be parsed.
///
/// @param buf Buffer to be parsed.
/// @param options Reference to option container. Options will be
/// put here.
/// @param relay_msg_offset reference to a size_t structure. If specified,
/// offset to beginning of relay_msg option will be stored in it.
/// @param relay_msg_len reference to a size_t structure. If specified,
/// length of the relay_msg option will be stored in it.
/// @return offset to the first byte after last parsed option
static
size_t
unpackOptions6
(
const
OptionBuffer
&
buf
,
isc
::
dhcp
::
Option
::
OptionCollection
&
options
);
isc
::
dhcp
::
Option
::
OptionCollection
&
options
,
size_t
*
relay_msg_offset
=
0
,
size_t
*
relay_msg_len
=
0
);
/// Registers factory method that produces options of specific option types.
///
...
...
src/lib/dhcp/option_custom.cc
View file @
1eb11784
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012
-2013
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -230,7 +230,7 @@ OptionCustom::createBuffers(const OptionBuffer& data_buf) {
// 1 byte larger than the size of the string
// representation of this FQDN.
data_size
=
fqdn
.
size
()
+
1
;
}
else
{
}
else
if
(
(
*
field
==
OPT_BINARY_TYPE
)
||
(
*
field
==
OPT_STRING_TYPE
)
)
{
// In other case we are dealing with string or binary value
// which size can't be determined. Thus we consume the
// remaining part of the buffer for it. Note that variable
...
...
@@ -238,14 +238,11 @@ OptionCustom::createBuffers(const OptionBuffer& data_buf) {
// that the validate() function in OptionDefinition object
// should have checked wheter it is a case for this option.
data_size
=
std
::
distance
(
data
,
data_buf
.
end
());
}
if
(
data_size
==
0
)
{
}
else
{
// If we reached the end of buffer we assume that this option is
// truncated because there is no remaining data to initialize
// an option field.
if
(
data_size
==
0
)
{
isc_throw
(
OutOfRange
,
"option buffer truncated"
);
}
isc_throw
(
OutOfRange
,
"option buffer truncated"
);
}
}
else
{
// Our data field requires that there is a certain chunk of
...
...
src/lib/dhcp/pkt6.cc
View file @
1eb11784
// Copyright (C) 2011-201
2
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-201
3
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -21,10 +21,17 @@
#include
<sstream>
using
namespace
std
;
using
namespace
isc
::
asiolink
;
namespace
isc
{
namespace
dhcp
{
Pkt6
::
RelayInfo
::
RelayInfo
()
:
msg_type_
(
0
),
hop_count_
(
0
),
linkaddr_
(
"::"
),
peeraddr_
(
"::"
),
relay_msg_len_
(
0
)
{
// interface_id_, subscriber_id_, remote_id_ initialized to NULL
// echo_options_ initialized to empty collection
}
Pkt6
::
Pkt6
(
const
uint8_t
*
buf
,
uint32_t
buf_len
,
DHCPv6Proto
proto
/* = UDP */
)
:
proto_
(
proto
),
msg_type_
(
0
),
...
...
@@ -54,9 +61,61 @@ Pkt6::Pkt6(uint8_t msg_type, uint32_t transid, DHCPv6Proto proto /*= UDP*/) :
}
uint16_t
Pkt6
::
len
()
{
if
(
relay_info_
.
empty
())
{
return
(
directLen
());
}
else
{
// Unfortunately we need to re-calculate relay size every time, because
// we need to make sure that once a new option is added, its extra size
// is reflected in Pkt6::len().
calculateRelaySizes
();
return
(
relay_info_
[
0
].
relay_msg_len_
+
getRelayOverhead
(
relay_info_
[
0
]));
}
}
OptionPtr
Pkt6
::
getRelayOption
(
uint16_t
opt_type
,
uint8_t
relay_level
)
{
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."
);
}
for
(
Option
::
OptionCollection
::
iterator
it
=
relay_info_
[
relay_level
].
options_
.
begin
();
it
!=
relay_info_
[
relay_level
].
options_
.
end
();
++
it
)
{
if
((
*
it
).
second
->
getType
()
==
opt_type
)
{
return
(
it
->
second
);
}
}
return
(
OptionPtr
());
}
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
for
(
Option
::
OptionCollection
::
const_iterator
opt
=
relay
.
options_
.
begin
();
opt
!=
relay
.
options_
.
end
();
++
opt
)
{
len
+=
(
opt
->
second
)
->
len
();
}
return
(
len
);
}
uint16_t
Pkt6
::
calculateRelaySizes
()
{
uint16_t
len
=
directLen
();
// start with length of all options
for
(
int
relay_index
=
relay_info_
.
size
();
relay_index
>
0
;
--
relay_index
)
{
relay_info_
[
relay_index
-
1
].
relay_msg_len_
=
len
;
len
+=
getRelayOverhead
(
relay_info_
[
relay_index
-
1
]);
}
return
(
len
);
}
uint16_t
Pkt6
::
directLen
()
const
{
uint16_t
length
=
DHCPV6_PKT_HDR_LEN
;
// DHCPv6 header
for
(
Option
::
OptionCollection
::
iterator
it
=
options_
.
begin
();
for
(
Option
::
OptionCollection
::
const_
iterator
it
=
options_
.
begin
();
it
!=
options_
.
end
();
++
it
)
{
length
+=
(
*
it
).
second
->
len
();
...
...
@@ -82,6 +141,50 @@ Pkt6::pack() {
bool
Pkt6
::
packUDP
()
{
try
{
// is this a relayed packet?
if
(
!
relay_info_
.
empty
())
{
// calculate size needed for each relay (if there is only one relay,
// then it will be equal to "regular" length + relay-forw header +
// size of relay-msg option header + possibly size of interface-id
// option (if present). If there is more than one relay, the whole
// process is called iteratively for each relay.
calculateRelaySizes
();
// Now for each relay, we need to...
for
(
vector
<
RelayInfo
>::
iterator
relay
=
relay_info_
.
begin
();
relay
!=
relay_info_
.
end
();
++
relay
)
{
// build relay-forw/relay-repl header (see RFC3315, section 7)
bufferOut_
.
writeUint8
(
relay
->
msg_type_
);
bufferOut_
.
writeUint8
(
relay
->
hop_count_
);
bufferOut_
.
writeData
(
&
(
relay
->
linkaddr_
.
toBytes
()[
0
]),
isc
::
asiolink
::
V6ADDRESS_LEN
);
bufferOut_
.
writeData
(
&
relay
->
peeraddr_
.
toBytes
()[
0
],
isc
::
asiolink
::
V6ADDRESS_LEN
);
// store every option in this relay scope. Usually that will be
// only interface-id, but occasionally other options may be
// present here as well (vendor-opts for Cable modems,
// subscriber-id, remote-id, options echoed back from Echo
// Request Option, etc.)
for
(
Option
::
OptionCollection
::
const_iterator
opt
=
relay
->
options_
.
begin
();
opt
!=
relay
->
options_
.
end
();
++
opt
)
{
(
opt
->
second
)
->
pack
(
bufferOut_
);
}
// and include header relay-msg option. Its payload will be
// generated in the next iteration (if there are more relays)
// or outside the loop (if there are no more relays and the
// payload is a direct message)
bufferOut_
.
writeUint16
(
D6O_RELAY_MSG
);
bufferOut_
.
writeUint16
(
relay
->
relay_msg_len_
);
}
}
// DHCPv6 header: message-type (1 octect) + transaction id (3 octets)
bufferOut_
.
writeUint8
(
msg_type_
);
// store 3-octet transaction-id
...
...
@@ -127,12 +230,43 @@ Pkt6::unpackUDP() {
return
(
false
);
}
msg_type_
=
data_
[
0
];
transid_
=
(
(
data_
[
1
])
<<
16
)
+
((
data_
[
2
])
<<
8
)
+
(
data_
[
3
]);
switch
(
msg_type_
)
{
case
DHCPV6_SOLICIT
:
case
DHCPV6_ADVERTISE
:
case
DHCPV6_REQUEST
:
case
DHCPV6_CONFIRM
:
case
DHCPV6_RENEW
:
case
DHCPV6_REBIND
:
case
DHCPV6_REPLY
:
case
DHCPV6_DECLINE
:
case
DHCPV6_RECONFIGURE
:
case
DHCPV6_INFORMATION_REQUEST
:
default:
// assume that uknown messages are not using relay format
{
return
(
unpackMsg
(
data_
.
begin
(),
data_
.
end
()));
}
case
DHCPV6_RELAY_FORW
:
case
DHCPV6_RELAY_REPL
:
return
(
unpackRelayMsg
());
}
}
bool
Pkt6
::
unpackMsg
(
OptionBuffer
::
const_iterator
begin
,
OptionBuffer
::
const_iterator
end
)
{
if
(
std
::
distance
(
begin
,
end
)
<
4
)
{
// truncated message (less than 4 bytes)
return
(
false
);
}
msg_type_
=
*
begin
++
;
transid_
=
(
(
*
begin
++
)
<<
16
)
+
((
*
begin
++
)
<<
8
)
+
(
*
begin
++
);
transid_
=
transid_
&
0xffffff
;
try
{
OptionBuffer
opt_buffer
(
data_
.
begin
()
+
4
,
data_
.
end
()
);
OptionBuffer
opt_buffer
(
begin
,
end
);
LibDHCP
::
unpackOptions6
(
opt_buffer
,
options_
);
}
catch
(
const
Exception
&
e
)
{
...
...
@@ -142,6 +276,97 @@ Pkt6::unpackUDP() {
return
(
true
);
}
bool
Pkt6
::
unpackRelayMsg
()
{
// we use offset + bufsize, because we want to avoid creating unnecessary
// copies. There may be up to 32 relays. While using InputBuffer would
// be probably a bit cleaner, copying data up to 32 times is unacceptable
// price here. Hence a single buffer with offets and lengths.
size_t
bufsize
=
data_
.
size
();
size_t
offset
=
0
;
while
(
bufsize
>=
DHCPV6_RELAY_HDR_LEN
)
{
RelayInfo
relay
;
size_t
relay_msg_offset
=
0
;
size_t
relay_msg_len
=
0
;
// parse fixed header first (first 34 bytes)
relay
.
msg_type_
=
data_
[
offset
++
];
relay
.
hop_count_
=
data_
[
offset
++
];
relay
.
linkaddr_
=
IOAddress
::
fromBytes
(
AF_INET6
,
&
data_
[
offset
]);
offset
+=
isc
::
asiolink
::
V6ADDRESS_LEN
;
relay
.
peeraddr_
=
IOAddress
::
fromBytes
(
AF_INET6
,
&
data_
[
offset
]);
offset
+=
isc
::
asiolink
::
V6ADDRESS_LEN
;
bufsize
-=
DHCPV6_RELAY_HDR_LEN
;
// 34 bytes (1+1+16+16)
try
{
// parse the rest as options
OptionBuffer
opt_buffer
(
&
data_
[
offset
],
&
data_
[
offset
+
bufsize
]);
LibDHCP
::
unpackOptions6
(
opt_buffer
,
relay
.
options_
,
&
relay_msg_offset
,
&
relay_msg_len
);
/// @todo: check that each option appears at most once
//relay.interface_id_ = options->getOption(D6O_INTERFACE_ID);
//relay.subscriber_id_ = options->getOption(D6O_SUBSCRIBER_ID);
//relay.remote_id_ = options->getOption(D6O_REMOTE_ID);
if
(
relay_msg_offset
==
0
||
relay_msg_len
==
0
)
{
isc_throw
(
BadValue
,
"Mandatory relay-msg option missing"
);
}
// store relay information parsed so far
addRelayInfo
(
relay
);
/// @todo: implement ERO here
if
(
relay_msg_len
>=
bufsize
)
{
// length of the relay_msg option extends beyond end of the message
isc_throw
(
Unexpected
,
"Relay-msg option is truncated."
);
return
false
;
}
uint8_t
inner_type
=
data_
[
offset
+
relay_msg_offset
];
offset
+=
relay_msg_offset
;
// offset is relative
bufsize
=
relay_msg_len
;
// length is absolute
if
(
(
inner_type
!=
DHCPV6_RELAY_FORW
)
&&
(
inner_type
!=
DHCPV6_RELAY_REPL
))
{
// Ok, the inner message is not encapsulated, let's decode it
// directly
return
(
unpackMsg
(
data_
.
begin
()
+
offset
,
data_
.
begin
()
+
offset
+
relay_msg_len
));
}
// Oh well, there's inner relay-forw or relay-repl inside. Let's
// unpack it as well. The next loop iteration will take care
// of that.
}
catch
(
const
Exception
&
e
)
{
/// @todo: throw exception here once we turn this function to void.
return
(
false
);
}
}
if
(
(
offset
==
data_
.
size
())
&&
(
bufsize
==
0
)
)
{
// message has been parsed completely
return
(
true
);
}
/// @todo: log here that there are additional unparsed bytes
return
(
true
);
}
void
Pkt6
::
addRelayInfo
(
const
RelayInfo
&
relay
)
{
if
(
relay_info_
.
size
()
>
32
)
{
isc_throw
(
BadValue
,
"Massage cannot be encapsulated more than 32 times"
);
}
/// @todo: Implement type checks here (e.g. we could receive relay-forw in relay-repl)
relay_info_
.
push_back
(
relay
);
}
bool
Pkt6
::
unpackTCP
()
{
isc_throw
(
Unexpected
,
"DHCPv6 over TCP (bulk leasequery and failover) "
...
...
src/lib/dhcp/pkt6.h
View file @
1eb11784
// Copyright (C) 2011-201
2
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-201
3
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -32,15 +32,40 @@ namespace dhcp {
class
Pkt6
{
public:
/// specifes DHCPv6 packet header length
/// specif
i
es
non-relayed
DHCPv6 packet header length
(over UDP)
const
static
size_t
DHCPV6_PKT_HDR_LEN
=
4
;
/// specifies relay DHCPv6 packet header length (over UDP)
const
static
size_t
DHCPV6_RELAY_HDR_LEN
=
34
;
/// DHCPv6 transport protocol
enum
DHCPv6Proto
{
UDP
=
0
,
// most packets are UDP
TCP
=
1
// there are TCP DHCPv6 packets (bulk leasequery, failover)
};
/// @brief structure that describes a single relay information
///
/// Client sends messages. Each relay along its way will encapsulate the message.
/// This structure represents all information added by a single relay.
struct
RelayInfo
{
/// @brief default constructor
RelayInfo
();
uint8_t
msg_type_
;
///< message type (RELAY-FORW oro RELAY-REPL)
uint8_t
hop_count_
;
///< number of traversed relays (up to 32)
isc
::
asiolink
::
IOAddress
linkaddr_
;
///< fixed field in relay-forw/relay-reply
isc
::
asiolink
::
IOAddress
peeraddr_
;
///< fixed field in relay-forw/relay-reply
/// @brief length of the relay_msg_len
/// Used when calculating length during pack/unpack
uint16_t
relay_msg_len_
;
/// options received from a specified relay, except relay-msg option
isc
::
dhcp
::
Option
::
OptionCollection
options_
;
};
/// Constructor, used in replying to a message
///
/// @param msg_type type of message (SOLICIT=1, ADVERTISE=2, ...)
...
...
@@ -89,7 +114,6 @@ public:
/// @return reference to output buffer
const
isc
::
util
::
OutputBuffer
&
getBuffer
()
const
{
return
(
bufferOut_
);
};
/// @brief Returns reference to input buffer.
///
/// @return reference to input buffer
...
...
@@ -160,6 +184,23 @@ public:
/// @return pointer to found option (or NULL)
OptionPtr
getOption
(
uint16_t
type
);
/// @brief returns option inserted by relay
///
/// Returns an option from specified relay scope (inserted by a given relay
/// if this is received packet or to be decapsulated by a given relay if
/// this is a transmitted packet). nesting_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 nesting level has invalid value.
///
/// @param option_code code of the requested option
/// @param nesting_level see description above
///
/// @return pointer to the option (or NULL if there is no such option)
OptionPtr
getRelayOption
(
uint16_t
option_code
,
uint8_t
nesting_level
);
/// @brief Returns all instances of specified type.
///
/// Returns all instances of options of the specified type. DHCPv6 protocol
...
...
@@ -246,7 +287,7 @@ public:
/// @brief Returns packet timestamp.
///
/// Returns packet timestamp value updated when
/// packet is received or sen
d
.
/// packet is received or sen
t
.
///
/// @return packet timestamp.
const
boost
::
posix_time
::
ptime
&
getTimestamp
()
const
{
return
timestamp_
;
}
...
...
@@ -259,8 +300,18 @@ public:
/// @return interface name
void
setIface
(
const
std
::
string
&
iface
)
{
iface_
=
iface
;
};
/// @brief add information about one traversed relay
///
/// This adds information about one traversed relay, i.e.
/// one relay-forw or relay-repl level of encapsulation.
///
/// @param relay structure with necessary relay information
void
addRelayInfo
(
const
RelayInfo
&
relay
);
/// collection of options present in this message
///
/// @todo: Text mentions protected, but this is really public
///
/// @warning This protected member is accessed by derived
/// classes directly. One of such derived classes is
/// @ref perfdhcp::PerfPkt6. The impact on derived clasess'
...
...
@@ -305,6 +356,15 @@ public:
/// be freed by the caller.
const
char
*
getName
()
const
;
/// relay information
///
/// this 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.
std
::
vector
<
RelayInfo
>
relay_info_
;
protected:
/// Builds on wire packet for TCP transmission.
///
...
...
@@ -340,6 +400,44 @@ protected:
/// @return true, if build was successful
bool
unpackUDP
();
/// @brief unpacks direct (non-relayed) message
///
/// This method unpacks specified buffer range as a direct
/// (e.g. solicit or request) message. This method is called from
/// unpackUDP() when received message is detected to be direct.
///
/// @param begin start of the buffer
/// @param end end of the buffer
/// @return true if parsing was successful and there are no leftover bytes
bool
unpackMsg
(
OptionBuffer
::
const_iterator
begin
,
OptionBuffer
::
const_iterator
end
);
/// @brief unpacks relayed message (RELAY-FORW or RELAY-REPL)
///
/// This method is called from unpackUDP() when received message
/// is detected to be relay-message. It goes iteratively over
/// all relays (if there are multiple encapsulation levels).
///
/// @return true if parsing was successful
bool
unpackRelayMsg
();
/// @brief calculates overhead introduced in specified relay
///
/// It is used when calculating message size and packing message
/// @param relay RelayInfo structure that holds information about relay
/// @return number of bytes needed to store relay information
uint16_t
getRelayOverhead
(
const
RelayInfo
&
relay
)
const
;
/// @brief calculates overhead for all relays defined for this message
/// @return number of bytes needed to store all relay information
uint16_t
calculateRelaySizes
();
/// @brief calculates size of the message as if it was not relayed at all
///
/// This is equal to len() if the message was not relayed.
/// @return number of bytes required to store the message
uint16_t
directLen
()
const
;
/// UDP (usually) or TCP (bulk leasequery or failover)
DHCPv6Proto
proto_
;
...
...
src/lib/dhcp/tests/option_custom_unittest.cc
View file @
1eb11784
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012
-2013
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -766,9 +766,15 @@ TEST_F(OptionCustomTest, recordDataTruncated) {
// 2 bytes of uint16_t value and IPv6 address. Option definitions specifies
// 3 data fields for this option but the length of the data is insufficient
// to initialize 3 data field.
EXPECT_THROW
(
option
.
reset
(
new
OptionCustom
(
opt_def
,
Option
::
V6
,
buf
.
begin
(),
buf
.
begin
()
+
18
)),
isc
::
OutOfRange
// @todo:
// Currently the code was modified to allow empty string or empty binary data
// Potentially change this back to EXPECT_THROW(..., OutOfRange) once we
// decide how to treat zero length strings and binary data (they are typically
// valid or invalid on a per option basis, so there likely won't be a single
// one answer to all)
EXPECT_NO_THROW
(
option
.
reset
(
new
OptionCustom
(
opt_def
,
Option
::
V6
,
buf
.
begin
(),
buf
.
begin
()
+
18
))
);
// Try to further reduce the length of the buffer to make it insufficient
...
...
src/lib/dhcp/tests/pkt6_unittest.cc
View file @
1eb11784
// Copyright (C) 2011-201
2
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-201
3
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -17,9 +17,15 @@
#include
<asiolink/io_address.h>
#include
<dhcp/dhcp6.h>
#include
<dhcp/option.h>
#include
<dhcp/option_custom.h>
#include
<dhcp/option6_ia.h>
#include
<dhcp/option_int.h>
#include
<dhcp/option_int_array.h>
#include
<dhcp/pkt6.h>
#include
<boost/date_time/posix_time/posix_time.hpp>
#include
<boost/scoped_ptr.hpp>
#include
<util/encode/hex.h>
#include
<gtest/gtest.h>
#include
<iostream>
...
...
@@ -99,6 +105,67 @@ Pkt6* capture1() {
return
(
pkt
);
}
/// @brief creates doubly relayed solicit message
///
/// This is a traffic capture exported from wireshark. It includes a SOLICIT
/// message that passed through two relays. Each relay include interface-id,
/// remote-id and relay-forw encapsulation. It is especially interesting,