Coverage Report

Created: 2023-01-17 06:15

/src/PcapPlusPlus/Packet++/src/DhcpLayer.cpp
Line
Count
Source (jump to first uncovered line)
1
0
#define LOG_MODULE PacketLogModuleDhcpLayer
2
3
#include "DhcpLayer.h"
4
#include "Logger.h"
5
6
namespace pcpp
7
{
8
9
0
#define DHCP_MAGIC_NUMBER 0x63538263
10
11
12
DhcpOption DhcpOptionBuilder::build() const
13
0
{
14
0
  size_t recSize = 2 * sizeof(uint8_t) + m_RecValueLen;
15
0
  uint8_t recType = static_cast<uint8_t>(m_RecType);
16
17
0
  if ((recType == DHCPOPT_END || recType == DHCPOPT_PAD))
18
0
  {
19
0
    if (m_RecValueLen != 0)
20
0
    {
21
0
      PCPP_LOG_ERROR("Can't set DHCP END option or DHCP PAD option with size different than 0, tried to set size " << (int)m_RecValueLen);
22
0
      return DhcpOption(NULL);
23
0
    }
24
25
0
    recSize = sizeof(uint8_t);
26
0
  }
27
28
0
  uint8_t* recordBuffer = new uint8_t[recSize];
29
0
  memset(recordBuffer, 0, recSize);
30
0
  recordBuffer[0] = recType;
31
0
  if (recSize > 1)
32
0
  {
33
0
    recordBuffer[1] = static_cast<uint8_t>(m_RecValueLen);
34
0
    if (m_RecValue != NULL)
35
0
      memcpy(recordBuffer+2, m_RecValue, m_RecValueLen);
36
0
    else
37
0
      memset(recordBuffer+2, 0, m_RecValueLen);
38
0
  }
39
40
0
  return DhcpOption(recordBuffer);
41
0
}
42
43
DhcpLayer::DhcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet)
44
448
{
45
448
   m_Protocol = DHCP;
46
448
}
47
48
void DhcpLayer::initDhcpLayer(size_t numOfBytesToAllocate)
49
0
{
50
0
  m_DataLen = numOfBytesToAllocate;
51
0
  m_Data = new uint8_t[numOfBytesToAllocate];
52
0
  memset(m_Data, 0, numOfBytesToAllocate);
53
0
  m_Protocol = DHCP;
54
0
}
55
56
DhcpLayer::DhcpLayer() : Layer()
57
0
{
58
0
  initDhcpLayer(sizeof(dhcp_header));
59
0
}
60
61
DhcpLayer::DhcpLayer(DhcpMessageType msgType, const MacAddress& clientMacAddr) : Layer()
62
0
{
63
0
  initDhcpLayer(sizeof(dhcp_header) + 4*sizeof(uint8_t));
64
65
0
  setClientHardwareAddress(clientMacAddr);
66
67
0
  uint8_t* msgTypeOptionPtr = m_Data + sizeof(dhcp_header);
68
0
  msgTypeOptionPtr[0] = (uint8_t)DHCPOPT_DHCP_MESSAGE_TYPE; // option code
69
0
  msgTypeOptionPtr[1] = 1; // option len
70
0
  msgTypeOptionPtr[2] = (uint8_t)msgType; // option data - message type
71
72
0
  msgTypeOptionPtr[3] =  (uint8_t)DHCPOPT_END;
73
0
}
74
75
MacAddress DhcpLayer::getClientHardwareAddress() const
76
0
{
77
0
  dhcp_header* hdr = getDhcpHeader();
78
0
  if (hdr != NULL && hdr->hardwareType == 1 && hdr->hardwareAddressLength == 6)
79
0
    return MacAddress(hdr->clientHardwareAddress);
80
81
0
  PCPP_LOG_DEBUG("Hardware type isn't Ethernet or hardware addr len != 6, returning MacAddress:Zero");
82
83
0
  return MacAddress::Zero;
84
0
}
85
86
void DhcpLayer::setClientHardwareAddress(const MacAddress& addr)
87
0
{
88
0
  dhcp_header* hdr = getDhcpHeader();
89
0
  hdr->hardwareType = 1; // Ethernet
90
0
  hdr->hardwareAddressLength = 6; // MAC address length
91
0
  addr.copyTo(hdr->clientHardwareAddress);
92
0
}
93
94
void DhcpLayer::computeCalculateFields()
95
0
{
96
0
  dhcp_header* hdr = getDhcpHeader();
97
98
0
  hdr->magicNumber = DHCP_MAGIC_NUMBER;
99
100
0
  DhcpMessageType msgType = getMessageType();
101
0
  switch(msgType)
102
0
  {
103
0
  case DHCP_DISCOVER:
104
0
  case DHCP_REQUEST:
105
0
  case DHCP_DECLINE:
106
0
  case DHCP_RELEASE:
107
0
  case DHCP_INFORM:
108
0
  case DHCP_UNKNOWN_MSG_TYPE:
109
0
    hdr->opCode = DHCP_BOOTREQUEST;
110
0
    break;
111
0
  case DHCP_OFFER:
112
0
  case DHCP_ACK:
113
0
  case DHCP_NAK:
114
0
    hdr->opCode = DHCP_BOOTREPLY;
115
0
    break;
116
0
  default:
117
0
    break;
118
0
  }
119
120
0
  hdr->hardwareType = 1; //Ethernet
121
0
  hdr->hardwareAddressLength = 6; // MAC address length
122
0
}
123
124
std::string DhcpLayer::toString() const
125
0
{
126
0
  std::string msgType = "Unknown";
127
0
  switch (getMessageType())
128
0
  {
129
0
  case DHCP_DISCOVER:
130
0
  {
131
0
    msgType = "Discover";
132
0
    break;
133
0
  }
134
0
  case DHCP_OFFER:
135
0
  {
136
0
    msgType = "Offer";
137
0
    break;
138
0
  }
139
0
  case DHCP_REQUEST:
140
0
  {
141
0
    msgType = "Request";
142
0
    break;
143
0
  }
144
0
  case DHCP_DECLINE:
145
0
  {
146
0
    msgType = "Decline";
147
0
    break;
148
0
  }
149
0
  case DHCP_ACK:
150
0
  {
151
0
    msgType = "Acknowledge";
152
0
    break;
153
0
  }
154
0
  case DHCP_NAK:
155
0
  {
156
0
    msgType = "Negative Acknowledge";
157
0
    break;
158
0
  }
159
0
  case DHCP_RELEASE:
160
0
  {
161
0
    msgType = "Release";
162
0
    break;
163
0
  }
164
0
  case DHCP_INFORM:
165
0
  {
166
0
    msgType = "Inform";
167
0
    break;
168
0
  }
169
0
  default:
170
0
    break;
171
172
0
  }
173
174
0
  return "DHCP layer (" + msgType + ")";
175
0
}
176
177
DhcpMessageType DhcpLayer::getMessageType() const
178
0
{
179
0
  DhcpOption opt = getOptionData(DHCPOPT_DHCP_MESSAGE_TYPE);
180
0
  if (opt.isNull())
181
0
    return DHCP_UNKNOWN_MSG_TYPE;
182
183
0
  return (DhcpMessageType)opt.getValueAs<uint8_t>();
184
0
}
185
186
bool DhcpLayer::setMessageType(DhcpMessageType msgType)
187
0
{
188
0
  if (msgType == DHCP_UNKNOWN_MSG_TYPE)
189
0
    return false;
190
191
0
  DhcpOption opt = getOptionData(DHCPOPT_DHCP_MESSAGE_TYPE);
192
0
  if (opt.isNull())
193
0
  {
194
0
    opt = addOptionAfter(DhcpOptionBuilder(DHCPOPT_DHCP_MESSAGE_TYPE, (uint8_t)msgType), DHCPOPT_UNKNOWN);
195
0
    if (opt.isNull())
196
0
      return false;
197
0
  }
198
199
0
  opt.setValue<uint8_t>((uint8_t)msgType);
200
0
  return true;
201
0
}
202
203
DhcpOption DhcpLayer::getOptionData(DhcpOptionTypes option) const
204
0
{
205
0
  return m_OptionReader.getTLVRecord((uint8_t)option, getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header));
