Coverage Report

Created: 2026-07-16 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/RadiusLayer.cpp
Line
Count
Source
1
0
#define LOG_MODULE PacketLogModuleRadiusLayer
2
#include "RadiusLayer.h"
3
#include "Logger.h"
4
#include "GeneralUtils.h"
5
#include <sstream>
6
#include "EndianPortable.h"
7
8
namespace pcpp
9
{
10
11
  RadiusAttribute RadiusAttributeBuilder::build() const
12
0
  {
13
0
    size_t recSize = m_RecValueLen + 2;
14
0
    uint8_t* recordBuffer = new uint8_t[recSize];
15
0
    memset(recordBuffer, 0, recSize);
16
0
    recordBuffer[0] = static_cast<uint8_t>(m_RecType);
17
0
    recordBuffer[1] = static_cast<uint8_t>(recSize);
18
0
    if (m_RecValueLen > 0)
19
0
      memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen);
20
21
0
    return RadiusAttribute(recordBuffer);
22
0
  }
23
24
  RadiusLayer::RadiusLayer(uint8_t code, uint8_t id, const uint8_t* authenticator, uint8_t authenticatorArrSize)
25
0
  {
26
0
    allocData(sizeof(radius_header));
27
0
    m_Protocol = Radius;
28
29
0
    radius_header* hdr = getRadiusHeader();
30
0
    hdr->code = code;
31
0
    hdr->id = id;
32
0
    hdr->length = htobe16(sizeof(radius_header));
33
0
    if (authenticatorArrSize == 0 || authenticator == nullptr)
34
0
      return;
35
0
    if (authenticatorArrSize > 16)
36
0
      authenticatorArrSize = 16;
37
0
    memcpy(hdr->authenticator, authenticator, authenticatorArrSize);
38
0
  }
39
40
  RadiusLayer::RadiusLayer(uint8_t code, uint8_t id, const std::string& authenticator)
41
0
  {
42
0
    allocData(sizeof(radius_header));
43
0
    m_Protocol = Radius;
44
45
0
    radius_header* hdr = getRadiusHeader();
46
0
    hdr->code = code;
47
0
    hdr->id = id;
48
0
    hdr->length = htobe16(sizeof(radius_header));
49
0
    setAuthenticatorValue(authenticator);
50
0
  }
51
52
  RadiusAttribute RadiusLayer::addAttrAt(const RadiusAttributeBuilder& attrBuilder, int offset)
53
0
  {
54
0
    RadiusAttribute newAttr = attrBuilder.build();
55
0
    if (newAttr.isNull())
56
0
    {
57
0
      PCPP_LOG_ERROR("Cannot build new attribute of type " << (int)newAttr.getType());
58
0
      return newAttr;
59
0
    }
60
61
0
    size_t sizeToExtend = newAttr.getTotalSize();
62
0
    if (!extendLayer(offset, sizeToExtend))
63
0
    {
64
0
      PCPP_LOG_ERROR("Could not extend RadiusLayer in [" << newAttr.getTotalSize() << "] bytes");
65
0
      newAttr.purgeRecordData();
66
0
      return RadiusAttribute(nullptr);
67
0
    }
68
69
0
    memcpy(m_Data + offset, newAttr.getRecordBasePtr(), newAttr.getTotalSize());
70
71
0
    uint8_t* newAttrPtr = m_Data + offset;
72
73
0
    m_AttributeReader.changeTLVRecordCount(1);
74
75
0
    newAttr.purgeRecordData();
76
77
0
    getRadiusHeader()->length = htobe16(m_DataLen);
78
79
0
    return RadiusAttribute(newAttrPtr);
80
0
  }
81
82
  std::string RadiusLayer::getAuthenticatorValue() const
83
0
  {
84
0
    return byteArrayToHexString(getRadiusHeader()->authenticator, 16);
85
0
  }
86
87
  void RadiusLayer::setAuthenticatorValue(const std::string& authValue)
88
0
  {
89
0
    hexStringToByteArray(authValue, getRadiusHeader()->authenticator, 16);
90
0
  }
91
92
  std::string RadiusLayer::getRadiusMessageString(uint8_t radiusMessageCode)
93
9.14k
  {
94
9.14k
    switch (radiusMessageCode)
95
9.14k
    {
96
2.45k
    case 1:
97
2.45k
      return "Access-Request";
98
582
    case 2:
99
582
      return "Access-Accept";
100
656
    case 3:
101
656
      return "Access-Reject";
102
198
    case 4:
103
198
      return "Accounting-Request";
104
86
    case 5:
105
86
      return "Accounting-Response";
106
1.45k
    case 11:
107
1.45k
      return "Access-Challenge";
108
0
    case 12:
109
0
      return "Status-Server";
110
0
    case 13:
111
0
      return "Status-Client";
112
1.93k
    case 40:
113
1.93k
      return "Disconnect-Request";
114
1.23k
    case 41:
115
1.23k
      return "Disconnect-ACK";
116
186
    case 42:
117
186
      return "Disconnect-NAK";
118
0
    case 43:
119
0
      return "CoA-Request";
120
114
    case 44:
121
114
      return "CoA-ACK";
122
0
    case 45:
123
0
      return "CoA-NAK";
124
32
    case 255:
125
32
      return "Reserved";
126
214
    default:
127
214
      return "Unknown";
128
9.14k
    }
129
9.14k
  }
