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
// 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_FILTER_H
#define PKT_FILTER_H

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

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) { };
};

/// Forward declaration to the structure describing a socket.
struct SocketInfo;

/// Forward declaration to the class representing interface
class Iface;

/// @brief Abstract packet handling class
///
/// This class represents low level method to send and receive DHCP packet.
/// Different methods, represented by classes derived from this class, use
/// different socket families and socket types. Also, various packet filtering
/// methods can be implemented by derived classes, e.g. Linux Packet
/// Filtering (LPF) or Berkeley Packet Filtering (BPF).
///
/// Low-level code operating on sockets may require special privileges to execute.
/// For example: opening raw socket or opening socket on low port number requires
/// root privileges. This makes it impossible or very hard to unit test the IfaceMgr.
/// In order to overcome this problem, it is recommended to create mock object derived
/// from this class that mimics the behavior of the real packet handling class making
/// IfaceMgr testable.
class PktFilter {
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 Check if the socket received time is supported.
    ///
    /// If true, then packets received through this filter will include
    /// a SOCKET_RECEIVED event in its event stack.  Other than direct
    /// clients using BPF for which this is always true, this function
    /// is true provided SO_TIMESTAMP is defined.
    ///
    /// @return True if it is supported.
    virtual bool isSocketReceivedTimeSupported() const = 0;

    /// @brief Open primary and fallback socket.
    ///
    /// A method implementation in the derived class may open one or two
    /// sockets:
    /// - a primary socket - used for communication with clients. DHCP messages
    /// received using this socket are processed and the same socket is used
    /// to send a response to the client.
    /// - a fallback socket which is optionally opened if there is a need for
    /// the presence of the socket which can be bound to a specific IP address
    /// and UDP port (e.g. raw primary socket can't be). For the details, see
    /// the documentation of @c isc::dhcp::SocketInfo.
    ///
    /// @param iface Interface descriptor.
    /// @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) = 0;

    /// @brief Receive packet over specified socket.
    ///
    /// @param iface interface
    /// @param socket_info structure holding socket information
    ///
    /// @return Received packet
    virtual Pkt4Ptr receive(Iface& iface,
                            const SocketInfo& socket_info) = 0;

    /// @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 the packet. It is 0 if successful.
    virtual int send(const Iface& iface, uint16_t sockfd,
                     const Pkt4Ptr& pkt) = 0;

protected:

    /// @brief Default implementation to open a fallback socket.
    ///
    /// This method provides a means to open a fallback socket and bind it
    /// to a given IPv4 address and UDP port. This function may be used by the
    /// derived classes to create a fallback socket. It can be overridden
    /// in the derived classes if it happens to be insufficient on some
    /// environments.
    ///
    /// The fallback socket is meant to be opened together with the other socket
    /// (a.k.a. primary socket) used to receive and handle DHCPv4 traffic. The
    /// traffic received through the fallback should be dropped. The reasoning
    /// behind opening the fallback socket is explained in the documentation of
    /// @c isc::dhcp::SocketInfo structure.
    ///
    /// @param addr An IPv4 address to bind the socket to.
    /// @param port A port number to bind socket to.
    ///
    /// @return A fallback socket descriptor. This descriptor should be assigned
    /// to the @c fallbackfd_ field of the @c isc::dhcp::SocketInfo structure.
    /// @throw isc::dhcp::SocketConfigError if socket opening, binding or
    /// configuration fails.
    virtual int openFallbackSocket(const isc::asiolink::IOAddress& addr,
                                   const uint16_t port);
};

/// Pointer to a PktFilter object.
typedef boost::shared_ptr<PktFilter> PktFilterPtr;

} // namespace isc::dhcp
} // namespace isc

#endif // PKT_FILTER_H