Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
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
fe532755
Commit
fe532755
authored
Jun 09, 2016
by
Francis Dupont
Browse files
[4106_update] Ported and improved code from old trac4106 including unit tests
parent
d610482f
Changes
19
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/ctrl_dhcp4_srv.cc
View file @
fe532755
...
...
@@ -192,7 +192,7 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
// Setup DHCPv4-over-DHCPv6 IPC
try
{
Dhcp4o6Ipc
::
instance
().
open
();
Dhcp4
t
o6Ipc
::
instance
().
open
();
}
catch
(
const
std
::
exception
&
ex
)
{
std
::
ostringstream
err
;
err
<<
"error starting DHCPv4-over-DHCPv6 IPC "
...
...
src/bin/dhcp4/dhcp4_dhcp4o6_ipc.cc
View file @
fe532755
...
...
@@ -24,14 +24,14 @@ using namespace std;
namespace
isc
{
namespace
dhcp
{
Dhcp4o6Ipc
::
Dhcp4o6Ipc
()
:
Dhcp4o6IpcBase
()
{}
Dhcp4
t
o6Ipc
::
Dhcp4
t
o6Ipc
()
:
Dhcp4o6IpcBase
()
{}
Dhcp4o6Ipc
&
Dhcp4o6Ipc
::
instance
()
{
static
Dhcp4o6Ipc
dhcp4o6_ipc
;
return
(
dhcp4o6_ipc
);
Dhcp4
t
o6Ipc
&
Dhcp4
t
o6Ipc
::
instance
()
{
static
Dhcp4
t
o6Ipc
dhcp4
t
o6_ipc
;
return
(
dhcp4
t
o6_ipc
);
}
void
Dhcp4o6Ipc
::
open
()
{
void
Dhcp4
t
o6Ipc
::
open
()
{
uint32_t
port
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getDhcp4o6Port
();
if
(
port
==
0
)
{
Dhcp4o6IpcBase
::
close
();
...
...
@@ -42,31 +42,48 @@ void Dhcp4o6Ipc::open() {
}
int
old_fd
=
socket_fd_
;
socket_fd_
=
Dhcp4o6IpcBase
::
open
(
static_cast
<
uint16_t
>
(
port
),
4
);
socket_fd_
=
Dhcp4o6IpcBase
::
open
(
static_cast
<
uint16_t
>
(
port
),
ENDPOINT_TYPE_V4
);
if
((
old_fd
==
-
1
)
&&
(
socket_fd_
!=
old_fd
))
{
IfaceMgr
::
instance
().
addExternalSocket
(
socket_fd_
,
Dhcp4o6Ipc
::
handler
);
IfaceMgr
::
instance
().
addExternalSocket
(
socket_fd_
,
Dhcp4to6Ipc
::
handler
);
}
}
void
Dhcp4o6Ipc
::
handler
()
{
Dhcp4o6Ipc
&
ipc
=
Dhcp4o6Ipc
::
instance
();
void
Dhcp4to6Ipc
::
handler
()
{
Dhcp4to6Ipc
&
ipc
=
Dhcp4to6Ipc
::
instance
();
// Reset received message in case we return from this method before the
// received message pointer is updated.
ipc
.
received_
.
reset
();
// Receive message from the IPC socket.
Pkt6Ptr
pkt
=
ipc
.
receive
();
if
(
!
pkt
)
{
return
;
}
// Each message must contain option holding DHCPv4 message.
OptionCollection
msgs
=
pkt
->
getOptions
(
D6O_DHCPV4_MSG
);
if
(
msgs
.
size
()
!=
1
)
{
return
;
if
(
msgs
.
empty
())
{
isc_throw
(
Dhcp4o6IpcError
,
"DHCPv4 message option not present in the"
" DHCPv4o6 message received by the DHCPv4 server"
);
}
else
if
(
msgs
.
size
()
>
1
)
{
isc_throw
(
Dhcp4o6IpcError
,
"expected exactly one DHCPv4 message within"
" DHCPv4 message option received by the DHCPv4 server"
);
}
OptionPtr
msg
=
pkt
->
getOption
(
D6O_DHCPV4_MSG
);
OptionPtr
msg
=
msgs
.
begin
()
->
second
;
if
(
!
msg
)
{
isc_throw
(
Unexpected
,
"Can't get DHCPv4 message option"
);
isc_throw
(
Dhcp4o6IpcError
,
"null DHCPv4 message option in the"
" DHCPv4o6 message received by the DHCPv4 server"
);
}
instance
().
received_
.
reset
(
new
Pkt4o6
(
msg
->
getData
(),
pkt
));
// Record this message.
ipc
.
received_
.
reset
(
new
Pkt4o6
(
msg
->
getData
(),
pkt
));
}
Pkt4o6Ptr
&
Dhcp4o6Ipc
::
getReceived
()
{
Pkt4o6Ptr
&
Dhcp4
t
o6Ipc
::
getReceived
()
{
return
(
received_
);
}
...
...
src/bin/dhcp4/dhcp4_dhcp4o6_ipc.h
View file @
fe532755
...
...
@@ -28,23 +28,23 @@ namespace isc {
namespace
dhcp
{
/// @brief Handles DHCPv4-over-DHCPv6 IPC on the DHCPv4 server side
class
Dhcp4o6Ipc
:
public
Dhcp4o6IpcBase
{
class
Dhcp4
t
o6Ipc
:
public
Dhcp4o6IpcBase
{
protected:
/// @brief Constructor
///
/// Default constructor
Dhcp4o6Ipc
();
Dhcp4
t
o6Ipc
();
/// @brief Destructor.
virtual
~
Dhcp4o6Ipc
()
{
}
virtual
~
Dhcp4
t
o6Ipc
()
{
}
public:
/// @brief Returns pointer to the sole instance of Dhcp4o6Ipc
/// @brief Returns pointer to the sole instance of Dhcp4
t
o6Ipc
///
/// Dhcp4o6Ipc is a singleton class
/// Dhcp4
t
o6Ipc is a singleton class
///
/// @return the only existing instance of DHCP4o6 IPC
static
Dhcp4o6Ipc
&
instance
();
static
Dhcp4
t
o6Ipc
&
instance
();
/// @brief Open communication socket
///
...
...
src/bin/dhcp4/tests/Makefile.am
View file @
fe532755
...
...
@@ -93,6 +93,7 @@ dhcp4_unittests_SOURCES += release_unittest.cc
dhcp4_unittests_SOURCES
+=
out_of_range_unittest.cc
dhcp4_unittests_SOURCES
+=
decline_unittest.cc
dhcp4_unittests_SOURCES
+=
kea_controller_unittest.cc
dhcp4_unittests_SOURCES
+=
dhcp4_dhcp4o6_ipc_unittest.cc
nodist_dhcp4_unittests_SOURCES
=
marker_file.h test_libraries.h
...
...
src/bin/dhcp4/tests/dhcp4_dhcp4o6_ipc_unittest.cc
0 → 100644
View file @
fe532755
// Copyright (C) 2015-2016 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
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#include <asiolink/io_address.h>
#include <dhcp/pkt4o6.h>
#include <dhcp/pkt6.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcp4/dhcp4_dhcp4o6_ipc.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/testutils/dhcp4o6_test_ipc.h>
#include <gtest/gtest.h>
#include <stdint.h>
using
namespace
isc
;
using
namespace
isc
::
asiolink
;
using
namespace
isc
::
dhcp
;
using
namespace
isc
::
dhcp
::
test
;
using
namespace
isc
::
util
;
namespace
{
/// @brief Port number used in tests.
const
uint16_t
TEST_PORT
=
32000
;
/// @brief Define short name for the test IPC.
typedef
Dhcp4o6TestIpc
TestIpc
;
/// @brief Test fixture class for DHCPv4 endpoint of DHCPv4o6 IPC.
class
Dhcp4to6IpcTest
:
public
::
testing
::
Test
{
public:
/// @brief Constructor
///
/// Configures IPC to use a test port. It also provides a fake
/// configuration of interfaces.
Dhcp4to6IpcTest
()
:
iface_mgr_test_config_
(
true
)
{
configurePort
(
TEST_PORT
);
}
/// @brief Configure DHCP4o6 port.
///
/// @param port New port.
void
configurePort
(
uint16_t
port
);
/// @brief Creates an instance of the DHCPv4o6 Message option.
///
/// @return Pointer to the instance of the DHCPv4-query Message option.
OptionPtr
createDHCPv4MsgOption
()
const
;
private:
/// @brief Provides fake configuration of interfaces.
IfaceMgrTestConfig
iface_mgr_test_config_
;
};
void
Dhcp4to6IpcTest
::
configurePort
(
uint16_t
port
)
{
CfgMgr
::
instance
().
getStagingCfg
()
->
setDhcp4o6Port
(
port
);
}
OptionPtr
Dhcp4to6IpcTest
::
createDHCPv4MsgOption
()
const
{
// Create the DHCPv4 message.
Pkt4Ptr
pkt
(
new
Pkt4
(
DHCPREQUEST
,
1234
));
// Make a wire representation of the DHCPv4 message.
pkt
->
pack
();
OutputBuffer
&
output_buffer
=
pkt
->
getBuffer
();
const
uint8_t
*
data
=
static_cast
<
const
uint8_t
*>
(
output_buffer
.
getData
());
OptionBuffer
option_buffer
(
data
,
data
+
output_buffer
.
getLength
());
// Create the DHCPv4 Message option holding the created message.
OptionPtr
opt_msg
(
new
Option
(
Option
::
V6
,
D6O_DHCPV4_MSG
,
option_buffer
));
return
(
opt_msg
);
}
// This test verifies that the IPC returns an error when trying to bind
// to the out of range port.
TEST_F
(
Dhcp4to6IpcTest
,
invalidPortError
)
{
// Create instance of the IPC endpoint under test with out-of-range port.
configurePort
(
65535
);
Dhcp4to6Ipc
&
ipc
=
Dhcp4to6Ipc
::
instance
();
EXPECT_THROW
(
ipc
.
open
(),
isc
::
OutOfRange
);
}
// This test verifies that the DHCPv4 endpoint of the DHCPv4o6 IPC can
// receive messages.
TEST_F
(
Dhcp4to6IpcTest
,
receive
)
{
// Create instance of the IPC endpoint under test.
Dhcp4to6Ipc
&
ipc
=
Dhcp4to6Ipc
::
instance
();
// Create instance of the IPC endpoint being used as a source of messages.
TestIpc
src_ipc
(
TEST_PORT
,
TestIpc
::
ENDPOINT_TYPE_V6
);
// Open both endpoints.
ASSERT_NO_THROW
(
ipc
.
open
());
ASSERT_NO_THROW
(
src_ipc
.
open
());
// Create message to be sent over IPC.
Pkt6Ptr
pkt
(
new
Pkt6
(
DHCPV6_DHCPV4_QUERY
,
1234
));
pkt
->
addOption
(
createDHCPv4MsgOption
());
pkt
->
setIface
(
"eth0"
);
pkt
->
setRemoteAddr
(
IOAddress
(
"2001:db8:1::123"
));
ASSERT_NO_THROW
(
pkt
->
pack
());
// Send and wait up to 1 second to receive it.
ASSERT_NO_THROW
(
src_ipc
.
send
(
pkt
));
ASSERT_NO_THROW
(
IfaceMgr
::
instance
().
receive6
(
1
,
0
));
// Make sure that the message has been received.
Pkt4o6Ptr
pkt_received
=
ipc
.
getReceived
();
ASSERT_TRUE
(
pkt_received
);
Pkt6Ptr
pkt6_received
=
pkt_received
->
getPkt6
();
ASSERT_TRUE
(
pkt6_received
);
EXPECT_EQ
(
"eth0"
,
pkt6_received
->
getIface
());
EXPECT_EQ
(
"2001:db8:1::123"
,
pkt6_received
->
getRemoteAddr
().
toText
());
}
// This test verifies that message with multiple DHCPv4 query options
// is rejected.
TEST_F
(
Dhcp4to6IpcTest
,
receiveMultipleQueries
)
{
// Create instance of the IPC endpoint under test.
Dhcp4to6Ipc
&
ipc
=
Dhcp4to6Ipc
::
instance
();
// Create instance of the IPC endpoint being used as a source of messages.
TestIpc
src_ipc
(
TEST_PORT
,
TestIpc
::
ENDPOINT_TYPE_V6
);
// Open both endpoints.
ASSERT_NO_THROW
(
ipc
.
open
());
ASSERT_NO_THROW
(
src_ipc
.
open
());
// Create message to be sent over IPC.
Pkt6Ptr
pkt
(
new
Pkt6
(
DHCPV6_DHCPV4_QUERY
,
1234
));
// Add two DHCPv4 query options.
pkt
->
addOption
(
createDHCPv4MsgOption
());
pkt
->
addOption
(
createDHCPv4MsgOption
());
pkt
->
setIface
(
"eth0"
);
pkt
->
setRemoteAddr
(
IOAddress
(
"2001:db8:1::123"
));
ASSERT_NO_THROW
(
pkt
->
pack
());
// Send message.
ASSERT_NO_THROW
(
src_ipc
.
send
(
pkt
));
// Reception handler should throw exception.
EXPECT_THROW
(
IfaceMgr
::
instance
().
receive6
(
1
,
0
),
Dhcp4o6IpcError
);
}
// This test verifies that message with no DHCPv4 query options is rejected.
TEST_F
(
Dhcp4to6IpcTest
,
receiveNoQueries
)
{
// Create instance of the IPC endpoint under test.
Dhcp4to6Ipc
&
ipc
=
Dhcp4to6Ipc
::
instance
();
// Create instance of the IPC endpoint being used as a source of messages.
TestIpc
src_ipc
(
TEST_PORT
,
TestIpc
::
ENDPOINT_TYPE_V6
);
// Open both endpoints.
ASSERT_NO_THROW
(
ipc
.
open
());
ASSERT_NO_THROW
(
src_ipc
.
open
());
// Create message to be sent over IPC without DHCPv4 query option.
Pkt6Ptr
pkt
(
new
Pkt6
(
DHCPV6_DHCPV4_QUERY
,
1234
));
pkt
->
setIface
(
"eth0"
);
pkt
->
setRemoteAddr
(
IOAddress
(
"2001:db8:1::123"
));
ASSERT_NO_THROW
(
pkt
->
pack
());
// Send message.
ASSERT_NO_THROW
(
src_ipc
.
send
(
pkt
));
// Reception handler should throw exception.
EXPECT_THROW
(
IfaceMgr
::
instance
().
receive6
(
1
,
0
),
Dhcp4o6IpcError
);
}
}
// end of anonymous namespace
src/bin/dhcp6/ctrl_dhcp6_srv.cc
View file @
fe532755
...
...
@@ -216,7 +216,7 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
// Setup DHCPv4-over-DHCPv6 IPC
try
{
Dhcp
4o6
Ipc
::
instance
().
open
();
Dhcp
6to4
Ipc
::
instance
().
open
();
}
catch
(
const
std
::
exception
&
ex
)
{
std
::
ostringstream
err
;
err
<<
"error starting DHCPv4-over-DHCPv6 IPC "
...
...
src/bin/dhcp6/dhcp6_dhcp4o6_ipc.cc
View file @
fe532755
...
...
@@ -24,14 +24,14 @@ using namespace std;
namespace
isc
{
namespace
dhcp
{
Dhcp
4o6
Ipc
::
Dhcp
4o6
Ipc
()
:
Dhcp4o6IpcBase
()
{}
Dhcp
6to4
Ipc
::
Dhcp
6to4
Ipc
()
:
Dhcp4o6IpcBase
()
{}
Dhcp
4o6
Ipc
&
Dhcp
4o6
Ipc
::
instance
()
{
static
Dhcp
4o6
Ipc
dhcp
4o6
_ipc
;
return
(
dhcp
4o6
_ipc
);
Dhcp
6to4
Ipc
&
Dhcp
6to4
Ipc
::
instance
()
{
static
Dhcp
6to4
Ipc
dhcp
6to4
_ipc
;
return
(
dhcp
6to4
_ipc
);
}
void
Dhcp
4o6
Ipc
::
open
()
{
void
Dhcp
6to4
Ipc
::
open
()
{
uint32_t
port
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getDhcp4o6Port
();
if
(
port
==
0
)
{
Dhcp4o6IpcBase
::
close
();
...
...
@@ -42,30 +42,38 @@ void Dhcp4o6Ipc::open() {
}
int
old_fd
=
socket_fd_
;
socket_fd_
=
Dhcp4o6IpcBase
::
open
(
static_cast
<
uint16_t
>
(
port
),
6
);
socket_fd_
=
Dhcp4o6IpcBase
::
open
(
static_cast
<
uint16_t
>
(
port
),
ENDPOINT_TYPE_V6
);
if
((
old_fd
==
-
1
)
&&
(
socket_fd_
!=
old_fd
))
{
IfaceMgr
::
instance
().
addExternalSocket
(
socket_fd_
,
Dhcp4o6Ipc
::
handler
);
IfaceMgr
::
instance
().
addExternalSocket
(
socket_fd_
,
Dhcp6to4Ipc
::
handler
);
}
}
void
Dhcp4o6Ipc
::
handler
()
{
Dhcp4o6Ipc
&
ipc
=
Dhcp4o6Ipc
::
instance
();
void
Dhcp6to4Ipc
::
handler
()
{
Dhcp6to4Ipc
&
ipc
=
Dhcp6to4Ipc
::
instance
();
// Receive message from IPC.
Pkt6Ptr
pkt
=
ipc
.
receive
();
if
(
!
pkt
)
{
return
;
}
// The received message has been unpacked by the receive() function. This
// method could have modified the message so it's better to pack() it
// again because we'll be forwarding it to a client.
isc
::
util
::
OutputBuffer
&
buf
=
pkt
->
getBuffer
();
buf
.
clear
();
pkt
->
pack
();
uint8_t
msg_type
=
buf
[
0
]
;
uint8_t
msg_type
=
pkt
->
getType
()
;
if
((
msg_type
==
DHCPV6_RELAY_FORW
)
||
(
msg_type
==
DHCPV6_RELAY_REPL
))
{
pkt
->
setRemotePort
(
DHCP6_SERVER_PORT
);
}
else
{
pkt
->
setRemotePort
(
DHCP6_CLIENT_PORT
);
}
// Forward packet to the client.
IfaceMgr
::
instance
().
send
(
pkt
);
// processStatsSent(pkt);
}
...
...
src/bin/dhcp6/dhcp6_dhcp4o6_ipc.h
View file @
fe532755
...
...
@@ -15,7 +15,7 @@
#ifndef DHCP6_DHCP4O6_IPC_H
#define DHCP6_DHCP4O6_IPC_H
/// @file dhcp6_dhcp4o6_ipc.h Defines the Dhcp
4o6
Ipc class.
/// @file dhcp6_dhcp4o6_ipc.h Defines the Dhcp
6to4
Ipc class.
/// This file defines the class Kea uses to act as the DHCPv6 server
/// side of DHCPv4-over-DHCPv6 communication between servers.
///
...
...
@@ -26,23 +26,23 @@ namespace isc {
namespace
dhcp
{
/// @brief Handles DHCPv4-over-DHCPv6 IPC on the DHCPv6 server side
class
Dhcp
4o6
Ipc
:
public
Dhcp4o6IpcBase
{
class
Dhcp
6to4
Ipc
:
public
Dhcp4o6IpcBase
{
protected:
/// @brief Constructor
///
/// Default constructor
Dhcp
4o6
Ipc
();
Dhcp
6to4
Ipc
();
/// @brief Destructor.
virtual
~
Dhcp
4o6
Ipc
()
{
}
virtual
~
Dhcp
6to4
Ipc
()
{
}
public:
/// @brief Returns pointer to the sole instance of Dhcp
4o6
Ipc
/// @brief Returns pointer to the sole instance of Dhcp
6to4
Ipc
///
/// Dhcp
4o6
Ipc is a singleton class
/// Dhcp
6to4
Ipc is a singleton class
///
/// @return the only existing instance of DHCP4o6 IPC
static
Dhcp
4o6
Ipc
&
instance
();
static
Dhcp
6to4
Ipc
&
instance
();
/// @brief Open communication socket
///
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
fe532755
...
...
@@ -213,7 +213,7 @@ Dhcpv6Srv::~Dhcpv6Srv() {
}
try
{
Dhcp
4o6
Ipc
::
instance
().
close
();
Dhcp
6to4
Ipc
::
instance
().
close
();
}
catch
(
const
std
::
exception
&
ex
)
{
// Highly unlikely, but lets Report it but go on
// LOG_ERROR(dhcp6_logger, DHCP6_SRV_DHCP4O6_ERROR).arg(ex.what());
...
...
src/bin/dhcp6/tests/Makefile.am
View file @
fe532755
...
...
@@ -94,8 +94,8 @@ dhcp6_unittests_SOURCES += confirm_unittest.cc
dhcp6_unittests_SOURCES
+=
infrequest_unittest.cc
dhcp6_unittests_SOURCES
+=
decline_unittest.cc
dhcp6_unittests_SOURCES
+=
dhcp6_message_test.cc dhcp6_message_test.h
dhcp6_unittests_SOURCES
+=
kea_controller_unittest.cc
dhcp6_unittests_SOURCES
+=
dhcp6_dhcp4o6_ipc_unittest.cc
nodist_dhcp6_unittests_SOURCES
=
marker_file.h test_libraries.h
...
...
src/bin/dhcp6/tests/dhcp6_dhcp4o6_ipc_unittest.cc
0 → 100644
View file @
fe532755
// Copyright (C) 2015-2016 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
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#include <asiolink/io_address.h>
#include <dhcp/pkt6.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcp/tests/pkt_filter6_test_stub.h>
#include <dhcp6/dhcp6_dhcp4o6_ipc.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/testutils/dhcp4o6_test_ipc.h>
#include <gtest/gtest.h>
#include <stdint.h>
using
namespace
isc
;
using
namespace
isc
::
asiolink
;
using
namespace
isc
::
dhcp
;
using
namespace
isc
::
dhcp
::
test
;
using
namespace
isc
::
util
;
namespace
{
/// @brief Port number used in tests.
const
uint16_t
TEST_PORT
=
32000
;
/// @brief Define short name for the test IPC.
typedef
Dhcp4o6TestIpc
TestIpc
;
/// @brief Test fixture class for DHCPv4 endpoint of DHCPv4o6 IPC.
class
Dhcp6to4IpcTest
:
public
::
testing
::
Test
{
public:
/// @brief Constructor
///
/// Configures IPC to use a test port. It also provides a fake
/// configuration of interfaces and opens IPv6 sockets.
Dhcp6to4IpcTest
()
:
iface_mgr_test_config_
(
true
)
{
IfaceMgr
::
instance
().
openSockets6
();
configurePort
(
TEST_PORT
);
}
/// @brief Configure DHCP4o6 port.
///
/// @param port New port.
void
configurePort
(
const
uint16_t
port
);
/// @brief Creates an instance of the DHCPv4o6 Message option.
///
/// @return Pointer to the instance of the DHCPv4-query Message option.
OptionPtr
createDHCPv4MsgOption
()
const
;
private:
/// @brief Provides fake configuration of interfaces.
IfaceMgrTestConfig
iface_mgr_test_config_
;
};
void
Dhcp6to4IpcTest
::
configurePort
(
const
uint16_t
port
)
{
CfgMgr
::
instance
().
getStagingCfg
()
->
setDhcp4o6Port
(
port
);
}
OptionPtr
Dhcp6to4IpcTest
::
createDHCPv4MsgOption
()
const
{
// Create the DHCPv4 message.
Pkt4Ptr
pkt
(
new
Pkt4
(
DHCPREQUEST
,
1234
));
// Make a wire representation of the DHCPv4 message.
pkt
->
pack
();
OutputBuffer
&
output_buffer
=
pkt
->
getBuffer
();
const
uint8_t
*
data
=
static_cast
<
const
uint8_t
*>
(
output_buffer
.
getData
());
OptionBuffer
option_buffer
(
data
,
data
+
output_buffer
.
getLength
());
// Create the DHCPv4 Message option holding the created message.
OptionPtr
opt_msg
(
new
Option
(
Option
::
V6
,
D6O_DHCPV4_MSG
,
option_buffer
));
return
(
opt_msg
);
}
// This test verifies that the IPC returns an error when trying to bind
// to the out of range port.
TEST_F
(
Dhcp6to4IpcTest
,
invalidPortError
)
{
// Create instance of the IPC endpoint under test with out-of-range port.
configurePort
(
65535
);
Dhcp6to4Ipc
&
ipc
=
Dhcp6to4Ipc
::
instance
();
EXPECT_THROW
(
ipc
.
open
(),
isc
::
OutOfRange
);
}
// This test verifies that the DHCPv4 endpoint of the DHCPv4o6 IPC can
// receive messages.
TEST_F
(
Dhcp6to4IpcTest
,
receive
)
{
// Create instance of the IPC endpoint under test.
Dhcp6to4Ipc
&
ipc
=
Dhcp6to4Ipc
::
instance
();
// Create instance of the IPC endpoint being used as a source of messages.
TestIpc
src_ipc
(
TEST_PORT
,
TestIpc
::
ENDPOINT_TYPE_V4
);
// Open both endpoints.
ASSERT_NO_THROW
(
ipc
.
open
());
ASSERT_NO_THROW
(
src_ipc
.
open
());
// Create message to be sent over IPC.
Pkt6Ptr
pkt
(
new
Pkt6
(
DHCPV6_DHCPV4_QUERY
,
1234
));
pkt
->
addOption
(
createDHCPv4MsgOption
());
pkt
->
setIface
(
"eth0"
);
pkt
->
setRemoteAddr
(
IOAddress
(
"2001:db8:1::123"
));
ASSERT_NO_THROW
(
pkt
->
pack
());
// Send and wait up to 1 second to receive it.
ASSERT_NO_THROW
(
src_ipc
.
send
(
pkt
));
ASSERT_NO_THROW
(
IfaceMgr
::
instance
().
receive6
(
1
,
0
));
#if 0
// The stub packet filter exposes static function to retrieve messages
// sent over the fake sockets/interfaces. This is the message that the
// IPC endpoint should forward to the client after receiving it
// from the DHCPv4 server.
Pkt6Ptr forwarded = PktFilter6TestStub::popSent();
ASSERT_TRUE(forwarded);
// Verify the packet received.
EXPECT_EQ(DHCP6_CLIENT_PORT, forwarded->getRemotePort());
EXPECT_EQ(forwarded->getType(), pkt->getType());
EXPECT_TRUE(forwarded->getOption(D6O_DHCPV4_MSG));
EXPECT_EQ("eth0", forwarded->getIface());
EXPECT_EQ("2001:db8:1::123", forwarded->getRemoteAddr().toText());
#endif
}
}
// end of anonymous namespace
src/lib/dhcpsrv/dhcp4o6_ipc.cc
View file @
fe532755
...
...
@@ -17,11 +17,12 @@
#include <dhcp/dhcp6.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/option6_addrlst.h>
#include <dhcp/option_custom.h>
#include <dhcp/option_string.h>
#include <dhcp/option_vendor.h>
#include <dhcpsrv/dhcp4o6_ipc.h>
#include <
dhcpsrv/dhcpsrv_log.h
>
#include <
boost/pointer_cast.hpp
>
#include <errno.h>
#include <netinet/in.h>
#include <sys/fcntl.h>
#include <string>
...
...
@@ -39,41 +40,36 @@ Dhcp4o6IpcBase::~Dhcp4o6IpcBase() {
close
();
}
int
Dhcp4o6IpcBase
::
open
(
uint16_t
port
,
int
side
)
{
int
Dhcp4o6IpcBase
::
open
(
uint16_t
port
,
EndpointType
endpoint_type
)
{
// Don't check if the value is greater than 65534 as it is done
// by callers before they cast the value to 16 bits.
if
(
port
==
port_
)
{