Coverage Report

Created: 2026-03-31 07:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/SomeIpSdLayer.cpp
Line
Count
Source
1
#define LOG_MODULE PacketLogModuleSomeIpSdLayer
2
3
#include "SomeIpSdLayer.h"
4
#include "EndianPortable.h"
5
#include <algorithm>
6
#include <sstream>
7
#include <stdexcept>
8
9
namespace pcpp
10
{
11
  // -------- Class SomeIpSdOption -----------------
12
13
  SomeIpSdOption::~SomeIpSdOption()
14
5.26k
  {
15
5.26k
    if (m_ShadowData != nullptr)
16
0
      delete[] m_ShadowData;
17
5.26k
  }
18
19
  SomeIpSdOption::OptionType SomeIpSdOption::getType() const
20
2.90k
  {
21
2.90k
    return static_cast<OptionType>(getSomeIpSdOptionHeader()->type);
22
2.90k
  }
23
24
  uint8_t* SomeIpSdOption::getDataPtr() const
25
8.65k
  {
26
8.65k
    if (m_DataContainer != nullptr)
27
8.65k
      return m_DataContainer->getDataPtr(m_Offset);
28
29
0
    return m_ShadowData;
30
8.65k
  }
31
32
  SomeIpSdOption::someipsdhdroptionsbase* SomeIpSdOption::getSomeIpSdOptionHeader() const
33
3.25k
  {
34
3.25k
    return (someipsdhdroptionsbase*)getDataPtr();
35
3.25k
  }
36
37
  void SomeIpSdOption::initStdFields(OptionType type)
38
0
  {
39
0
    someipsdhdroptionsbase* optionHdr = getSomeIpSdOptionHeader();
40
41
0
    optionHdr->type = static_cast<uint8_t>(type);
42
    // Length field is excluding length field itself and uint8_t type field
43
0
    optionHdr->length = htobe16((uint16_t)(m_DataLen - sizeof(optionHdr->length) - sizeof(optionHdr->type)));
44
0
  }
45
46
  // -------- Class SomeIpSdIPv4Option -----------------
47
48
  SomeIpSdIPv4Option::SomeIpSdIPv4Option(IPv4OptionType type, IPv4Address ipAddress, uint16_t port,
49
                                         SomeIpSdProtocolType l4Protocol)
50
0
  {
51
0
    m_DataLen = sizeof(someipsdhdroptionsipv4);
52
0
    m_ShadowData = new uint8_t[m_DataLen];
53
0
    memset(m_ShadowData, 0, m_DataLen);
54
55
0
    switch (type)
56
0
    {
57
0
    case IPv4OptionType::IPv4Endpoint:
58
0
      initStdFields(OptionType::IPv4Endpoint);
59
0
      break;
60
0
    case IPv4OptionType::IPv4Multicast:
61
0
      initStdFields(OptionType::IPv4Multicast);
62
0
      break;
63
0
    case IPv4OptionType::IPv4SdEndpoint:
64
0
      initStdFields(OptionType::IPv4SdEndpoint);
65
0
      break;
66
0
    }
67
68
0
    someipsdhdroptionsipv4* hdr = (someipsdhdroptionsipv4*)getDataPtr();
69
0
    hdr->ipv4Address = ipAddress.toInt();
70
0
    hdr->portNumber = htobe16(port);
71
0
    hdr->l4Protocol = l4Protocol;
72
0
  }
73
74
  SomeIpSdIPv4Option::SomeIpSdIPv4Option(const IDataContainer* dataContainer, size_t offset)
75
1.99k
      : SomeIpSdOption(dataContainer, offset)
76
1.99k
  {
77
1.99k
    m_DataLen = sizeof(someipsdhdroptionsipv4);
78
1.99k
  }
79
80
  IPv4Address SomeIpSdIPv4Option::getIpAddress() const
81
1.02k
  {
82
1.02k
    someipsdhdroptionsipv4* hdr = (someipsdhdroptionsipv4*)getDataPtr();
83
1.02k
    IPv4Address ipAddr(hdr->ipv4Address);
84
85
1.02k
    return ipAddr;
86
1.02k
  }
87
88
  uint16_t SomeIpSdIPv4Option::getPort() const
89
1.02k
  {
90
1.02k
    someipsdhdroptionsipv4* hdr = (someipsdhdroptionsipv4*)getDataPtr();
91
1.02k
    return be16toh(hdr->portNumber);
92
1.02k
  }
93
94
  SomeIpSdProtocolType SomeIpSdIPv4Option::getProtocol() const
95
1.02k
  {
96
1.02k
    someipsdhdroptionsipv4* hdr = (someipsdhdroptionsipv4*)getDataPtr();
97
1.02k
    return hdr->l4Protocol;
98
1.02k
  }
99
100
  // -------- Class SomeIpSdIPv6Option -----------------
101
102
  SomeIpSdIPv6Option::SomeIpSdIPv6Option(IPv6OptionType type, IPv6Address ipAddress, uint16_t port,
103
                                         SomeIpSdProtocolType l4Protocol)
104
0
  {
105
0
    m_DataLen = sizeof(someipsdhdroptionsipv6);
106
0
    m_ShadowData = new uint8_t[m_DataLen];
107
0
    memset(m_ShadowData, 0, m_DataLen);
108
109
0
    switch (type)
110
0
    {
111
0
    case IPv6OptionType::IPv6Endpoint:
112
0
      initStdFields(OptionType::IPv6Endpoint);
113
0
      break;
114
0
    case IPv6OptionType::IPv6Multicast:
115
0
      initStdFields(OptionType::IPv6Multicast);
116
0
      break;
117
0
    case IPv6OptionType::IPv6SdEndpoint:
118
0
      initStdFields(OptionType::IPv6SdEndpoint);
119
0
      break;
120
0
    }
121
122
0
    someipsdhdroptionsipv6* hdr = (someipsdhdroptionsipv6*)getDataPtr();
123
0
    std::memcpy(hdr->ipv6Address, ipAddress.toBytes(), 16);
124
0
    hdr->portNumber = htobe16(port);
125
0
    hdr->l4Protocol = l4Protocol;
126
0
  }
127
128
  SomeIpSdIPv6Option::SomeIpSdIPv6Option(const IDataContainer* dataContainer, size_t offset)
129
1.31k
      : SomeIpSdOption(dataContainer, offset)
130
1.31k
  {
131
1.31k
    m_DataLen = sizeof(someipsdhdroptionsipv6);
132
1.31k
  }
133
134
  IPv6Address SomeIpSdIPv6Option::getIpAddress() const
135
779
  {
136
779
    someipsdhdroptionsipv6* hdr = (someipsdhdroptionsipv6*)getDataPtr();
137
779
    IPv6Address ipAddr(hdr->ipv6Address);
138
139
779
    return ipAddr;
140
779
  }
141
142
  uint16_t SomeIpSdIPv6Option::getPort() const
143
779
  {
144
779
    someipsdhdroptionsipv6* hdr = (someipsdhdroptionsipv6*)getDataPtr();
145
779
    return be16toh(hdr->portNumber);
146
779
  }
147
148
  SomeIpSdProtocolType SomeIpSdIPv6Option::getProtocol() const
149
779
  {
150
779
    someipsdhdroptionsipv6* hdr = (someipsdhdroptionsipv6*)getDataPtr();
151
779
    return hdr->l4Protocol;
152
779
  }
153
154
  // -------- Class SomeIpSdConfigurationOption -----------------
155
156
  SomeIpSdConfigurationOption::SomeIpSdConfigurationOption(const std::string& configurationString)
157
0
  {
158
0
    m_DataLen = configurationString.length() + sizeof(someipsdhdroptionsbase);
159
0
    m_ShadowData = new uint8_t[m_DataLen];
160
0
    memset(m_ShadowData, 0, m_DataLen);
161
162
0
    initStdFields(OptionType::ConfigurationString);
163
0
    std::memcpy(getDataPtr() + sizeof(someipsdhdroptionsbase), configurationString.c_str(),
164
0
                configurationString.length());
165
0
  }
166
167
  SomeIpSdConfigurationOption::SomeIpSdConfigurationOption(const IDataContainer* dataContainer, size_t offset)
168
355
      : SomeIpSdOption(dataContainer, offset)
169
355
  {
170
355
    m_DataLen = sizeof(someipsdhdroptionsbase) - 1 + be16toh(getSomeIpSdOptionHeader()->length);
171
355
  }
172
173
  std::string SomeIpSdConfigurationOption::getConfigurationString() const
174
0
  {
175
0
    return std::string((char*)getDataPtr() + sizeof(someipsdhdroptionsbase),
176
0
                       be16toh(getSomeIpSdOptionHeader()->length) - 1);
177
0
  }
178
179
  // -------- Class SomeIpSdLoadBalancingOption -----------------
180
181
  SomeIpSdLoadBalancingOption::SomeIpSdLoadBalancingOption(uint16_t priority, uint16_t weight)
182
0
  {
183
0
    m_DataLen = sizeof(someipsdhdroptionsload);
184
0
    m_ShadowData = new uint8_t[m_DataLen];
185
0
    memset(m_ShadowData, 0, m_DataLen);
186
187
0
    initStdFields(OptionType::LoadBalancing);
188
189
0
    someipsdhdroptionsload* hdr = (someipsdhdroptionsload*)getDataPtr();
190
0
    hdr->priority = htobe16(priority);
191
0
    hdr->weight = htobe16(weight);
192
0
  }
193
194
  SomeIpSdLoadBalancingOption::SomeIpSdLoadBalancingOption(const IDataContainer* dataContainer, size_t offset)
195
1.59k
      : SomeIpSdOption(dataContainer, offset)
196
1.59k
  {
197
1.59k
    m_DataLen = sizeof(someipsdhdroptionsload);
198
1.59k
  }
199
200
  uint16_t SomeIpSdLoadBalancingOption::getPriority() const
201
0
  {
202
0
    someipsdhdroptionsload* hdr = (someipsdhdroptionsload*)getDataPtr();
203
0
    return be16toh(hdr->priority);
204
0
  }
205
206
  uint16_t SomeIpSdLoadBalancingOption::getWeight() const
207
0
  {
208
0
    someipsdhdroptionsload* hdr = (someipsdhdroptionsload*)getDataPtr();
209
0
    return be16toh(hdr->weight);
210
0
  }
211
212
  // -------- Class SomeIpSdEntry -----------------
213
214
  SomeIpSdEntry::SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion,
215
                               uint32_t TTL, uint32_t minorVersion)
