Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
8b0cb0de
Commit
8b0cb0de
authored
Apr 25, 2013
by
Marcin Siodelski
Browse files
[2902] DHCPv4 server will try to use 'direct response' feature if possible.
parent
fa9feb90
Changes
12
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/dhcp4_srv.cc
View file @
8b0cb0de
...
...
@@ -61,8 +61,13 @@ Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const char* dbconfig, const bool use_bcast)
LOG_DEBUG
(
dhcp4_logger
,
DBG_DHCP4_START
,
DHCP4_OPEN_SOCKET
).
arg
(
port
);
try
{
// First call to instance() will create IfaceMgr (it's a singleton)
// it may throw something if things go wrong
IfaceMgr
::
instance
();
// it may throw something if things go wrong.
// The 'true' value of in the call to setMatchingPacketFilter imposes
// that IfaceMgr will try to use the mechanism to respond directly
// to the client which doesn't have address assigned. This capability
// may be lacking on some OSes, so there is no guarantee that server
// will be able to respond directly.
IfaceMgr
::
instance
().
setMatchingPacketFilter
(
true
);
if
(
port
)
{
// open sockets only if port is non-zero. Port 0 is used
...
...
src/lib/dhcp/iface_mgr.cc
View file @
8b0cb0de
...
...
@@ -157,6 +157,11 @@ IfaceMgr::~IfaceMgr() {
closeSockets
();
}
bool
IfaceMgr
::
isDirectResponseSupported
()
const
{
return
(
packet_filter_
->
isDirectResponseSupported
());
}
void
IfaceMgr
::
stubDetectIfaces
()
{
string
ifaceName
;
const
string
v4addr
(
"127.0.0.1"
),
v6addr
(
"::1"
);
...
...
src/lib/dhcp/iface_mgr.h
View file @
8b0cb0de
...
...
@@ -39,13 +39,6 @@ public:
isc
::
Exception
(
file
,
line
,
what
)
{
};
};
/// @brief IfaceMgr exception thrown when invalid packet filter object specified.
class
InvalidPacketFilter
:
public
Exception
{
public:
InvalidPacketFilter
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{
};
};
/// @brief IfaceMgr exception thrown thrown when socket opening
/// or configuration failed.
class
SocketConfigError
:
public
Exception
{
...
...
@@ -324,7 +317,7 @@ public:
/// the client.
///
/// @return true if direct response is supported.
bool
isDirectResponseSupported
();
bool
isDirectResponseSupported
()
const
;
/// @brief Returns interface with specified interface index
///
...
...
@@ -580,6 +573,22 @@ public:
packet_filter_
=
packet_filter
;
}
/// @brief Set Packet Filter object to handle send/receive packets.
///
/// This function sets Packet Filter object to be used by IfaceMgr,
/// appropriate for the current OS. They will vary depending on the
/// OS being used if the function argument is set 'true'. There is
/// no guarantee that there is an implementation that supports this
/// feature on a particular OS. If there isn't the PktFilterInet
/// object will be set. If the argument is set to 'false' then
/// PktFilterInet object instance will be set as the Packet Filter
/// regrdaless of the OS.
///
/// @param direct_response_desired specifies whether the Packet Filter
/// object being set should support direct responses to the host
/// not having address assigned.
void
setMatchingPacketFilter
(
const
bool
direct_response_desired
=
false
);
/// A value of socket descriptor representing "not specified" state.
static
const
int
INVALID_SOCKET
=
-
1
;
...
...
src/lib/dhcp/iface_mgr_bsd.cc
View file @
8b0cb0de
...
...
@@ -34,11 +34,6 @@ IfaceMgr::detectIfaces() {
stubDetectIfaces
();
}
bool
IfaceMgr
::
isDirectResponseSupported
()
{
return
(
false
);
}
void
IfaceMgr
::
os_send4
(
struct
msghdr
&
/*m*/
,
boost
::
scoped_array
<
char
>&
/*control_buf*/
,
size_t
/*control_buf_len*/
,
...
...
@@ -54,6 +49,13 @@ bool IfaceMgr::os_receive4(struct msghdr& /*m*/, Pkt4Ptr& /*pkt*/) {
return
(
true
);
// pretend that we have everything set up for reception.
}
void
IfaceMgr
::
setMatchingPacketFilter
(
const
bool
/* direct_response_desired */
)
{
boost
::
shared_ptr
<
PktFilter
>
pkt_filter
(
new
PktFilterInet
());
setPacketFilter
(
pkt_filter
);
}
}
// end of isc::dhcp namespace
}
// end of dhcp namespace
...
...
src/lib/dhcp/iface_mgr_linux.cc
View file @
8b0cb0de
...
...
@@ -33,6 +33,8 @@
#include <asiolink/io_address.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/pkt_filter_inet.h>
#include <dhcp/pkt_filter_lpf.h>
#include <exceptions/exceptions.h>
#include <util/io/sockaddr_util.h>
...
...
@@ -494,11 +496,6 @@ void IfaceMgr::detectIfaces() {
nl
.
release_list
(
addr_info
);
}
bool
IfaceMgr
::
isDirectResponseSupported
()
{
return
(
false
);
}
/// @brief sets flag_*_ fields.
///
/// This implementation is OS-specific as bits have different meaning
...
...
@@ -515,6 +512,18 @@ void Iface::setFlags(uint32_t flags) {
flag_broadcast_
=
flags
&
IFF_BROADCAST
;
}
void
IfaceMgr
::
setMatchingPacketFilter
(
const
bool
direct_response_desired
)
{
if
(
direct_response_desired
)
{
boost
::
shared_ptr
<
PktFilter
>
pkt_filter
(
new
PktFilterLPF
());
setPacketFilter
(
pkt_filter
);
}
else
{
boost
::
shared_ptr
<
PktFilter
>
pkt_filter
(
new
PktFilterInet
());
setPacketFilter
(
pkt_filter
);
}
}
void
IfaceMgr
::
os_send4
(
struct
msghdr
&
,
boost
::
scoped_array
<
char
>&
,
size_t
,
const
Pkt4Ptr
&
)
{
...
...
src/lib/dhcp/iface_mgr_sun.cc
View file @
8b0cb0de
...
...
@@ -34,11 +34,6 @@ IfaceMgr::detectIfaces() {
stubDetectIfaces
();
}
bool
IfaceMgr
::
isDirectResponseSupported
()
{
return
(
false
);
}
void
IfaceMgr
::
os_send4
(
struct
msghdr
&
/*m*/
,
boost
::
scoped_array
<
char
>&
/*control_buf*/
,
size_t
/*control_buf_len*/
,
...
...
@@ -54,6 +49,12 @@ bool IfaceMgr::os_receive4(struct msghdr& /*m*/, Pkt4Ptr& /*pkt*/) {
return
(
true
);
// pretend that we have everything set up for reception.
}
void
IfaceMgr
::
setMatchingPacketFilter
(
const
bool
/* direct_response_desired */
)
{
boost
::
shared_ptr
<
PktFilter
>
pkt_filter
(
new
PktFilterInet
());
setPacketFilter
(
pkt_filter
);
}
}
// end of isc::dhcp namespace
}
// end of dhcp namespace
...
...
src/lib/dhcp/pkt_filter.h
View file @
8b0cb0de
...
...
@@ -15,12 +15,20 @@
#ifndef PKT_FILTER_H
#define PKT_FILTER_H
#include <dhcp/pkt4.h>
#include <asiolink/io_address.h>
#include <boost/shared_ptr.hpp>
namespace
isc
{
namespace
dhcp
{
/// @brief Exception thrown when invalid packet filter object specified.
class
InvalidPacketFilter
:
public
Exception
{
public:
InvalidPacketFilter
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{
};
};
struct
SocketInfo
;
/// Forward declaration to the class representing interface
...
...
@@ -46,6 +54,18 @@ public:
/// @brief Virtual Destructor
virtual
~
PktFilter
()
{
}
/// @brief Check if packet can be sent to the host without address directly.
///
/// Checks if the Packet Filter class has capability to send a packet
/// directly to the client having no address assigned. This capability
/// is used by DHCPv4 servers which respond to the clients they assign
/// addresses to. Not all classes derived from PktFilter support this
/// because it requires injection of the destination host HW address to
/// the link layer header of the packet.
///
/// @return true of the direct response is supported.
virtual
bool
isDirectResponseSupported
()
const
=
0
;
/// @brief Open socket.
///
/// @param iface interface descriptor
...
...
src/lib/dhcp/pkt_filter_inet.h
View file @
8b0cb0de
...
...
@@ -33,6 +33,17 @@ public:
/// Allocates control buffer.
PktFilterInet
();
/// @brief Check if packet can be sent to the host without address directly.
///
/// This Packet Filter sends packets through AF_INET datagram sockets, so
/// it can't inject the HW address of the destionation host into the packet.
/// Therefore this class does not support direct responses.
///
/// @return false always.
virtual
bool
isDirectResponseSupported
()
const
{
return
(
false
);
}
/// @brief Open socket.
///
/// @param iface interface descriptor
...
...
src/lib/dhcp/pkt_filter_lpf.h
View file @
8b0cb0de
...
...
@@ -32,6 +32,15 @@ namespace dhcp {
class
PktFilterLPF
:
public
PktFilter
{
public:
/// @brief Check if packet can be sent to the host without address directly.
///
/// This class supports direct responses to the host without address.
///
/// @return true always.
virtual
bool
isDirectResponseSupported
()
const
{
return
(
true
);
}
/// @brief Open socket.
///
/// @param iface interface descriptor
...
...
src/lib/dhcp/tests/iface_mgr_unittest.cc
View file @
8b0cb0de
...
...
@@ -74,6 +74,10 @@ public:
:
open_socket_called_
(
false
)
{
}
virtual
bool
isDirectResponseSupported
()
const
{
return
(
false
);
}
/// Pretends to open socket. Only records a call to this function.
virtual
int
openSocket
(
const
Iface
&
,
const
isc
::
asiolink
::
IOAddress
&
,
...
...
@@ -839,6 +843,69 @@ TEST_F(IfaceMgrTest, setPacketFilter) {
EXPECT_EQ
(
1024
,
socket1
);
}
#if defined OS_LINUX
// This Linux specific test checks whether it is possible to use
// IfaceMgr to figure out which Pakcket Filter object should be
// used when direct responses to hosts, having no address assigned
// are desired or not desired.
TEST_F
(
IfaceMgrTest
,
setMatchingPacketFilter
)
{
// Create an instance of IfaceMgr.
boost
::
scoped_ptr
<
NakedIfaceMgr
>
iface_mgr
(
new
NakedIfaceMgr
());
ASSERT_TRUE
(
iface_mgr
);
// Let IfaceMgr figure out which Packet Filter to use when
// direct response capability is not desired. It should pick
// PktFilterInet.
EXPECT_NO_THROW
(
iface_mgr
->
setMatchingPacketFilter
(
false
));
// The PktFilterInet is supposed to report lack of direct
// response capability.
EXPECT_FALSE
(
iface_mgr
->
isDirectResponseSupported
());
// There is working implementation of direct responses on Linux
// in PktFilterLPF. It uses Linux Packet Filtering as underlying
// mechanism. When direct responses are desired the object of
// this class should be set.
EXPECT_NO_THROW
(
iface_mgr
->
setMatchingPacketFilter
(
true
));
// This object should report that direct responses are supported.
EXPECT_TRUE
(
iface_mgr
->
isDirectResponseSupported
());
}
#else
// This non-Linux specific test checks whether it is possible to use
// IfaceMgr to figure out which Pakcket Filter object should be
// used when direct responses to hosts, having no address assigned
// are desired or not desired. Since direct responses aren't supported
// on systems other than Linux the function under test should always
// set object of PktFilterInet type as current Packet Filter. This
// object does not support direct responses. Once implementation is
// added on non-Linux systems the OS specific version of the test
// will be removed.
TEST_F
(
IfaceMgrTest
,
setMatchingPacketFilter
)
{
// Create an instance of IfaceMgr.
boost
::
scoped_ptr
<
NakedIfaceMgr
>
iface_mgr
(
new
NakedIfaceMgr
());
ASSERT_TRUE
(
iface_mgr
);
// Let IfaceMgr figure out which Packet Filter to use when
// direct response capability is not desired. It should pick
// PktFilterInet.
EXPECT_NO_THROW
(
iface_mgr
->
setMatchingPacketFilter
(
false
));
// The PktFilterInet is supposed to report lack of direct
// response capability.
EXPECT_FALSE
(
iface_mgr
->
isDirectResponseSupported
());
// On non-Linux systems, we are missing the direct traffic
// implementation. Therefore, we expect that PktFilterInet
// object will be set.
EXPECT_NO_THROW
(
iface_mgr
->
setMatchingPacketFilter
(
true
));
// This object should report lack of direct response capability.
EXPECT_FALSE
(
iface_mgr
->
isDirectResponseSupported
());
}
#endif
TEST_F
(
IfaceMgrTest
,
socket4
)
{
...
...
src/lib/dhcp/tests/pkt_filter_inet_unittest.cc
View file @
8b0cb0de
...
...
@@ -77,6 +77,17 @@ public:
};
// This test verifies that the PktFilterInet class reports its lack
// of capability to send packets to the host having no IP address
// assigned.
TEST_F
(
PktFilterInetTest
,
isDirectResponseSupported
)
{
// Create object under test.
PktFilterInet
pkt_filter
;
// This Packet Filter class does not support direct responses
// under any conditions.
EXPECT_FALSE
(
pkt_filter
.
isDirectResponseSupported
());
}
// This test verifies that the INET datagram socket is correctly opened and
// bound to the appropriate address and port.
TEST_F
(
PktFilterInetTest
,
openSocket
)
{
...
...
src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc
View file @
8b0cb0de
...
...
@@ -81,6 +81,15 @@ public:
};
// This test verifies that the PktFilterLPF class reports its capability
// to send packets to the host having no IP address assigned.
TEST_F
(
PktFilterLPFTest
,
isDirectResponseSupported
)
{
// Create object under test.
PktFilterLPF
pkt_filter
;
// Must support direct responses.
EXPECT_TRUE
(
pkt_filter
.
isDirectResponseSupported
());
}
// All tests below require root privileges to execute successfully. If
// they are run as non-root user they will fail due to insufficient privileges
// to open raw network sockets. Therefore, they should remain disabled by default
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a 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