Coverage Report

Created: 2025-07-11 07:47

/src/PcapPlusPlus/Packet++/header/NflogLayer.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include "Layer.h"
4
#include "TLVData.h"
5
#include "GeneralUtils.h"
6
7
/// @file
8
9
/// @namespace pcpp
10
/// @brief The main namespace for the PcapPlusPlus lib
11
namespace pcpp
12
{
13
  /// @struct nflog_header
14
  /// Represents Nflog header
15
#pragma pack(push, 1)
16
  struct nflog_header
17
  {
18
    /// A Linux AF_ value, so it's 2 for IPv4 and 10 for IPv6
19
    uint8_t addressFamily;
20
    /// The version field is 0 for the current version of the pseudo-header
21
    uint8_t version;
22
    /// The network byte order (big-endian)
23
    uint16_t resourceId;
24
  };
25
#pragma pack(pop)
26
  static_assert(sizeof(nflog_header) == 4, "nflog_header size is not 4 bytes");
27
28
  /// @enum NflogTlvType
29
  /// Represents TLV types of NFLOG packets
30
  enum class NflogTlvType
31
  {
32
    /// the packet header structure
33
    NFULA_PACKET_HDR = 1,
34
    /// packet mark from skbuff
35
    NFULA_MARK = 2,
36
    /// nflog_timestamp_t for skbuff's time stamp
37
    NFULA_TIMESTAMP = 3,
38
    /// ifindex of device on which packet received (possibly bridge group)
39
    NFULA_IFINDEX_INDEV = 4,
40
    /// ifindex of device on which packet transmitted (possibly bridge group)
41
    NFULA_IFINDEX_OUTDEV = 5,
42
    /// ifindex of physical device on which packet received (not bridge group)
43
    NFULA_IFINDEX_PHYSINDEV = 6,
44
    /// ifindex of physical device on which packet transmitted (not bridge group)
45
    NFULA_IFINDEX_PHYSOUTDEV = 7,
46
    /// nflog_hwaddr_t for hardware address
47
    NFULA_HWADDR = 8,
48
    /// packet payload
49
    NFULA_PAYLOAD = 9,
50
    /// text string - null-terminated, count includes NUL
51
    NFULA_PREFIX = 10,
52
    /// UID owning socket on which packet was sent/received
53
    NFULA_UID = 11,
54
    /// sequence number of packets on this NFLOG socket
55
    NFULA_SEQ = 12,
56
    /// sequence number of packets on all NFLOG sockets
57
    NFULA_SEQ_GLOBAL = 13,
58
    /// GID owning socket on which packet was sent/received
59
    NFULA_GID = 14,
60
    /// ARPHRD_ type of skbuff's device
61
    NFULA_HWTYPE = 15,
62
    /// skbuff's MAC-layer header
63
    NFULA_HWHEADER = 16,
64
    /// length of skbuff's MAC-layer header
65
    NFULA_HWLEN = 17,
66
  };
67
68
  /// @class NflogTlv
69
  /// A wrapper class for NFLOG TLV fields. This class does not create or modify TLVs related to NFLOG, but rather
70
  /// serves as a wrapper and provides useful methods for setting and retrieving data to/from them
71
  class NflogTlv
72
  {
73
  private:
74
    struct NflogTLVRawData
75
    {
76
      /// Record length in bytes
77
      uint16_t recordLen;
78
      /// Record type
79
      uint16_t recordType;
80
      /// Record value (variable size)
81
      uint8_t recordValue[];
82
    };
83
    NflogTLVRawData* m_Data;
84
85
  public:
86
    /// A c'tor for this class that gets a pointer to the option raw data (byte array)
87
    /// @param[in] recordRawData A pointer to the option raw data
88
    explicit NflogTlv(uint8_t* recordRawData)
89
2.19k
    {
90
2.19k
      assign(recordRawData);
91
2.19k
    }
92
93
    /// @return recordLen attribute in NflogTLVRawData
94
    size_t getTotalSize() const
95
7.28k
    {
96
      // as in
97
      // https://github.com/the-tcpdump-group/libpcap/blob/766b607d60d8038087b49fc4cf433dac3dcdb49c/pcap-util.c#L371-L374
98
7.28k
      return align<4>(m_Data->recordLen);
99
7.28k
    }
100
101
    /// Assign a pointer to the TLV record raw data (byte array)
102
    /// @param[in] recordRawData A pointer to the TLV record raw data
103
    void assign(uint8_t* recordRawData)
104
6.52k
    {
105
6.52k
      m_Data = reinterpret_cast<NflogTLVRawData*>(recordRawData);
106
6.52k
    }
107
108
    /// Check if a pointer can be assigned to the TLV record data
109
    /// @param[in] recordRawData A pointer to the TLV record raw data
110
    /// @param[in] tlvDataLen The size of the TLV record raw data
111
    /// * @return True if data is valid and can be assigned
112
    static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen)
113
2.19k
    {
114
2.19k
      return recordRawData != nullptr && tlvDataLen >= sizeof(NflogTLVRawData::recordLen);
115
2.19k
    }
116
117
    /// @return True if the TLV record raw data is nullptr, false otherwise
118
    bool isNull() const
119
6.55k
    {
120
6.55k
      return (m_Data == nullptr);
121
6.55k
    }
122
123
    /// @return The type field of the record (the 'T' in __Type__-Length-Value)
124
    uint16_t getType() const
125
900
    {
126
900
      return m_Data->recordType;
127
900
    }
128
129
    /// @return A pointer to the TLV record raw data byte stream
130
    uint8_t* getRecordBasePtr() const
131
5.72k
    {
132
5.72k
      return reinterpret_cast<uint8_t*>(m_Data);
133
5.72k
    }
134
135
    /// @return A pointer to the value of the record as byte array (the 'V' in Type-Length- __Value__)
136
    uint8_t* getValue() const
137
0
    {
138
0
      return m_Data->recordValue;
139
0
    }
140
  };