216
0
  {
217
0
    initStdFields(type, serviceID, instanceID, majorVersion, TTL);
218
0
    setMinorVersion(minorVersion);
219
0
  }
220
221
  SomeIpSdEntry::SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion,
222
                               uint32_t TTL, uint8_t counter, uint16_t eventGroupID)
223
0
  {
224
0
    initStdFields(type, serviceID, instanceID, majorVersion, TTL);
225
0
    setCounter(counter);
226
0
    setEventgroupId(eventGroupID);
227
0
  }
228
229
  SomeIpSdEntry::SomeIpSdEntry(const SomeIpSdLayer* pSomeIpSdLayer, size_t offset)
230
3.60k
      : m_Layer(pSomeIpSdLayer), m_Offset(offset), m_ShadowData(nullptr)
231
3.60k
  {
232
3.60k
    EntryType entryType;
233
234
3.60k
    someipsdhdrentry* hdr = getSomeIpSdEntryHeader();
235
3.60k
    TypeInternal internalType = static_cast<TypeInternal>(hdr->type);
236
3.60k
    auto ttl = getTtl();
237
238
3.60k
    switch (internalType)
239
3.60k
    {
240
354
    case SomeIpSdEntry::TypeInternal::FindService_Internal:
241
354
      entryType = SomeIpSdEntry::EntryType::FindService;
242
354
      break;
243
2.21k
    case SomeIpSdEntry::TypeInternal::OfferService_Internal:
244
2.21k
      if (ttl == 0)
245
320
      {
246
320
        entryType = EntryType::StopOfferService;
247
320
      }
248
1.89k
      else
249
1.89k
      {
250
1.89k
        entryType = EntryType::OfferService;
251
1.89k
      }
252
2.21k
      break;
253
14
    case SomeIpSdEntry::TypeInternal::SubscribeEventgroup_Internal:
254
14
      if (ttl == 0)
255
1
      {
256
1
        entryType = EntryType::StopSubscribeEventgroup;
257
1
      }
258
13
      else
259
13
      {
260
13
        entryType = EntryType::SubscribeEventgroup;
261
13
      }
262
14
      break;
263
385
    case SomeIpSdEntry::TypeInternal::SubscribeEventgroupAck_Internal:
264
385
      if (ttl == 0)
265
173
      {
266
173
        entryType = EntryType::SubscribeEventgroupNack;
267
173
      }
268
212
      else
269
212
      {
270
212
        entryType = EntryType::SubscribeEventgroupAck;
271
212
      }
272
385
      break;
273
640
    default:
274
640
      entryType = EntryType::UnknownEntryType;
275
640
      break;
276
3.60k
    }
277
278
3.60k
    m_EntryType = entryType;
279
3.60k
  }
