Commit 9fba39d9 authored by Marcin Siodelski's avatar Marcin Siodelski

[master] Merge branch 'trac2893'

parents 0a00f963 6d62841b
......@@ -1756,8 +1756,15 @@ temporarily override a list of interface names and listen on all interfaces.
</simpara>
</listitem>
<listitem>
<simpara>Raw sockets operation is working on Linux
only. See <xref linkend="iface-detect"/> for details.</simpara>
<simpara>On Linux and BSD system families the DHCP messages are sent
and received over the raw sockets (using LPF and BPF) and all packet
headers (including data link layer, IP and UDP headers) are created and
parsed by Kea, rather than the system kernel. Currently, Kea can
only parse the data link layer headers with a format adhering to
IEEE 802.3 standard and assumes this data link layer header format
for all interfaces. Hence, Kea will fail to work on interfaces
which use different data link layer header formats (e.g. Infiniband).
</simpara>
</listitem>
<listitem>
<simpara>The DHCPv4 server does not verify that
......
......@@ -41,9 +41,9 @@
<para>DHCPv4 requires special raw socket processing to send and receive
packets from hosts that do not have IPv4 address assigned yet. Support
for this operation is implemented on Linux only, so it is likely that
DHCPv4 component will not work in certain cases on systems other than
Linux.</para>
for this operation is implemented on Linux, FreeBSD, NetBSD and OpenBSD.
It is likely that DHCPv4 component will not work in certain cases on
other systems.</para>
</section>
<!--
......
......@@ -64,7 +64,7 @@ public:
}
/// Does nothing.
virtual SocketInfo openSocket(const Iface&,
virtual SocketInfo openSocket(Iface&,
const isc::asiolink::IOAddress& addr,
const uint16_t port, const bool, const bool) {
return (SocketInfo(addr, port, 0));
......
......@@ -50,10 +50,16 @@ libkea_dhcp___la_SOURCES += pkt_filter6.h pkt_filter6.cc
libkea_dhcp___la_SOURCES += pkt_filter_inet.cc pkt_filter_inet.h
libkea_dhcp___la_SOURCES += pkt_filter_inet6.cc pkt_filter_inet6.h
# Utilize Linux Packet Filtering on Linux.
if OS_LINUX
libkea_dhcp___la_SOURCES += pkt_filter_lpf.cc pkt_filter_lpf.h
endif
# Utilize Berkeley Packet Filtering on BSD.
if OS_BSD
libkea_dhcp___la_SOURCES += pkt_filter_bpf.cc pkt_filter_bpf.h
endif
libkea_dhcp___la_SOURCES += std_option_defs.h
libkea_dhcp___la_SOURCES += docsis3_option_defs.h
......
......@@ -55,11 +55,18 @@ Iface::Iface(const std::string& name, int ifindex)
:name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
flag_loopback_(false), flag_up_(false), flag_running_(false),
flag_multicast_(false), flag_broadcast_(false), flags_(0),
inactive4_(false), inactive6_(false)
inactive4_(false), inactive6_(false), read_buffer_(NULL),
read_buffer_size_(0)
{
memset(mac_, 0, sizeof(mac_));
}
Iface::~Iface() {
if (read_buffer_ != NULL) {
free(read_buffer_);
}
}
void
Iface::closeSockets() {
// Close IPv4 sockets.
......@@ -167,6 +174,21 @@ bool Iface::delSocket(const uint16_t sockfd) {
return (false); // socket not found
}
void
Iface::resizeReadBuffer(const size_t new_size) {
// Do nothing if the new size is equal to the current size.
if (new_size == read_buffer_size_) {
return;
}
read_buffer_size_ = new_size;
read_buffer_ = static_cast<uint8_t*>(realloc(read_buffer_,
read_buffer_size_));
if (read_buffer_ == NULL) {
read_buffer_size_ = 0;
}
}
IfaceMgr::IfaceMgr()
:control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
control_buf_(new char[control_buf_len_]),
......@@ -411,18 +433,6 @@ bool
IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast,
IfaceMgrErrorMsgCallback error_handler) {
int count = 0;
// This option is used to bind sockets to particular interfaces.
// This is currently the only way to discover on which interface
// the broadcast packet has been received. If this option is
// not supported then only one interface should be confugured
// to listen for broadcast traffic.
#ifdef SO_BINDTODEVICE
const bool bind_to_device = true;
#else
const bool bind_to_device = false;
#endif
int bcast_num = 0;
for (IfaceCollection::iterator iface = ifaces_.begin();
......@@ -450,17 +460,26 @@ IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast,
// options on the socket so as it can receive and send broadcast
// messages.
if (iface->flag_broadcast_ && use_bcast) {
// If our OS supports binding socket to a device we can listen
// for broadcast messages on multiple interfaces. Otherwise we
// bind to INADDR_ANY address but we can do it only once. Thus,
// if one socket has been bound we can't do it any further.
if (!bind_to_device && bcast_num > 0) {
// The DHCP server must have means to determine which interface
// the broadcast packets are coming from. This is achieved by
// binding a socket to the device (interface) and specialized
// packet filters (e.g. BPF and LPF) implement this mechanism.
// If the PktFilterInet (generic one) is used, the socket is
// bound to INADDR_ANY which effectively binds the socket to
// all addresses on all interfaces. So, only one of those can
// be opened. Currently, the direct response support is
// provided by the PktFilterLPF and PktFilterBPF, so by checking
// the support for direct response we actually determine that
// one of those objects is in use. For all other objects we
// assume that binding to the device is not supported and we
// cease opening sockets and display the appropriate message.
if (!isDirectResponseSupported() && bcast_num > 0) {
IFACEMGR_ERROR(SocketConfigError, error_handler,
"SO_BINDTODEVICE socket option is"
" not supported on this OS;"
" therefore, DHCP server can only"
" listen broadcast traffic on a"
" single interface");
"Binding socket to an interface is not"
" supported on this OS; therefore only"
" one socket listening to broadcast traffic"
" can be opened. Sockets will not be opened"
" on remaining interfaces");
continue;
} else {
......@@ -479,9 +498,7 @@ IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast,
// Binding socket to an interface is not supported so we
// can't open any more broadcast sockets. Increase the
// number of open broadcast sockets.
if (!bind_to_device) {
++bcast_num;
}
++bcast_num;
}
} else {
......
......@@ -120,12 +120,21 @@ struct SocketInfo {
};
/// @brief Represents a single network interface
///
/// Iface structure represents network interface with all useful
/// information, like name, interface index, MAC address and
/// list of assigned addresses
///
/// This class also holds the pointer to the socket read buffer.
/// Functions reading from the socket may utilize this buffer to store the
/// data being read from the socket. The advantage of using the
/// pre-allocated buffer is that the buffer is allocated only once, rather
/// than on every read. In addition, some OS specific code (e.g. BPF)
/// may require use of fixed-size buffers. The size of such a buffer is
/// returned by the OS kernel when the socket is opened. Hence, it is
/// convenient to allocate the buffer when the socket is being opened and
/// utilze it throughout the lifetime of the socket.
class Iface {
public:
......@@ -154,6 +163,11 @@ public:
/// @param ifindex interface index (unique integer identifier)
Iface(const std::string& name, int ifindex);
/// @brief Destructor.
///
/// Deallocates the socket read buffer.
~Iface();
/// @brief Closes all open sockets on interface.
void closeSockets();
......@@ -330,6 +344,29 @@ public:
return unicasts_;
}
/// @brief Returns the pointer to the buffer used for data reading.
///
/// The returned pointer is only valid during the lifetime of the
/// object which returns it or until the buffer is resized.
/// This function is meant to be used with socket API to gather
/// data from the socket.
///
/// @return Pointer to the first element of the read buffer or
/// NULL if the buffer is empty.
uint8_t* getReadBuffer() const {
return (read_buffer_);
}
/// @brief Returns the current size of the socket read buffer.
size_t getReadBufferSize() const {
return (read_buffer_size_);
}
/// @brief Reallocates the socket read buffer.
///
/// @param new_size New size of the buffer.
void resizeReadBuffer(const size_t new_size);
protected:
/// Socket used to send data.
SocketCollection sockets_;
......@@ -388,6 +425,16 @@ public:
/// Indicates that IPv6 sockets should (true) or should not (false)
/// be opened on this interface.
bool inactive6_;
private:
/// @brief Pointer to the buffer holding the data read from the socket.
///
/// See @c Iface manager description for details.
uint8_t* read_buffer_;
/// @brief Allocated size of the read buffer.
size_t read_buffer_size_;
};
/// @brief This type describes the callback function invoked when error occurs
......
......@@ -18,6 +18,7 @@
#include <dhcp/iface_mgr.h>
#include <dhcp/iface_mgr_error_handler.h>
#include <dhcp/pkt_filter_bpf.h>
#include <dhcp/pkt_filter_inet.h>
#include <exceptions/exceptions.h>
......@@ -144,10 +145,21 @@ bool IfaceMgr::os_receive4(struct msghdr& /*m*/, Pkt4Ptr& /*pkt*/) {
}
void
IfaceMgr::setMatchingPacketFilter(const bool /* direct_response_desired */) {
// @todo Currently we ignore the preference to use direct traffic
// because it hasn't been implemented for BSD systems.
setPacketFilter(PktFilterPtr(new PktFilterInet()));
IfaceMgr::setMatchingPacketFilter(const bool direct_response_desired) {
// If direct response is desired we have to use BPF. If the direct
// response is not desired we use datagram socket supported by the
// PktFilterInet class. Note however that on BSD systems binding the
// datagram socket to the device is not supported and the server would
// have no means to determine on which interface the packet has been
// received. Hence, it is discouraged to use PktFilterInet for the
// server.
if (direct_response_desired) {
setPacketFilter(PktFilterPtr(new PktFilterBPF()));
} else {
setPacketFilter(PktFilterPtr(new PktFilterInet()));
}
}
bool
......
......@@ -159,32 +159,28 @@ address.
Kea supports the use of raw sockets to create a complete Data-link/IP/UDP/DHCPv4
stack. By creating each layer of the outgoing packet, the Kea logic has full
control over the frame contents and it may bypass the use of ARP to inject the
link layer address into the frame. The raw socket is bound to a specific interface,
not to the IP address/UDP port. Therefore, the system kernel doesn't have
means to verify that Kea is listening to the DHCP traffic on the specific address
and port. This has two major implications:
link layer address into the frame.
The low level operations on raw sockets are implemented within the "packet
filtering" classes derived from @c isc::dhcp::PktFilter. The implementation
of these classes is specific to the operating system. On Linux the
@c isc::dhcp::PktFilterLPF is used. On BSD systems the
@c isc::dhcp::PktFilterBPF is used.
The raw sockets are bound to a specific interface, not to the IP address/UDP port.
Therefore, the system kernel doesn't have means to verify that Kea is listening
to the DHCP traffic on the specific address and port. This has two major implications:
- It is possible to run another DHCPv4 sever instance which will bind socket to the
same address and port.
- An attempt to send a unicast message to the DHCPv4 server will result in ICMP
"Port Unreachable" message being sent by the kernel (which is unaware that the
DHCPv4 service is actually running).
In order to overcome these issues, the isc::dhcp::PktFilterLPF opens a
In order to overcome these issues, the packet filtering classes open a
regular IP/UDP socket which coexists with the raw socket. The socket is referred
to as "fallback socket" in the Kea code. All packets received through this socket
are discarded.
In general, the use of datagram sockets is preferred over raw sockets.
For convenience, the switchable Packet Filter objects are used to manage
sockets for different purposes. These objects implement the socket opening
operation and sending/receiving messages over this socket. For example:
the isc::dhcp::PktFilterLPF object opens a raw socket.
The isc::dhcp::PktFilterLPF::send and isc::dhcp::PktFilterLPF::receive
methods encode/decode full data-link/IP/UDP/DHCPv4 stack. The
isc::dhcp::PktFilterInet supports sending and receiving messages over
the regular IP/UDP socket. The isc::dhcp::PktFilterInet should be used in all
cases when an application using the libdhcp++ doesn't require sending
DHCP messages to a device which doesn't have an address yet.
@section libdhcpPktFilter6 Switchable Packet Filters for DHCPv6
The DHCPv6 implementation doesn't suffer from the problems described in \ref
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 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
......@@ -86,7 +86,7 @@ public:
/// @param send_bcast configure socket to send broadcast messages.
///
/// @return A structure describing a primary and fallback socket.
virtual SocketInfo openSocket(const Iface& iface,
virtual SocketInfo openSocket(Iface& iface,
const isc::asiolink::IOAddress& addr,
const uint16_t port,
const bool receive_bcast,
......
This diff is collapsed.
// Copyright (C) 2014 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.
#ifndef PKT_FILTER_BPF_H
#define PKT_FILTER_BPF_H
#include <dhcp/pkt_filter.h>
#include <util/buffer.h>
namespace isc {
namespace dhcp {
/// @brief Packet handling class using Berkeley Packet Filtering (BPF)
///
/// The BPF is supported on the BSD-like operating systems. It allows for access
/// to low level layers of the inbound and outbound packets. This is specifically
/// useful when the DHCP server is allocating new address to the client.
///
/// The response being sent to the client must include the HW address in the
/// datalink layer. When the regular datagram socket is used the kernel will
/// determine the HW address of the destination using ARP. In the case when
/// the DHCP server is allocating the new address for the client the ARP can't
/// be used because it requires the destination to have the IP address.
///
/// The DHCP server utilizes HW address sent by the client in the DHCP message
/// and stores it in the datalink layer of the outbound packet. The BPF provides
/// the means for crafting the whole packet (including datalink and network
/// layers) and injecting the hardware address of the client.
///
/// The DHCP server receiving the messages sent from the directly connected
/// clients to the broadcast address must be able to determine the interface
/// on which the message arrives. The Linux kernel provides the SO_BINDTODEVICE
/// socket option which allows for binding the socket to the particular
/// interface. This option is not implemented on the BSD-like operating
/// systems. This implies that there may be only one datagram socket listening
/// to broadcast messages and this socket would receive the traffic on all
/// interfaces. This effectively precludes the server from identifying the
/// interface on which the packet arrived. The BPF resolves this problem.
/// The BPF device (socket) can be attached to the selected interface using
/// the ioctl function.
///
/// In nutshell, the BPF device is created by opening the file /dev/bpf%d
/// where %d is a number. The BPF device is configured by issuing ioctl
/// commands listed here: http://www.freebsd.org/cgi/man.cgi?bpf(4).
/// The specific configuration used by Kea DHCP server is decribed in
/// documentation of @c PktFilterBPF::openSocket.
///
/// Use of BPF requires Kea to encode and decode the datalink and network
/// layer headers. Currently Kea supports encoding and decoding ethernet
/// frames on physical interfaces and pseudo headers received on local
/// loopback interface.
class PktFilterBPF : 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 primary and fallback socket.
///
/// This method opens the BPF device and applies the following
/// configuration to it:
/// - attach the device to the specified interface
/// - set filter program to receive DHCP messages encapsulated in UDP
/// packets
/// - set immediate mode which causes the read function to return
/// immediatelly and do not wait for the whole read buffer to be filled
/// by the kernel (to avoid hangs)
///
/// It also obtains the following configuration from the kernel:
/// - major and minor version of the BPF (and checks if it is valid)
/// - length of the buffer to be used to receive the data from the socket
///
/// @param iface Interface descriptor. Note that the function (re)allocates
/// the socket read buffer according to the buffer size returned by the
/// kernel.
/// @param addr Address on the interface to be used to send packets.
/// @param port Port number.
/// @param receive_bcast Configure socket to receive broadcast messages
/// @param send_bcast Configure socket to send broadcast messages.
///
/// @return A structure describing a primary and fallback socket.
virtual SocketInfo openSocket(Iface& iface,
const isc::asiolink::IOAddress& addr,
const uint16_t port,
const bool receive_bcast,
const bool send_bcast);
/// @brief Receive packet over specified socket.
///
/// @param iface interface
/// @param socket_info structure holding socket information
///
/// @return Received packet
virtual Pkt4Ptr receive(const Iface& iface, const SocketInfo& socket_info);
/// @brief Send packet over specified socket.
///
/// @param iface interface to be used to send packet
/// @param sockfd socket descriptor
/// @param pkt packet to be sent
///
/// @return result of sending a packet. It is 0 if successful.
virtual int send(const Iface& iface, uint16_t sockfd,
const Pkt4Ptr& pkt);
private:
/// @brief Writes pseudo header containing an address family into a buffer.
///
/// BPF utilizes the pseudo headers to pass the ancillary data between the
/// kernel and the application. For example, when the packet is to be sent
/// over the local loopback interface the pseudo header must be added before
/// the network layer header to indicate the address family. Other link
/// layer header (e.g. ethernet) is not used for local loopback interface.
///
/// The header written by this method consists of 4 bytes and contains the
/// address family value in host byte order. See sys/socket.h for the
/// address family values. Typically it will be AF_INET.
///
/// This function doesn't throw.
///
/// @param address_family Address family (e.g. AF_INET).
/// @param [out] out_buf buffer where a header is written.
void writeAFPseudoHeader(const uint32_t address_family,
util::OutputBuffer& out_buf);
};
} // namespace isc::dhcp
} // namespace isc
#endif // PKT_FILTER_BPF_H
......@@ -31,7 +31,7 @@ PktFilterInet::PktFilterInet()
}
SocketInfo
PktFilterInet::openSocket(const Iface& iface,
PktFilterInet::openSocket(Iface& iface,
const isc::asiolink::IOAddress& addr,
const uint16_t port,
const bool receive_bcast,
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 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
......@@ -55,7 +55,7 @@ public:
/// @return A structure describing a primary and fallback socket.
/// @throw isc::dhcp::SocketConfigError if error occurs when opening,
/// binding or configuring the socket.
virtual SocketInfo openSocket(const Iface& iface,
virtual SocketInfo openSocket(Iface& iface,
const isc::asiolink::IOAddress& addr,
const uint16_t port,
const bool receive_bcast,
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 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
......@@ -103,7 +103,7 @@ namespace isc {
namespace dhcp {
SocketInfo
PktFilterLPF::openSocket(const Iface& iface,
PktFilterLPF::openSocket(Iface& iface,
const isc::asiolink::IOAddress& addr,
const uint16_t port, const bool,
const bool) {
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 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
......@@ -49,7 +49,7 @@ public:
/// @param send_bcast Configure socket to send broadcast messages.
///
/// @return A structure describing a primary and fallback socket.
virtual SocketInfo openSocket(const Iface& iface,
virtual SocketInfo openSocket(Iface& iface,
const isc::asiolink::IOAddress& addr,
const uint16_t port,
const bool receive_bcast,
......
......@@ -78,10 +78,16 @@ libdhcp___unittests_SOURCES += pkt_filter6_test_stub.cc pkt_filter_test_stub.h
libdhcp___unittests_SOURCES += pkt_filter_test_utils.h pkt_filter_test_utils.cc
libdhcp___unittests_SOURCES += pkt_filter6_test_utils.h pkt_filter6_test_utils.cc
# Utilize Linux Packet Filtering on Linux.
if OS_LINUX
libdhcp___unittests_SOURCES += pkt_filter_lpf_unittest.cc
endif
# Utilize Berkeley Packet Filtering on BSD.
if OS_BSD
libdhcp___unittests_SOURCES += pkt_filter_bpf_unittest.cc
endif
libdhcp___unittests_SOURCES += protocol_util_unittest.cc
libdhcp___unittests_SOURCES += duid_unittest.cc
......
......@@ -17,6 +17,7 @@
#include <asiolink/io_address.h>
#include <dhcp/dhcp4.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/option.h>
#include <dhcp/pkt6.h>
#include <dhcp/pkt_filter.h>
#include <dhcp/tests/iface_mgr_test_config.h>
......@@ -56,6 +57,39 @@ const uint16_t PORT2 = 10548; // V4 socket
// tolerance to 0.01s.
const uint32_t TIMEOUT_TOLERANCE = 10000;
/// This test verifies that the socket read buffer can be used to
/// receive the data and that the data can be read from it.
TEST(IfaceTest, readBuffer) {
// Create fake interface object.
Iface iface("em0", 0);
// The size of read buffer should initially be 0 and the returned
// pointer should be NULL.
ASSERT_EQ(0, iface.getReadBufferSize());
EXPECT_EQ(NULL, iface.getReadBuffer());
// Let's resize the buffer.
iface.resizeReadBuffer(256);
// Check that the buffer has expected size.
ASSERT_EQ(256, iface.getReadBufferSize());
// The returned pointer should now be non-NULL.
uint8_t* buf_ptr = iface.getReadBuffer();
ASSERT_FALSE(buf_ptr == NULL);
// Use the pointer to set some data.
for (int i = 0; i < iface.getReadBufferSize(); ++i) {
buf_ptr[i] = i;
}
// Get the pointer again and validate the data.
buf_ptr = iface.getReadBuffer();
ASSERT_EQ(256, iface.getReadBufferSize());
for (int i = 0; i < iface.getReadBufferSize(); ++i) {
// Use assert so as it fails on the first failure, no need
// to continue further checks.
ASSERT_EQ(i, buf_ptr[i]);
}
}
/// Mock object implementing PktFilter class. It is used by
/// IfaceMgrTest::setPacketFilter to verify that IfaceMgr::setPacketFilter
/// sets this object as a handler for opening sockets. This dummy
......@@ -96,7 +130,7 @@ public:
/// @param iface An interface on which the socket is to be opened.
/// @param addr An address to which the socket is to be bound.
/// @param port A port to which the socket is to be bound.
virtual SocketInfo openSocket(const Iface& iface,
virtual SocketInfo openSocket(Iface& iface,
const isc::asiolink::IOAddress& addr,
const uint16_t port,
const bool join_multicast,
......@@ -1256,12 +1290,12 @@ TEST_F(IfaceMgrTest, setPacketFilter6) {
}
#if defined OS_LINUX
#if defined OS_LINUX || OS_BSD
// 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.
// This test is only supported on Linux and BSD systems. It checks
// if it is possible to use the IfaceMgr to select the packet filter
// object which can be used to send direct responses to the host
// which doesn't have an address yet.
TEST_F(IfaceMgrTest, setMatchingPacketFilter) {
// Create an instance of IfaceMgr.
......@@ -1270,28 +1304,27 @@ TEST_F(IfaceMgrTest, setMatchingPacketFilter) {
// Let IfaceMgr figure out which Packet Filter to use when
// direct response capability is not desired. It should pick
// PktFilterInet.
// PktFilterInet on Linux.
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.
// and BSD (using PktFilterLPF and PktFilterBPF. 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());
}
// This test checks that it is not possible to open two sockets: IP/UDP
// and raw (LPF) socket and bind to the same address and port. The
// and raw socket and bind to the same address and port. The
// raw socket should be opened together with the fallback IP/UDP socket.
// The fallback socket should fail to open when there is another IP/UDP
// socket bound to the same address and port. Failing to open the fallback
// socket should preclude the raw socket from being open.
TEST_F(IfaceMgrTest, checkPacketFilterLPFSocket) {
TEST_F(IfaceMgrTest, checkPacketFilterRawSocket) {
IOAddress loAddr("127.0.0.1");
int socket1 = -1, socket2 = -1;
// Create two instances of IfaceMgr.
......@@ -1335,15 +1368,16 @@ TEST_F(IfaceMgrTest, checkPacketFilterLPFSocket) {
#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.
// Note: This test will only run on non-Linux and non-BSD systems.
// This 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
// and BSD 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 systems