141
142
  /// @class NflogLayer
143
  /// Represents an NFLOG protocol layer
144
  class NflogLayer : public Layer
145
  {
146
  public:
147
    /// A constructor that creates the layer from an existing packet raw data
148
    /// @param[in] data A pointer to the raw data (will be casted to ether_header)
149
    /// @param[in] dataLen Size of the data in bytes
150
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
151
892
    NflogLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, nullptr, packet, NFLOG)
152
892
    {}
153
154
892
    ~NflogLayer() override = default;
155
156
    /// Get a pointer to the Nflog header.
157
    /// @return A pointer to the nflog_header
158
    nflog_header* getNflogHeader() const
159
0
    {
160
0
      return reinterpret_cast<nflog_header*>(m_Data);
161
0
    }
162
163
    /// Get address family of the packet. e.g. 2 for ipv4 and 10 for ipv6
164
    /// @return an unsigned char of address family
165
    uint8_t getFamily();
166
167
    /// Get Version number inside packet header
168
    /// The version field is 0 for the current version of the pseudo-header
169
    /// @return an unsigned char for version
170
    uint8_t getVersion();
171
172
    /// Get Resource Id in packet header
173
    /// On one netlink socket it's possible to listen to several nflog groups; the resource ID is the nflog group
174
    /// for the packet
175
    uint16_t getResourceId();
176
177
    /// Get a TLV object found with the input type. if no tlv is found, the internal value of the object will set to
178
    /// nullptr
179
    /// @param[in] type type of tlv by using enum class defined as NflogTlvType
180
    /// @return NflogTlv obtained by type
181
    NflogTlv getTlvByType(NflogTlvType type) const;
182
183
    // implement abstract methods
184
185
    /// Currently identifies the following next layers: IPv4Layer, IPv6Layer using address family
186
    /// Otherwise sets PayloadLayer
187
    void parseNextLayer() override;
188
189
    /// @return Size of nflog_header
190
    size_t getHeaderLen() const override;
191
192
    /// Does nothing for this layer
193
446
    void computeCalculateFields() override {};
194
195
    std::string toString() const override;
196
197
    OsiModelLayer getOsiModelLayer() const override
198
446
    {
199
446
      return OsiModelDataLinkLayer;
200
446
    }
201
202
    /// A static method that validates the input data
203
    /// @param[in] data The pointer to the beginning of a byte stream of an NFLOG packet
204
    /// @param[in] dataLen The length of the byte stream
205
    /// @return True if the data is valid and can represent an NFLOG packet
206
    static bool isDataValid(const uint8_t* data, size_t dataLen);
207
208
  private:
209
    uint8_t* getTlvsBasePtr() const
210
1.59k
    {
211
1.59k
      return m_Data + sizeof(nflog_header);
212
1.59k
    }
213
214
    TLVRecordReader<NflogTlv> m_TlvReader;
215
  };
216
217
}  // namespace pcpp