280
281
  SomeIpSdEntry::~SomeIpSdEntry()
282
3.60k
  {
283
3.60k
    if (m_ShadowData != nullptr)
284
0
      delete[] m_ShadowData;
285
3.60k
  }
286
287
  uint8_t* SomeIpSdEntry::getDataPtr() const
288
32.4k
  {
289
32.4k
    if (m_Layer != nullptr)
290
32.4k
      return m_Layer->getDataPtr(m_Offset);
291
292
0
    return m_ShadowData;
293
32.4k
  }
294
295
  SomeIpSdEntry::someipsdhdrentry* SomeIpSdEntry::getSomeIpSdEntryHeader() const
296
32.4k
  {
297
32.4k
    return (someipsdhdrentry*)getDataPtr();
298
32.4k
  }
299
300
  uint32_t SomeIpSdEntry::getNumOptions() const
301
3.60k
  {
302
3.60k
    auto* hdr = getSomeIpSdEntryHeader();
303
3.60k
    return hdr->nrOpt1 + hdr->nrOpt2;
304
3.60k
  }
305
306
  uint16_t SomeIpSdEntry::getServiceId() const
307
3.60k
  {
308
3.60k
    return be16toh(getSomeIpSdEntryHeader()->serviceID);
309
3.60k
  }