130
131
  size_t RadiusLayer::getHeaderLen() const
132
4.57k
  {
133
4.57k
    uint16_t len = be16toh(getRadiusHeader()->length);
134
4.57k
    if (len > m_DataLen)
135
0
      return m_DataLen;
136
137
4.57k
    return len;
138
4.57k
  }
139
140
  void RadiusLayer::computeCalculateFields()
141
4.57k
  {
142
4.57k
    getRadiusHeader()->length = htobe16(m_DataLen);
143
4.57k
  }
144
145
  std::string RadiusLayer::toString() const
146
9.14k
  {
147
9.14k
    std::ostringstream str;
148
9.14k
    str << "RADIUS Layer, " << RadiusLayer::getRadiusMessageString(getRadiusHeader()->code) << "("
149
9.14k
        << (int)getRadiusHeader()->code
150
9.14k
        << "), "
151
9.14k
           "Id="
152
9.14k
        << (int)getRadiusHeader()->id << ", "
153
9.14k
        << "Length=" << be16toh(getRadiusHeader()->length);
154
155
9.14k
    return str.str();
156
9.14k
  }
157
158
  RadiusAttribute RadiusLayer::getFirstAttribute() const
159
0
  {
160
0
    return m_AttributeReader.getFirstTLVRecord(getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header));
161
0
  }
162
163
  RadiusAttribute RadiusLayer::getNextAttribute(RadiusAttribute& attr) const
164
0
  {
165
0
    return m_AttributeReader.getNextTLVRecord(attr, getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header));
166
0
  }
167
168
  RadiusAttribute RadiusLayer::getAttribute(uint8_t attributeType) const
169
0
  {
170
0
    return m_AttributeReader.getTLVRecord(attributeType, getAttributesBasePtr(),
171
0
                                          getHeaderLen() - sizeof(radius_header));
172
0
  }
173
174
  size_t RadiusLayer::getAttributeCount() const
175
0
  {
176
0
    return m_AttributeReader.getTLVRecordCount(getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header));
177
0
  }
178
179
  RadiusAttribute RadiusLayer::addAttribute(const RadiusAttributeBuilder& attrBuilder)
180
0
  {
181
0
    int offset = getHeaderLen();
182
0
    return addAttrAt(attrBuilder, offset);
183
0
  }
184
185
  RadiusAttribute RadiusLayer::addAttributeAfter(const RadiusAttributeBuilder& attrBuilder, uint8_t prevAttrType)
186
0
  {
187
0
    int offset = 0;
188
189
0
    RadiusAttribute prevAttr = getAttribute(prevAttrType);
190
191
0
    if (prevAttr.isNull())
192
0
    {
193
0
      offset = getHeaderLen();
194
0
    }
195
0
    else
196
0
    {
197
0
      offset = prevAttr.getRecordBasePtr() + prevAttr.getTotalSize() - m_Data;
198
0
    }
199
200
0
    return addAttrAt(attrBuilder, offset);
201
0
  }
202
203
  bool RadiusLayer::removeAttribute(uint8_t attrType)
204
0
  {
205
0
    RadiusAttribute attrToRemove = getAttribute(attrType);
206
0
    if (attrToRemove.isNull())
207
0
    {
208
0
      return false;
209
0
    }
210
211
0
    int offset = attrToRemove.getRecordBasePtr() - m_Data;
212
213
0
    if (!shortenLayer(offset, attrToRemove.getTotalSize()))
214
0
    {
215
0
      return false;
216
0
    }
217
218
0
    m_AttributeReader.changeTLVRecordCount(-1);
219
0
    getRadiusHeader()->length = htobe16(m_DataLen);
220
221
0
    return true;
222
0
  }
223
224
  bool RadiusLayer::removeAllAttributes()
225
0
  {
226
0
    int offset = sizeof(radius_header);
227
228
0
    if (!shortenLayer(offset, getHeaderLen() - offset))
229
0
      return false;
230
231
0
    m_AttributeReader.changeTLVRecordCount(0 - getAttributeCount());
232
233
0
    getRadiusHeader()->length = htobe16(m_DataLen);
234
235
0
    return true;
236
0
  }
237
238
  bool RadiusLayer::isDataValid(const uint8_t* udpData, size_t udpDataLen)
239
29.9k
  {
240
29.9k
    if (udpData != nullptr && udpDataLen >= sizeof(radius_header))
241
29.7k
    {
242
29.7k
      const radius_header* radHdr = reinterpret_cast<const radius_header*>(udpData);
243
29.7k
      size_t radLen = be16toh(radHdr->length);
244
29.7k
      return radLen >= sizeof(radius_header) && radLen <= udpDataLen;
245
29.7k
    }
246
140
    return false;
247
29.9k
  }
248
249
}  // namespace pcpp