206
0
}
207
208
DhcpOption DhcpLayer::getFirstOptionData() const
209
0
{
210
0
  return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header));
211
0
}
212
213
DhcpOption DhcpLayer::getNextOptionData(DhcpOption dhcpOption) const
214
0
{
215
0
  return m_OptionReader.getNextTLVRecord(dhcpOption, getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header));
216
0
}
217
218
size_t DhcpLayer::getOptionsCount() const
219
0
{
220
0
  return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header));
221
0
}
222
223
DhcpOption DhcpLayer::addOptionAt(const DhcpOptionBuilder& optionBuilder, int offset)
224
0
{
225
0
  DhcpOption newOpt = optionBuilder.build();
226
227
0
  if (newOpt.isNull())
228
0
  {
229
0
    PCPP_LOG_ERROR("Cannot build new option of type " << (int)newOpt.getType());
230
0
    return DhcpOption(NULL);
231
0
  }
232
233
0
  size_t sizeToExtend = newOpt.getTotalSize();
234
235
0
  if (!extendLayer(offset, sizeToExtend))
236
0
  {
237
0
    PCPP_LOG_ERROR("Could not extend DhcpLayer in [" << newOpt.getTotalSize() << "] bytes");
238
0
    return DhcpOption(NULL);
239
0
  }
240
241
0
  memcpy(m_Data + offset, newOpt.getRecordBasePtr(), newOpt.getTotalSize());
242
243
0
  uint8_t* newOptPtr = m_Data + offset;
244
245
0
  m_OptionReader.changeTLVRecordCount(1);
246
247
0
  newOpt.purgeRecordData();
248
249
0
  return DhcpOption(newOptPtr);
250
0
}
251
252
DhcpOption DhcpLayer::addOption(const DhcpOptionBuilder& optionBuilder)
253
0
{
254
0
  int offset = 0;
255
0
  DhcpOption endOpt = getOptionData(DHCPOPT_END);
256
0
  if (!endOpt.isNull())
257
0
    offset = endOpt.getRecordBasePtr() - m_Data;
258
0
  else
259
0
    offset = getHeaderLen();
260
261
0
  return addOptionAt(optionBuilder, offset);
262
0
}
263
264
DhcpOption DhcpLayer::addOptionAfter(const DhcpOptionBuilder& optionBuilder, DhcpOptionTypes prevOption)
265
0
{
266
0
  int offset = 0;
267
268
0
  DhcpOption prevOpt = getOptionData(prevOption);
269
270
0
  if (prevOpt.isNull())
271
0
  {
272
0
    offset = sizeof(dhcp_header);
273
0
  }
274
0
  else
275
0
  {
276
0
    offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data;
277
0
  }
278
279
0
  return addOptionAt(optionBuilder, offset);
280
0
}
281
282
bool DhcpLayer::removeOption(DhcpOptionTypes optionType)
283
0
{
284
0
  DhcpOption optToRemove = getOptionData(optionType);
285
0
  if (optToRemove.isNull())
286
0
  {
287
0
    return false;
288
0
  }
289
290
0
  int offset = optToRemove.getRecordBasePtr() - m_Data;
291
292
0
  if (!shortenLayer(offset, optToRemove.getTotalSize()))
293
0
  {
294
0
    return false;
295
0
  }
296
297
0
  m_OptionReader.changeTLVRecordCount(-1);
298
0
  return true;
299
0
}
300
301
bool DhcpLayer::removeAllOptions()
302
0
{
303
0
  int offset = sizeof(dhcp_header);
304
305
0
  if (!shortenLayer(offset, getHeaderLen()-offset))
306
0
    return false;
307
308
0
  m_OptionReader.changeTLVRecordCount(0-getOptionsCount());
309
0
  return true;
310
0
}
311
312
313
}