310
311
  void SomeIpSdEntry::setServiceId(uint16_t serviceId)
312
0
  {
313
0
    getSomeIpSdEntryHeader()->serviceID = htobe16(serviceId);
314
0
  }
315
316
  uint16_t SomeIpSdEntry::getInstanceId() const
317
3.60k
  {
318
3.60k
    return be16toh(getSomeIpSdEntryHeader()->instanceID);
319
3.60k
  }
320
321
  void SomeIpSdEntry::setInstanceId(uint16_t instanceId)
322
0
  {
323
0
    getSomeIpSdEntryHeader()->instanceID = htobe16(instanceId);
324
0
  }
325
326
  uint8_t SomeIpSdEntry::getMajorVersion() const
327
3.60k
  {
328
3.60k
    return (be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & ~SOMEIPSD_HDR_ENTRY_MASK_TTL) >> 24;
329
3.60k
  }
330
331
  void SomeIpSdEntry::setMajorVersion(uint8_t majorVersion)
332
0
  {
333
0
    someipsdhdrentry* hdr = getSomeIpSdEntryHeader();
334
0
    uint32_t val = (majorVersion << 24) | (be32toh(hdr->majorVersion_ttl) & SOMEIPSD_HDR_ENTRY_MASK_TTL);
335
0
    hdr->majorVersion_ttl = htobe32(val);
336
0
  }
337
338
  uint32_t SomeIpSdEntry::getTtl() const
339
3.60k
  {
340
3.60k
    return be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & SOMEIPSD_HDR_ENTRY_MASK_TTL;
341
3.60k
  }
342
343
  void SomeIpSdEntry::setTtl(uint32_t ttl)
344
0
  {
345
0
    someipsdhdrentry* hdr = getSomeIpSdEntryHeader();
346
0
    uint32_t val =
347
0
        (ttl & SOMEIPSD_HDR_ENTRY_MASK_TTL) | (be32toh(hdr->majorVersion_ttl) & ~SOMEIPSD_HDR_ENTRY_MASK_TTL);
348
0
    hdr->majorVersion_ttl = htobe32(val);
349
0
  }
350
351
  uint32_t SomeIpSdEntry::getMinorVersion() const
352
3.60k
  {
353
3.60k
    return be32toh(getSomeIpSdEntryHeader()->data);
354
3.60k
  }
355
356
  void SomeIpSdEntry::setMinorVersion(uint32_t minorVersion)
357
0
  {
358
0
    getSomeIpSdEntryHeader()->data = htobe32(minorVersion);
359
0
  }
360
361
  uint8_t SomeIpSdEntry::getCounter() const
362
3.60k
  {
363
3.60k
    return (uint8_t)((be32toh(getSomeIpSdEntryHeader()->data) >> 16) & 0x0F);
364
3.60k
  }
365
366
  void SomeIpSdEntry::setCounter(uint8_t counter)
367
0
  {
368
0
    someipsdhdrentry* hdr = getSomeIpSdEntryHeader();
369
0
    hdr->data = htobe32((be32toh(hdr->data) & 0xFFF0FFFF) | ((counter & 0x0F) << 16));
370
0
  }
371
372
  uint16_t SomeIpSdEntry::getEventgroupId() const
373
3.60k
  {
374
3.60k
    return (uint16_t)(be32toh(getSomeIpSdEntryHeader()->data) & 0x0000FFFF);
375
3.60k
  }
376
377
  void SomeIpSdEntry::setEventgroupId(uint16_t eventgroupID)
378
0
  {
379
0
    someipsdhdrentry* hdr = getSomeIpSdEntryHeader();
380
0
    hdr->data = htobe32((be32toh(hdr->data) & 0xFFFF0000) | eventgroupID);
381
0
  }
382
383
  void SomeIpSdEntry::initStdFields(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion,
384
                                    uint32_t TTL)
