1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Copyright (C) 2013-2024 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef PKT_FILTER6_TEST_UTILS_H
#define PKT_FILTER6_TEST_UTILS_H

#include <asiolink/io_address.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/pkt_filter.h>
#include <gtest/gtest.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace isc {
namespace dhcp {
namespace test {

/// @brief Test fixture class for testing classes derived from PktFilter6 class.
///
/// This class implements a simple algorithm checking presence of the loopback
/// interface and initializing its index. It assumes that the loopback interface
/// name is one of 'lo' or 'lo0'. If none of those interfaces is found, the
/// constructor will report a failure.
///
/// @todo The interface detection algorithm should be more generic. This will
/// be possible once the cross-OS interface detection is implemented.
class PktFilter6Test : public ::testing::Test {
public:

    /// @brief Constructor
    ///
    /// This constructor initializes sock_info_ structure to a default value.
    /// The socket descriptors should be set to a negative value to indicate
    /// that no socket has been opened. Specific tests will reinitialize this
    /// structure with the values of the open sockets. For non-negative socket
    /// descriptors, the class destructor will close associated sockets.
    PktFilter6Test(const uint16_t port);

    /// @brief Destructor
    ///
    /// Closes open sockets (if any).
    virtual ~PktFilter6Test();

    /// @brief Initializes DHCPv6 message used by tests.
    void initTestMessage();

    /// @brief Detect loopback interface.
    ///
    /// @todo this function will be removed once cross-OS interface
    /// detection is implemented
    void loInit();

    /// @brief Sends a single DHCPv6 message to the loopback address.
    ///
    /// This function opens a datagram socket and binds it to the local loopback
    /// address and client port. The client's port is assumed to be port_ + 1.
    /// The send_msg_sock_ member holds the socket descriptor so as the socket
    /// is closed automatically in the destructor. If the function succeeds to
    /// send a DHCPv6 message, the socket is closed so as the function can be
    /// called again within the same test.
    void sendMessage();

    /// @brief Test that the datagram socket is opened correctly.
    ///
    /// This function is used by multiple tests.
    ///
    /// @param sock A descriptor of the open socket.
    void testDgramSocket(const int sock) const;

    /// @brief Checks if the received message matches the test_message_.
    ///
    /// @param rcvd_msg An instance of the message to be tested.
    void testRcvdMessage(const Pkt6Ptr& rcvd_msg) const;

    /// @brief Checks that a received message has the appropriate events
    /// in it's event stack.
    ///
    /// @param msg An instance of the message to be tested.
    /// @param so_time_supported If true the event stack should have
    /// a SOCKET_RECEIVED event followed by a BUFFER_READ event, if false
    /// it should have only the latter.
    void testReceivedPktEvents(const PktPtr& msg, bool so_time_supported) const;

    /// @brief Checks the contents of a packet's event stack agains a list
    /// of expected events.
    ///
    /// @param msg pointer to the packet under test.
    /// @param start_time system time prior to or equal to the timestamp
    /// of the stack's first event (i.e. before packet was sent or received)
    /// @param expected_events a list of the event labels in the order they
    /// are expected to occur in the stack.
    void testPktEvents(const PktPtr& msg, boost::posix_time::ptime start_time,
                       std::list<std::string> expected_events) const;

    std::string ifname_;   ///< Loopback interface name.
    unsigned int ifindex_; ///< Loopback interface index.
    uint16_t port_;        ///< A port number used for the test.
    isc::dhcp::SocketInfo sock_info_; ///< A structure holding socket info.
    int send_msg_sock_;    ///< Holds a descriptor of the socket used by
                           ///< sendMessage function.
    boost::posix_time::ptime start_time_; ///< System time at the start of the test.
    Pkt6Ptr test_message_; ///< A DHCPv6 message used by tests.

};

/// @brief A stub implementation of the PktFilter6 class.
///
/// This class implements abstract methods of the @c isc::dhcp::PktFilter class.
/// The methods of this class mimic operations on sockets, but they neither
/// open actual sockets, nor perform any send nor receive operations on them.
class PktFilter6Stub : public PktFilter6 {
public:

    /// @brief Constructor
    PktFilter6Stub();

    /// @brief Simulate opening of a socket.
    ///
    /// This function simulates opening a socket. In reality, it doesn't open a
    /// socket but the socket descriptor returned in the SocketInfo structure is
    /// always set to 0. On each call to this function, the counter of
    /// invocations is increased by one. This is useful to check if packet
    /// filter object has been correctly installed and is used by @c IfaceMgr.
    /// As in the case of opening a real socket, this function will check
    /// if there is another fake socket "bound" to the same address and port.
    /// If there is, it will throw an exception. This allows to simulate the
    /// conditions when one of the sockets can't be open because there is
    /// a socket already open and test how IfaceMgr will handle it.
    ///
    /// @param iface Interface descriptor.
    /// @param addr Address on the interface to be used to send packets.
    /// @param port Port number.
    /// @param join_multicast A boolean parameter which indicates whether
    /// socket should join All_DHCP_Relay_Agents_and_servers multicast
    /// group.
    ///
    /// @return A structure describing a primary and fallback socket.
    virtual SocketInfo openSocket(const Iface& iface,<--- Function in derived class
                                  const isc::asiolink::IOAddress& addr,
                                  const uint16_t port,
                                  const bool join_multicast);

    /// @brief Simulate reception of the DHCPv6 message.
    ///
    /// @param socket_info A structure holding socket information.
    ///
    /// @return Always a NULL object.
    virtual Pkt6Ptr receive(const SocketInfo& socket_info);<--- Function in derived class

    /// @brief Simulate sending a DHCPv6 message.
    ///
    /// This function does nothing.
    ///
    /// @param iface Interface to be used to send packet.
    /// @param sockfd A socket descriptor
    /// @param pkt A packet to be sent.
    ///
    /// @note All parameters are ignored.
    ///
    /// @return 0.
    virtual int send(const Iface& iface, uint16_t sockfd, const Pkt6Ptr& pkt);<--- Function in derived class

    /// Holds the number of invocations to PktFilter6Stub::openSocket.
    int open_socket_count_;

};

}; // end of isc::dhcp::test namespace
}; // end of isc::dhcp namespace
}; // end of isc namespace

#endif // PKT_FILTER6_TEST_UTILS_H