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
50d91e4c
Commit
50d91e4c
authored
Oct 23, 2013
by
Marcin Siodelski
Browse files
[master] Merge branch 'trac3200'
parents
78cb0f4f
45eb1980
Changes
11
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/dhcp4_messages.mes
View file @
50d91e4c
...
...
@@ -118,7 +118,7 @@ a lease. It is up to the client to choose one server out of othe advertised
and continue allocation with that server. This is a normal behavior and
indicates successful operation.
% DHCP4_LEASE_ADVERT_FAIL failed to advertise a lease for client client-id %1, hwaddr %2
% DHCP4_LEASE_ADVERT_FAIL failed to advertise a lease for client client-id %1, hwaddr %2
, client sent yiaddr %3
This message indicates that the server has failed to offer a lease to
the specified client after receiving a DISCOVER message from it. There are
many possible reasons for such a failure.
...
...
@@ -128,7 +128,7 @@ This debug message indicates that the server successfully granted a lease
in response to client's REQUEST message. This is a normal behavior and
indicates successful operation.
% DHCP4_LEASE_ALLOC_FAIL failed to grant a lease for client-id %1, hwaddr %2
% DHCP4_LEASE_ALLOC_FAIL failed to grant a lease for client-id %1, hwaddr %2
, client sent yiaddr %3
This message indicates that the server failed to grant a lease to the
specified client after receiving a REQUEST message from it. There are many
possible reasons for such a failure. Additional messages will indicate the
...
...
src/bin/dhcp4/dhcp4_srv.cc
View file @
50d91e4c
...
...
@@ -754,13 +754,6 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
opt
->
setUint32
(
lease
->
valid_lft_
);
answer
->
addOption
(
opt
);
// Router (type 3)
Subnet
::
OptionDescriptor
opt_routers
=
subnet
->
getOptionDescriptor
(
"dhcp4"
,
DHO_ROUTERS
);
if
(
opt_routers
.
option
)
{
answer
->
addOption
(
opt_routers
.
option
);
}
// Subnet mask (type 1)
answer
->
addOption
(
getNetmaskOption
(
subnet
));
...
...
@@ -857,14 +850,17 @@ Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
copyDefaultFields
(
discover
,
offer
);
appendDefaultOptions
(
offer
,
DHCPOFFER
);
appendRequestedOptions
(
discover
,
offer
);
assignLease
(
discover
,
offer
);
// There are a few basic options that we always want to
// include in the response. If client did not request
// them we append them for him.
appendBasicOptions
(
discover
,
offer
);
// Adding any other options makes sense only when we got the lease.
if
(
offer
->
getYiaddr
()
!=
IOAddress
(
"0.0.0.0"
))
{
appendRequestedOptions
(
discover
,
offer
);
// There are a few basic options that we always want to
// include in the response. If client did not request
// them we append them for him.
appendBasicOptions
(
discover
,
offer
);
}
return
(
offer
);
}
...
...
@@ -880,17 +876,20 @@ Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
copyDefaultFields
(
request
,
ack
);
appendDefaultOptions
(
ack
,
DHCPACK
);
appendRequestedOptions
(
request
,
ack
);
// Note that we treat REQUEST message uniformly, regardless if this is a
// first request (requesting for new address), renewing existing address
// or even rebinding.
assignLease
(
request
,
ack
);
// There are a few basic options that we always want to
// include in the response. If client did not request
// them we append them for him.
appendBasicOptions
(
request
,
ack
);
// Adding any other options makes sense only when we got the lease.
if
(
ack
->
getYiaddr
()
!=
IOAddress
(
"0.0.0.0"
))
{
appendRequestedOptions
(
request
,
ack
);
// There are a few basic options that we always want to
// include in the response. If client did not request
// them we append them for him.
appendBasicOptions
(
request
,
ack
);
}
return
(
ack
);
}
...
...
src/bin/dhcp4/tests/dhcp4_test_utils.cc
View file @
50d91e4c
...
...
@@ -22,6 +22,7 @@
#include
<dhcp/option_custom.h>
#include
<dhcp/iface_mgr.h>
#include
<dhcpsrv/cfgmgr.h>
#include
<dhcpsrv/lease.h>
#include
<dhcpsrv/lease_mgr.h>
#include
<dhcpsrv/lease_mgr_factory.h>
...
...
@@ -123,37 +124,101 @@ void Dhcpv4SrvTest::messageCheck(const Pkt4Ptr& q, const Pkt4Ptr& a) {
EXPECT_TRUE
(
q
->
getLocalHWAddr
()
==
a
->
getLocalHWAddr
());
EXPECT_TRUE
(
q
->
getRemoteHWAddr
()
==
a
->
getRemoteHWAddr
());
// Check that bare minimum of required options are there.
// We don't check options requested by a client. Those
// are checked elsewhere.
EXPECT_TRUE
(
a
->
getOption
(
DHO_SUBNET_MASK
));
EXPECT_TRUE
(
a
->
getOption
(
DHO_ROUTERS
));
// Check that the server identifier is present in the response.
// Presence (or absence) of other options is checked elsewhere.
EXPECT_TRUE
(
a
->
getOption
(
DHO_DHCP_SERVER_IDENTIFIER
));
EXPECT_TRUE
(
a
->
getOption
(
DHO_DHCP_LEASE_TIME
));
EXPECT_TRUE
(
a
->
getOption
(
DHO_SUBNET_MASK
));
EXPECT_TRUE
(
a
->
getOption
(
DHO_DOMAIN_NAME
));
EXPECT_TRUE
(
a
->
getOption
(
DHO_DOMAIN_NAME_SERVERS
));
// Check that something is offered
EXPECT_TRUE
(
a
->
getYiaddr
().
toText
()
!=
"0.0.0.0"
);
}
void
Dhcpv4SrvTest
::
optionsCheck
(
const
Pkt4Ptr
&
pkt
)
{
// Check that the requested and configured options are returned
// in the ACK message.
EXPECT_TRUE
(
pkt
->
getOption
(
DHO_DOMAIN_NAME
))
<<
"domain-name not present in the response"
;
EXPECT_TRUE
(
pkt
->
getOption
(
DHO_DOMAIN_NAME_SERVERS
))
<<
"dns-servers not present in the response"
;
EXPECT_TRUE
(
pkt
->
getOption
(
DHO_LOG_SERVERS
))
<<
"log-servers not present in the response"
;
EXPECT_TRUE
(
pkt
->
getOption
(
DHO_COOKIE_SERVERS
))
<<
"cookie-servers not present in the response"
;
// Check that the requested but not configured options are not
// returned in the ACK message.
EXPECT_FALSE
(
pkt
->
getOption
(
DHO_LPR_SERVERS
))
<<
"domain-name present in the response but it is"
<<
" expected not to be present"
;
::
testing
::
AssertionResult
Dhcpv4SrvTest
::
basicOptionsPresent
(
const
Pkt4Ptr
&
pkt
)
{
std
::
ostringstream
errmsg
;
errmsg
<<
"option missing in the response"
;
if
(
!
pkt
->
getOption
(
DHO_DOMAIN_NAME
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"domain-name "
<<
errmsg
));
}
else
if
(
!
pkt
->
getOption
(
DHO_DOMAIN_NAME_SERVERS
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"dns-servers "
<<
errmsg
));
}
else
if
(
!
pkt
->
getOption
(
DHO_SUBNET_MASK
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"subnet-mask "
<<
errmsg
));
}
else
if
(
!
pkt
->
getOption
(
DHO_ROUTERS
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"routers "
<<
errmsg
));
}
else
if
(
!
pkt
->
getOption
(
DHO_DHCP_LEASE_TIME
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"dhcp-lease-time "
<<
errmsg
));
}
return
(
::
testing
::
AssertionSuccess
());
}
::
testing
::
AssertionResult
Dhcpv4SrvTest
::
noBasicOptions
(
const
Pkt4Ptr
&
pkt
)
{
std
::
ostringstream
errmsg
;
errmsg
<<
"option present in the response"
;
if
(
pkt
->
getOption
(
DHO_DOMAIN_NAME
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"domain-name "
<<
errmsg
));
}
else
if
(
pkt
->
getOption
(
DHO_DOMAIN_NAME_SERVERS
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"dns-servers "
<<
errmsg
));
}
else
if
(
pkt
->
getOption
(
DHO_SUBNET_MASK
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"subnet-mask "
<<
errmsg
));
}
else
if
(
pkt
->
getOption
(
DHO_ROUTERS
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"routers "
<<
errmsg
));
}
else
if
(
pkt
->
getOption
(
DHO_DHCP_LEASE_TIME
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"dhcp-lease-time "
<<
errmsg
));
}
return
(
::
testing
::
AssertionSuccess
());
}
::
testing
::
AssertionResult
Dhcpv4SrvTest
::
requestedOptionsPresent
(
const
Pkt4Ptr
&
pkt
)
{
std
::
ostringstream
errmsg
;
errmsg
<<
"option missing in the response"
;
if
(
!
pkt
->
getOption
(
DHO_LOG_SERVERS
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"log-servers "
<<
errmsg
));
}
else
if
(
!
pkt
->
getOption
(
DHO_COOKIE_SERVERS
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"cookie-servers "
<<
errmsg
));
}
return
(
::
testing
::
AssertionSuccess
());
}
::
testing
::
AssertionResult
Dhcpv4SrvTest
::
noRequestedOptions
(
const
Pkt4Ptr
&
pkt
)
{
std
::
ostringstream
errmsg
;
errmsg
<<
"option present in the response"
;
if
(
pkt
->
getOption
(
DHO_LOG_SERVERS
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"log-servers "
<<
errmsg
));
}
else
if
(
pkt
->
getOption
(
DHO_COOKIE_SERVERS
))
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"cookie-servers "
<<
errmsg
));
}
return
(
::
testing
::
AssertionSuccess
());
}
OptionPtr
Dhcpv4SrvTest
::
generateClientId
(
size_t
size
/*= 4*/
)
{
...
...
@@ -274,6 +339,48 @@ void Dhcpv4SrvTest::checkClientId(const Pkt4Ptr& rsp, const OptionPtr& expected_
EXPECT_TRUE
(
expected_clientid
->
getData
()
==
opt
->
getData
());
}
::
testing
::
AssertionResult
Dhcpv4SrvTest
::
createPacketFromBuffer
(
const
Pkt4Ptr
&
src_pkt
,
Pkt4Ptr
&
dst_pkt
)
{
// Create on-wire format of the packet. If pack() has been called
// on this instance of the packet already, the next call to pack()
// should remove all contents of the output buffer.
try
{
src_pkt
->
pack
();
}
catch
(
const
Exception
&
ex
)
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"Failed to parse source packet: "
<<
ex
.
what
()));
}
// Get the output buffer from the source packet.
const
util
::
OutputBuffer
&
buf
=
src_pkt
->
getBuffer
();
// Create a copy of the packet using the output buffer from the source
// packet.
try
{
dst_pkt
.
reset
(
new
Pkt4
(
static_cast
<
const
uint8_t
*>
(
buf
.
getData
()),
buf
.
getLength
()));
}
catch
(
const
Exception
&
ex
)
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"Failed to create a"
" destination packet from"
" the buffer: "
<<
ex
.
what
()));
}
try
{
// Parse the new packet and return to the caller.
dst_pkt
->
unpack
();
}
catch
(
const
Exception
&
ex
)
{
return
(
::
testing
::
AssertionFailure
(
::
testing
::
Message
()
<<
"Failed to parse a"
<<
" destination packet: "
<<
ex
.
what
()));
}
return
(
::
testing
::
AssertionSuccess
());
}
void
Dhcpv4SrvTest
::
testDiscoverRequest
(
const
uint8_t
msg_type
)
{
// Create an instance of the tested class.
boost
::
scoped_ptr
<
NakedDhcpv4Srv
>
srv
(
new
NakedDhcpv4Srv
(
0
));
...
...
@@ -318,17 +425,22 @@ void Dhcpv4SrvTest::testDiscoverRequest(const uint8_t msg_type) {
// are returned when requested.
configureRequestedOptions
();
// Create a copy of the original packet by parsing its wire format.
// This simulates the real life scenario when we process the packet
// which was parsed from its wire format.
Pkt4Ptr
received
;
ASSERT_TRUE
(
createPacketFromBuffer
(
req
,
received
));
if
(
msg_type
==
DHCPDISCOVER
)
{
ASSERT_NO_THROW
(
rsp
=
srv
->
processDiscover
(
re
q
);
);
rsp
=
srv
->
processDiscover
(
re
ceived
);
);
// Should return OFFER
ASSERT_TRUE
(
rsp
);
EXPECT_EQ
(
DHCPOFFER
,
rsp
->
getType
());
}
else
{
ASSERT_NO_THROW
(
rsp
=
srv
->
processRequest
(
re
q
);
);
ASSERT_NO_THROW
(
rsp
=
srv
->
processRequest
(
re
ceived
)
);
// Should return ACK
ASSERT_TRUE
(
rsp
);
...
...
@@ -336,27 +448,30 @@ void Dhcpv4SrvTest::testDiscoverRequest(const uint8_t msg_type) {
}
messageCheck
(
re
q
,
rsp
);
messageCheck
(
re
ceived
,
rsp
);
// Basic options should be present when we got the lease.
EXPECT_TRUE
(
basicOptionsPresent
(
rsp
));
// We did not request any options so these should not be present
// in the RSP.
EXPECT_FALSE
(
rsp
->
getOption
(
DHO_LOG_SERVERS
));
EXPECT_FALSE
(
rsp
->
getOption
(
DHO_COOKIE_SERVERS
));
EXPECT_FALSE
(
rsp
->
getOption
(
DHO_LPR_SERVERS
));
EXPECT_TRUE
(
noRequestedOptions
(
rsp
));
// Repeat the test but request some options.
// Add 'Parameter Request List' option.
addPrlOption
(
req
);
ASSERT_TRUE
(
createPacketFromBuffer
(
req
,
received
));
ASSERT_TRUE
(
received
->
getOption
(
DHO_DHCP_PARAMETER_REQUEST_LIST
));
if
(
msg_type
==
DHCPDISCOVER
)
{
ASSERT_NO_THROW
(
rsp
=
srv
->
processDiscover
(
re
q
);
);
ASSERT_NO_THROW
(
rsp
=
srv
->
processDiscover
(
re
ceived
)
);
// Should return non-NULL packet.
ASSERT_TRUE
(
rsp
);
EXPECT_EQ
(
DHCPOFFER
,
rsp
->
getType
());
}
else
{
ASSERT_NO_THROW
(
rsp
=
srv
->
processRequest
(
re
q
);
);
ASSERT_NO_THROW
(
rsp
=
srv
->
processRequest
(
re
ceived
)
);
// Should return non-NULL packet.
ASSERT_TRUE
(
rsp
);
...
...
@@ -364,7 +479,41 @@ void Dhcpv4SrvTest::testDiscoverRequest(const uint8_t msg_type) {
}
// Check that the requested options are returned.
optionsCheck
(
rsp
);
EXPECT_TRUE
(
basicOptionsPresent
(
rsp
));
EXPECT_TRUE
(
requestedOptionsPresent
(
rsp
));
// The following part of the test will test that the NAK is sent when
// there is no address pool configured. In the same time, we expect
// that the requested options are not included in NAK message, but that
// they are only included when yiaddr is set to non-zero value.
ASSERT_NO_THROW
(
subnet_
->
delPools
(
Lease
::
TYPE_V4
));
// There has been a lease allocated for the particular client. So,
// even though we deleted the subnet, the client would get the
// existing lease (not a NAK). Therefore, we have to change the chaddr
// in the packet so as the existing lease is not returned.
req
->
setHWAddr
(
1
,
6
,
std
::
vector
<
uint8_t
>
(
2
,
6
));
ASSERT_TRUE
(
createPacketFromBuffer
(
req
,
received
));
ASSERT_TRUE
(
received
->
getOption
(
DHO_DHCP_PARAMETER_REQUEST_LIST
));
if
(
msg_type
==
DHCPDISCOVER
)
{
ASSERT_NO_THROW
(
rsp
=
srv
->
processDiscover
(
received
));
// Should return non-NULL packet.
ASSERT_TRUE
(
rsp
);
}
else
{
ASSERT_NO_THROW
(
rsp
=
srv
->
processRequest
(
received
));
// Should return non-NULL packet.
ASSERT_TRUE
(
rsp
);
}
// We should get the NAK packet with yiaddr set to 0.
EXPECT_EQ
(
DHCPNAK
,
rsp
->
getType
());
ASSERT_EQ
(
"0.0.0.0"
,
rsp
->
getYiaddr
().
toText
());
// Make sure that none of the requested options is returned in NAK.
// Also options such as Routers or Subnet Mask should not be there,
// because lease hasn't been acquired.
EXPECT_TRUE
(
noRequestedOptions
(
rsp
));
EXPECT_TRUE
(
noBasicOptions
(
rsp
));
}
/// @brief This function cleans up after the test.
...
...
src/bin/dhcp4/tests/dhcp4_test_utils.h
View file @
50d91e4c
...
...
@@ -109,10 +109,32 @@ public:
/// @param a answer (server's message)
void
messageCheck
(
const
Pkt4Ptr
&
q
,
const
Pkt4Ptr
&
a
);
/// @brief Check that requested options are present.
/// @brief Check that certain basic (always added when lease is acquired)
/// are present in a message.
///
/// @param pkt packet to be checked.
void
optionsCheck
(
const
Pkt4Ptr
&
pkt
);
/// @param pkt A message to be checked.
/// @return Assertion result which indicates whether test passed or failed.
::
testing
::
AssertionResult
basicOptionsPresent
(
const
Pkt4Ptr
&
pkt
);
/// @brief Check that certain basic (always added when lease is acquired)
/// are not present.
///
/// @param pkt A packet to be checked.
/// @return Assertion result which indicates whether test passed or failed.
::
testing
::
AssertionResult
noBasicOptions
(
const
Pkt4Ptr
&
pkt
);
/// @brief Check that certain requested options are present in the message.
///
/// @param pkt A message to be checked.
/// @return Assertion result which indicates whether test passed or failed.
::
testing
::
AssertionResult
requestedOptionsPresent
(
const
Pkt4Ptr
&
pkt
);
/// @brief Check that certain options (requested with PRL option)
/// are not present.
///
/// @param pkt A packet to be checked.
/// @return Assertion result which indicates whether test passed or failed.
::
testing
::
AssertionResult
noRequestedOptions
(
const
Pkt4Ptr
&
pkt
);
/// @brief generates client-id option
///
...
...
@@ -183,6 +205,32 @@ public:
/// @return relayed DISCOVER
Pkt4Ptr
captureRelayedDiscover
();
/// @brief Create packet from output buffer of another packet.
///
/// This function creates a packet using an output buffer from another
/// packet. This imitates reception of a packet from the wire. The
/// unpack function is then called to parse packet contents and to
/// create a collection of the options carried by this packet.
///
/// This function is useful for unit tests which verify that the received
/// packet is parsed correctly. In those cases it is usually inappropriate
/// to create an instance of the packet, add options, set packet
/// fields and use such packet as an input to processDiscover or
/// processRequest function. This is because, such a packet has certain
/// options already initialized and there is no way to verify that they
/// have been initialized when packet instance was created or wire buffer
/// processing. By creating a packet from the buffer we guarantee that the
/// new packet is entirely initialized during wire data parsing.
///
/// @param src_pkt A source packet, to be copied.
/// @param [out] dst_pkt A destination packet.
///
/// @return assertion result indicating if a function completed with
/// success or failure.
static
::
testing
::
AssertionResult
createPacketFromBuffer
(
const
Pkt4Ptr
&
src_pkt
,
Pkt4Ptr
&
dst_pkt
);
/// @brief generates a DHCPv4 packet based on provided hex string
///
/// @return created packet
...
...
@@ -190,6 +238,14 @@ public:
/// @brief Tests if Discover or Request message is processed correctly
///
/// This test verifies that the Parameter Request List option is handled
/// correctly, i.e. it checks that certain options are present in the
/// server's response when they are requested and that they are not present
/// when they are not requested or NAK occurs.
///
/// @todo We need an additional test for PRL option using real traffic
/// capture.
///
/// @param msg_type DHCPDISCOVER or DHCPREQUEST
void
testDiscoverRequest
(
const
uint8_t
msg_type
);
...
...
src/lib/dhcp/option_definition.cc
View file @
50d91e4c
...
...
@@ -124,12 +124,14 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
return
(
factoryGeneric
(
u
,
type
,
begin
,
end
));
case
OPT_UINT8_TYPE
:
return
(
array_type_
?
factoryGeneric
(
u
,
type
,
begin
,
end
)
:
return
(
array_type_
?
factoryIntegerArray
<
uint8_t
>
(
u
,
type
,
begin
,
end
)
:
factoryInteger
<
uint8_t
>
(
u
,
type
,
getEncapsulatedSpace
(),
begin
,
end
,
callback
));
case
OPT_INT8_TYPE
:
return
(
array_type_
?
factoryGeneric
(
u
,
type
,
begin
,
end
)
:
return
(
array_type_
?
factoryIntegerArray
<
int8_t
>
(
u
,
type
,
begin
,
end
)
:
factoryInteger
<
int8_t
>
(
u
,
type
,
getEncapsulatedSpace
(),
begin
,
end
,
callback
));
...
...
src/lib/dhcp/pkt4.cc
View file @
50d91e4c
...
...
@@ -108,6 +108,10 @@ Pkt4::pack() {
isc_throw
(
InvalidOperation
,
"Can't build Pkt4 packet. HWAddr not set."
);
}
// Clear the output buffer to make sure that consecutive calls to pack()
// will not result in concatenation of multiple packet copies.
buffer_out_
.
clear
();
try
{
size_t
hw_len
=
hwaddr_
->
hwaddr_
.
size
();
...
...
src/lib/dhcp/pkt4.h
View file @
50d91e4c
...
...
@@ -72,6 +72,7 @@ public:
/// Prepares on-wire format of message and all its options.
/// Options must be stored in options_ field.
/// Output buffer will be stored in buffer_out_.
/// The buffer_out_ is cleared before writting to the buffer.
///
/// @throw InvalidOperation if packing fails
void
...
...
src/lib/dhcp/pkt6.cc
View file @
50d91e4c
...
...
@@ -43,7 +43,7 @@ Pkt6::Pkt6(const uint8_t* buf, uint32_t buf_len, DHCPv6Proto proto /* = UDP */)
remote_addr_
(
"::"
),
local_port_
(
0
),
remote_port_
(
0
),
buffer
O
ut_
(
0
)
{
buffer
_o
ut_
(
0
)
{
data_
.
resize
(
buf_len
);
memcpy
(
&
data_
[
0
],
buf
,
buf_len
);
}
...
...
@@ -58,7 +58,7 @@ Pkt6::Pkt6(uint8_t msg_type, uint32_t transid, DHCPv6Proto proto /*= UDP*/) :
remote_addr_
(
"::"
),
local_port_
(
0
),
remote_port_
(
0
),
buffer
O
ut_
(
0
)
{
buffer
_o
ut_
(
0
)
{
}
uint16_t
Pkt6
::
len
()
{
...
...
@@ -199,6 +199,8 @@ Pkt6::pack() {
void
Pkt6
::
packUDP
()
{
try
{
// Make sure that the buffer is empty before we start writting to it.
buffer_out_
.
clear
();
// is this a relayed packet?
if
(
!
relay_info_
.
empty
())
{
...
...
@@ -215,11 +217,11 @@ Pkt6::packUDP() {
relay
!=
relay_info_
.
end
();
++
relay
)
{
// build relay-forw/relay-repl header (see RFC3315, section 7)
buffer
O
ut_
.
writeUint8
(
relay
->
msg_type_
);
buffer
O
ut_
.
writeUint8
(
relay
->
hop_count_
);
buffer
O
ut_
.
writeData
(
&
(
relay
->
linkaddr_
.
toBytes
()[
0
]),
buffer
_o
ut_
.
writeUint8
(
relay
->
msg_type_
);
buffer
_o
ut_
.
writeUint8
(
relay
->
hop_count_
);
buffer
_o
ut_
.
writeData
(
&
(
relay
->
linkaddr_
.
toBytes
()[
0
]),
isc
::
asiolink
::
V6ADDRESS_LEN
);
buffer
O
ut_
.
writeData
(
&
relay
->
peeraddr_
.
toBytes
()[
0
],
buffer
_o
ut_
.
writeData
(
&
relay
->
peeraddr_
.
toBytes
()[
0
],
isc
::
asiolink
::
V6ADDRESS_LEN
);
// store every option in this relay scope. Usually that will be
...
...
@@ -230,28 +232,28 @@ Pkt6::packUDP() {
for
(
OptionCollection
::
const_iterator
opt
=
relay
->
options_
.
begin
();
opt
!=
relay
->
options_
.
end
();
++
opt
)
{
(
opt
->
second
)
->
pack
(
buffer
O
ut_
);
(
opt
->
second
)
->
pack
(
buffer
_o
ut_
);
}
// 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)
buffer
O
ut_
.
writeUint16
(
D6O_RELAY_MSG
);
buffer
O
ut_
.
writeUint16
(
relay
->
relay_msg_len_
);
buffer
_o
ut_
.
writeUint16
(
D6O_RELAY_MSG
);
buffer
_o
ut_
.
writeUint16
(
relay
->
relay_msg_len_
);
}
}
// DHCPv6 header: message-type (1 octect) + transaction id (3 octets)
buffer
O
ut_
.
writeUint8
(
msg_type_
);
buffer
_o
ut_
.
writeUint8
(
msg_type_
);
// store 3-octet transaction-id
buffer
O
ut_
.
writeUint8
(
(
transid_
>>
16
)
&
0xff
);
buffer
O
ut_
.
writeUint8
(
(
transid_
>>
8
)
&
0xff
);
buffer
O
ut_
.
writeUint8
(
(
transid_
)
&
0xff
);
buffer
_o
ut_
.
writeUint8
(
(
transid_
>>
16
)
&
0xff
);
buffer
_o
ut_
.
writeUint8
(
(
transid_
>>
8
)
&
0xff
);
buffer
_o
ut_
.
writeUint8
(
(
transid_
)
&
0xff
);
// the rest are options
LibDHCP
::
packOptions
(
buffer
O
ut_
,
options_
);
LibDHCP
::
packOptions
(
buffer
_o
ut_
,
options_
);
}
catch
(
const
Exception
&
e
)
{
// An exception is thrown and message will be written to Logger
...
...
@@ -502,7 +504,7 @@ Pkt6::delOption(uint16_t type) {
}
void
Pkt6
::
repack
()
{
buffer
O
ut_
.
writeData
(
&
data_
[
0
],
data_
.
size
());
buffer
_o
ut_
.
writeData
(
&
data_
[
0
],
data_
.
size
());
}
void
...
...
src/lib/dhcp/pkt6.h
View file @
50d91e4c
...
...
@@ -115,6 +115,7 @@ public:
/// Options must be stored in options_ field.
/// Output buffer will be stored in data_. Length
/// will be set in data_len_.
/// The output buffer is cleared before new data is written to it.
///
/// @throw BadValue if packet protocol is invalid, InvalidOperation
/// if packing fails, or NotImplemented if protocol is TCP (IPv6 over TCP is
...
...
@@ -139,7 +140,7 @@ public:
/// zero length
///
/// @return reference to output buffer
const
isc
::
util
::
OutputBuffer
&
getBuffer
()
const
{
return
(
buffer
O
ut_
);
};
const
isc
::
util
::
OutputBuffer
&
getBuffer
()
const
{
return
(
buffer
_o
ut_
);
};
/// @brief Returns protocol of this packet (UDP or TCP).
///
...
...
@@ -530,7 +531,7 @@ protected:
/// remote TCP or UDP port
uint16_t
remote_port_
;
///
o
utput buffer (used during message transmission)
///
O
utput buffer (used during message transmission)
///
/// @warning This protected member is accessed by derived
/// classes directly. One of such derived classes is
...
...
@@ -538,7 +539,7 @@ protected:
/// behavior must be taken into consideration before making
/// changes to this member such as access scope restriction or
/// data format change etc.
isc
::
util
::
OutputBuffer
buffer
O
ut_
;
isc
::
util
::
OutputBuffer
buffer
_o
ut_
;
/// packet timestamp
boost
::
posix_