385
0
  {
386
0
    m_EntryType = type;
387
0
    m_Layer = nullptr;
388
0
    m_Offset = 0;
389
390
0
    size_t dataLen = sizeof(someipsdhdrentry);
391
0
    m_ShadowData = new uint8_t[dataLen];
392
0
    memset(m_ShadowData, 0, dataLen);
393
394
0
    someipsdhdrentry* hdr = getSomeIpSdEntryHeader();
395
0
    setServiceId(serviceID);
396
0
    setInstanceId(instanceID);
397
0
    setMajorVersion(majorVersion);
398
0
    setTtl(TTL);
399
400
0
    switch (type)
401
0
    {
402
0
    case EntryType::FindService:
403
0
    {
404
0
      hdr->type = static_cast<uint8_t>(TypeInternal::FindService_Internal);
405
0
      break;
406
0
    }
407
0
    case EntryType::OfferService:
408
0
    case EntryType::StopOfferService:
409
0
    {
410
0
      hdr->type = static_cast<uint8_t>(TypeInternal::OfferService_Internal);
411
0
      break;
412
0
    }
413
0
    case EntryType::SubscribeEventgroup:
414
0
    case EntryType::StopSubscribeEventgroup:
415
0
    {
416
0
      hdr->type = static_cast<uint8_t>(TypeInternal::SubscribeEventgroup_Internal);
417
0
      break;
418
0
    }
419
0
    case EntryType::SubscribeEventgroupAck:
420
0
    case EntryType::SubscribeEventgroupNack:
421
0
    {
422
0
      hdr->type = static_cast<uint8_t>(TypeInternal::SubscribeEventgroupAck_Internal);
423
0
      break;
424
0
    }
425
0
    default:
426
0
      break;
427
0
    }
428
0
  }
429
430
  // -------- Class SomeIpSdLayer -----------------
431
432
  SomeIpSdLayer::SomeIpSdLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
433
24.7k
      : SomeIpLayer(data, dataLen, prevLayer, packet)
434
24.7k
  {
435
24.7k
    countOptions(m_NumOptions, data);
436
24.7k
  }
437
438
  SomeIpSdLayer::SomeIpSdLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID,
439
                               uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint8_t flags)
440
0
  {
441
0
    m_Protocol = SomeIP;
442
0
    m_DataLen = sizeof(someipsdhdr) + 2 * sizeof(uint32_t);
443
0
    m_Data = new uint8_t[m_DataLen];
444
0
    memset(m_Data, 0, m_DataLen);
445
446
0
    m_NumOptions = 0;
447
448
0
    setServiceID(serviceID);
449
0
    setMethodID(methodID);
450
0
    setPayloadLength(sizeof(uint32_t) * 3);  // Flags+Reserved, Length Entries, Length Options
451
0
    setClientID(clientID);
452
0
    setSessionID(sessionID);
453
0
    setProtocolVersion(0x01);
454
0
    setInterfaceVersion(interfaceVersion);
455
0
    setMessageType(type);
456
0
    setReturnCode(returnCode);
457
0
    setFlags(flags);
458
0
  }
459
460
  uint8_t SomeIpSdLayer::getFlags() const
461
3.67k
  {
462
3.67k
    someipsdhdr* hdr = (someipsdhdr*)m_Data;
463
3.67k
    return hdr->flags;
464
3.67k
  }
465
466
  void SomeIpSdLayer::setFlags(uint8_t flags)
467
0
  {
468
0
    someipsdhdr* hdr = (someipsdhdr*)m_Data;
469
0
    hdr->flags = flags;
470
0
  }
471
472
  uint32_t SomeIpSdLayer::getNumEntries() const
473
10.9k
  {
474
10.9k
    return (uint32_t)(getLenEntries() / sizeof(SomeIpSdEntry::someipsdhdrentry));
475
10.9k
  }
476
477
  uint32_t SomeIpSdLayer::getNumOptions() const
478
7.34k
  {
479
7.34k
    return m_NumOptions;
480
7.34k
  }
481
482
  const SomeIpSdLayer::EntriesVec SomeIpSdLayer::getEntries() const
483
3.67k
  {
484
3.67k
    size_t remainingLen = getLenEntries();
485
3.67k
    size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t);
486
487
3.67k
    EntriesVec vecEntries;
488
3.67k
    EntryPtr entry;
489
490
7.27k
    while (remainingLen > 0)
491
3.73k
    {
492
      // Ensure there is enough remaining length for a new entry
493
3.73k
      if (remainingLen < sizeof(SomeIpSdEntry::someipsdhdrentry))
494
123
      {
495
123
        break;
496
123
      }
497
3.60k
      entry = new SomeIpSdEntry(this, offset);
498
499
3.60k
      size_t entryLen = entry->getLength();
500
3.60k
      remainingLen -= entryLen;
501
3.60k
      offset += entryLen;
502
503
3.60k
      vecEntries.push_back(entry);
504
3.60k
    }
505
506
3.67k
    return vecEntries;
507
3.67k
  };
508
509
  const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptions() const
510
3.67k
  {
511
3.67k
    OptionsVec vecOptions;
512
3.67k
    OptionPtr option;
513
514
3.67k
    size_t remainingLen = getLenOptions();
515
3.67k
    size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t);
516
517
7.77k
    while (remainingLen > 0)
518
4.10k
    {
519
4.10k
      SomeIpSdOption::someipsdhdroptionsbase* hdr = (SomeIpSdOption::someipsdhdroptionsbase*)(m_Data + offset);
520
4.10k
      SomeIpSdOption::OptionType optionType = static_cast<SomeIpSdOption::OptionType>(hdr->type);
521
522
4.10k
      option = parseOption(optionType, offset);
523
524
4.10k
      if (option != nullptr)
525
2.90k
      {
526
2.90k
        vecOptions.push_back(std::move(option));
527
2.90k
      }
528
529
4.10k
      size_t optionLen = be16toh(hdr->length) + 3;
530
4.10k
      remainingLen -= optionLen;
531
4.10k
      offset += optionLen;
532
4.10k
    }
533
534
3.67k
    return vecOptions;
535
3.67k
  }
536
537
  const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptionsFromEntry(uint32_t index) const
538
3.59k
  {
539
3.59k
    OptionsVec vecOptions;
540
3.59k
    OptionPtr option;
541
542
3.59k
    if (index >= getNumEntries())
543
0
      return vecOptions;
544
545
3.59k
    size_t remainingLen = getLenOptions();
546
3.59k
    size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t);
547
548
3.59k
    size_t offsetToEntry = sizeof(someipsdhdr) + sizeof(uint32_t) + index * sizeof(SomeIpSdEntry::someipsdhdrentry);
549
3.59k
    SomeIpSdEntry::someipsdhdrentry* hdrEntry = (SomeIpSdEntry::someipsdhdrentry*)(m_Data + offsetToEntry);
550
3.59k
    uint8_t startIdxRun1 = hdrEntry->indexFirstOption;
551
3.59k
    uint8_t lenRun1 = hdrEntry->nrOpt1;
552
3.59k
    uint8_t startIdxRun2 = hdrEntry->indexSecondOption;
553
3.59k
    uint8_t lenRun2 = hdrEntry->nrOpt2;
554
555
3.59k
    int idx = 0;
556
557
7.70k
    while (remainingLen > 0)
558
4.10k
    {
559
4.10k
      SomeIpSdOption::someipsdhdroptionsbase* hdrOption =
560
4.10k
          (SomeIpSdOption::someipsdhdroptionsbase*)(m_Data + offset);
561
562
4.10k
      if (((idx >= startIdxRun1) && (idx < (startIdxRun1 + lenRun1))) ||
563
1.52k
          ((idx >= startIdxRun2) && (idx < (startIdxRun2 + lenRun2))))
564
2.78k
      {
565
2.78k
        SomeIpSdOption::OptionType optionType = static_cast<SomeIpSdOption::OptionType>(hdrOption->type);
566
567
2.78k
        option = parseOption(optionType, offset);
568
569
2.78k
        if (option != nullptr)
570
2.35k
        {
571
2.35k
          vecOptions.push_back(std::move(option));
572
2.35k
        }
573
2.78k
      }
574
575
4.10k
      size_t optionLen = be16toh(hdrOption->length) + 3;
576
4.10k
      remainingLen -= optionLen;
577
4.10k
      offset += optionLen;
578
4.10k
      ++idx;
579
4.10k
    }
580
581
3.59k
    return vecOptions;
582
3.59k
  }
583
584
  bool SomeIpSdLayer::addOptionTo(uint32_t indexEntry, const SomeIpSdOption& option)
585
0
  {
586
0
    if (indexEntry >= getNumEntries())
587
0
    {
588
0
      return false;
589
0
    }
590
591
0
    uint32_t indexOption = findOption(option);
592
0
    bool success = addOptionIndex(indexEntry, indexOption);
593
594
0
    if (!success)
595
0
    {
596
0
      return false;
597
0
    }
598
599
0
    if (indexOption == m_NumOptions)
600
0
    {
601
0
      addOption(option);
602
0
    }
603
604
0
    return true;
605
0
  }
606
607
  std::string SomeIpSdLayer::toString() const
608
7.34k
  {
609
7.34k
    std::stringstream dataStream;
610
611
7.34k
    dataStream << "SOME/IP-SD Layer, " << getNumEntries() << " entries, " << getNumOptions() << " options";
612
613
7.34k
    return dataStream.str();
614
7.34k
  }
615
616
  uint32_t SomeIpSdLayer::addEntry(const SomeIpSdEntry& entry)
617
0
  {
618
0
    size_t lenEntries = getLenEntries();
619
0
    int offsetToAddAt = sizeof(someipsdhdr) + sizeof(uint32_t) + lenEntries;
620
621
0
    extendLayer(offsetToAddAt, entry.getLength());
622
623
0
    setLenEntries(lenEntries + entry.getLength());
624
625
0
    memcpy(m_Data + offsetToAddAt, entry.getDataPtr(), entry.getLength());
626
627
0
    auto hdr = getSomeIpHeader();
628
0
    hdr->length = htobe32(be32toh(hdr->length) + (uint32_t)entry.getLength());
629
630
0
    return getNumEntries() - 1;
631
0
  }
632
633
  bool SomeIpSdLayer::isDataValid(const uint8_t* data, size_t dataLen)
634
30.6k
  {
635
30.6k
    uint32_t count;
636
30.6k
    if (!data || dataLen < sizeof(someipsdhdr) + sizeof(uint32_t) ||
637
30.6k
        dataLen < sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t) ||
638
27.6k
        dataLen <
639
27.6k
            sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t) + getLenOptions(data) ||
640
27.2k
        !countOptions(count, data))
641
5.88k
    {
642
5.88k
      return false;
643
5.88k
    }
644
645
24.7k
    return true;
646
30.6k
  }
647
648
  bool SomeIpSdLayer::countOptions(uint32_t& count, const uint8_t* data)
649
51.9k
  {
650
51.9k
    size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t);
651
51.9k
    size_t lenOptions = getLenOptions(data);
652
51.9k
    uint32_t len = 0;
653
654
51.9k
    count = 0;
655
105k
    while (len < lenOptions)
656
56.0k
    {
657
56.0k
      if (len + sizeof(uint16_t) + 3 * sizeof(uint8_t) > lenOptions)
658
73
        return false;
659
660
56.0k
      uint32_t lenOption = be16toh(*((uint16_t*)(data + offsetOption + len))) + 3 * sizeof(uint8_t);
661
56.0k
      len += lenOption;
662
56.0k
      if (len > lenOptions)  // the last one must be equal to lenOptions
663
2.39k
        return false;
664
665
53.6k
      ++(count);
666
53.6k
    }
667
49.4k
    return true;
668
51.9k
  }
669
670
  uint32_t SomeIpSdLayer::findOption(const SomeIpSdOption& option)
671
0
  {
672
0
    size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t);
673
674
0
    uint32_t i = 0;
675
0
    while (i < m_NumOptions)
676
0
    {
677
0
      uint32_t lenOption = be16toh(*((uint16_t*)(m_Data + offsetOption))) + 3 * sizeof(uint8_t);
678
679
0
      if (option.getLength() == lenOption)
680
0
      {
681
0
        if (memcmp(m_Data + offsetOption, option.getDataPtr(), option.getLength()) == 0)
682
0
        {
683
0
          return i;
684
0
        }
685
0
      }
686
687
0
      offsetOption += lenOption;
688
0
      ++i;
689
0
    }
690
0
    return i;
691
0
  }
692
693
  void SomeIpSdLayer::addOption(const SomeIpSdOption& option)
694
0
  {
695
0
    int offsetToAddAt = (int)getHeaderLen();
696
697
0
    extendLayer(offsetToAddAt, option.getLength());
698
0
    memcpy(m_Data + offsetToAddAt, option.getDataPtr(), option.getLength());
699
700
0
    setLenOptions(uint32_t(getLenOptions() + option.getLength()));
701
702
0
    auto hdr = getSomeIpHeader();
703
0
    hdr->length = htobe32(be32toh(hdr->length) + (uint32_t)option.getLength());
704
705
0
    ++m_NumOptions;
706
0
  }
707
708
  bool SomeIpSdLayer::addOptionIndex(uint32_t indexEntry, uint32_t indexOffset)
709
0
  {
710
    //    The SOME/IP-SD protocol supports two option runs. Runs meaning that two different starting indices with
711
    //    differing length can be provided. Of course, this only works if the indices in both runs are consecutive.
712
    //
713
    //    So, indices like this would work:
714
    //        1 2 3 ; 7 8
715
    //
716
    //    What wouldn't work is this:
717
    //        1 2 3 ; 7 9
718
    //        1 3 ; 7 8
719
720
0
    const size_t someipsdhdrentrySize = sizeof(SomeIpSdEntry::someipsdhdrentry);
721
0
    size_t offsetToAddAt = sizeof(someipsdhdr) + sizeof(uint32_t) + indexEntry * someipsdhdrentrySize;
722
0
    auto hdrEntry = (SomeIpSdEntry::someipsdhdrentry*)(m_Data + offsetToAddAt);
723
724
0
    uint8_t indexFirstOption = hdrEntry->indexFirstOption;
725
0
    uint8_t lenFirstOption = hdrEntry->nrOpt1;
726
727
0
    if (lenFirstOption == 0)
728
0
    {
729
0
      hdrEntry->indexFirstOption = indexOffset;
730
0
      ++hdrEntry->nrOpt1;
731
0
      return true;
732
0
    }
733
734
0
    if (static_cast<uint32_t>(indexFirstOption + lenFirstOption + 1) == indexOffset)
735
0
    {
736
0
      ++hdrEntry->nrOpt1;
737
0
      return true;
738
0
    }
739
740
0
    uint8_t indexSecondOption = hdrEntry->indexSecondOption;
741
0
    uint8_t lenSecondOption = hdrEntry->nrOpt2;
742
743
0
    if (lenSecondOption == 0)
744
0
    {
745
0
      hdrEntry->indexFirstOption = indexOffset;
746
0
      ++hdrEntry->nrOpt1;
747
0
      return true;
748
0
    }
749
750
0
    if (static_cast<uint32_t>(indexSecondOption + lenSecondOption + 1) == indexOffset)
751
0
    {
752
0
      ++hdrEntry->nrOpt2;
753
0
      return true;
754
0
    }
755
756
0
    return false;
757
0
  }
758
759
  SomeIpSdLayer::OptionPtr SomeIpSdLayer::parseOption(SomeIpSdOption::OptionType type, size_t offset) const
760
6.89k
  {
761
6.89k
    switch (type)
762
6.89k
    {
763
1.13k
    case SomeIpSdOption::OptionType::IPv4Endpoint:
764
1.62k
    case SomeIpSdOption::OptionType::IPv4Multicast:
765
1.99k
    case SomeIpSdOption::OptionType::IPv4SdEndpoint:
766
1.99k
    {
767
1.99k
      return new SomeIpSdIPv4Option(this, offset);
768
1.62k
    }
769
49
    case SomeIpSdOption::OptionType::IPv6Endpoint:
770
294
    case SomeIpSdOption::OptionType::IPv6Multicast:
771
1.31k
    case SomeIpSdOption::OptionType::IPv6SdEndpoint:
772
1.31k
    {
773
1.31k
      return new SomeIpSdIPv6Option(this, offset);
774
294
    }
775
355
    case SomeIpSdOption::OptionType::ConfigurationString:
776
355
    {
777
355
      return new SomeIpSdConfigurationOption(this, offset);
778
294
    }
779
1.59k
    case SomeIpSdOption::OptionType::LoadBalancing:
780
1.59k
    {
781
1.59k
      return new SomeIpSdLoadBalancingOption(this, offset);
782
294
    }
783
1.63k
    default:
784
1.63k
      break;
785
6.89k
    }
786
1.63k
    return nullptr;
787
6.89k
  }
788
789
  size_t SomeIpSdLayer::getLenEntries() const
790
21.8k
  {
791
21.8k
    return getLenEntries(m_Data);
792
21.8k
  }
793
794
  size_t SomeIpSdLayer::getLenEntries(const uint8_t* data)
795
218k
  {
796
218k
    return be32toh(*((uint32_t*)(data + sizeof(someipsdhdr))));
797
218k
  }
798
799
  size_t SomeIpSdLayer::getLenOptions() const
800
7.26k
  {
801
7.26k
    return getLenOptions(m_Data);
802
7.26k
  }
803
804
  size_t SomeIpSdLayer::getLenOptions(const uint8_t* data)
805
86.8k
  {
806
86.8k
    return be32toh(*((uint32_t*)(data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data))));
807
86.8k
  }
808
809
  void SomeIpSdLayer::setLenEntries(uint32_t length)
810
0
  {
811
0
    *((uint32_t*)(m_Data + sizeof(someipsdhdr))) = htobe32(length);
812
0
  }
813
814
  void SomeIpSdLayer::setLenOptions(uint32_t length)
815
0
  {
816
    *((uint32_t*)(m_Data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries())) = htobe32(length);
817
0
  }
818
}  // namespace pcpp