Coverage Report

Created: 2026-08-31 07:52

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
4.01k
  {
15
4.01k
    if (m_ShadowData != nullptr)
16
0
      delete[] m_ShadowData;
17
4.01k
  }
18
19
  SomeIpSdOption::OptionType SomeIpSdOption::getType() const
20
2.34k
  {
21
2.34k
    return static_cast<OptionType>(getSomeIpSdOptionHeader()->type);
22
2.34k
  }
23
24
  uint8_t* SomeIpSdOption::getDataPtr() const
25
7.04k
  {
26
7.04k
    if (m_DataContainer != nullptr)
27
7.04k
      return m_DataContainer->getDataPtr(m_Offset);
28
29
0
    return m_ShadowData;
30
7.04k
  }
31
32
  SomeIpSdOption::someipsdhdroptionsbase* SomeIpSdOption::getSomeIpSdOptionHeader() const
33
2.80k
  {
34
2.80k
    return reinterpret_cast<someipsdhdroptionsbase*>(getDataPtr());
35
2.80k
  }
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 = reinterpret_cast<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.52k
      : SomeIpSdOption(dataContainer, offset)
76
1.52k
  {
77
1.52k
    m_DataLen = sizeof(someipsdhdroptionsipv4);
78
1.52k
  }
79
80
  IPv4Address SomeIpSdIPv4Option::getIpAddress() const
81
779
  {
82
779
    someipsdhdroptionsipv4* hdr = reinterpret_cast<someipsdhdroptionsipv4*>(getDataPtr());
83
779
    IPv4Address ipAddr(hdr->ipv4Address);
84
85
779
    return ipAddr;
86
779
  }
87
88
  uint16_t SomeIpSdIPv4Option::getPort() const
89
779
  {
90
779
    someipsdhdroptionsipv4* hdr = reinterpret_cast<someipsdhdroptionsipv4*>(getDataPtr());
91
779
    return be16toh(hdr->portNumber);
92
779
  }
93
94
  SomeIpSdProtocolType SomeIpSdIPv4Option::getProtocol() const
95
779
  {
96
779
    someipsdhdroptionsipv4* hdr = reinterpret_cast<someipsdhdroptionsipv4*>(getDataPtr());
97
779
    return hdr->l4Protocol;
98
779
  }
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 = reinterpret_cast<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
954
      : SomeIpSdOption(dataContainer, offset)
130
954
  {
131
954
    m_DataLen = sizeof(someipsdhdroptionsipv6);
132
954
  }
133
134
  IPv6Address SomeIpSdIPv6Option::getIpAddress() const
135
637
  {
136
637
    someipsdhdroptionsipv6* hdr = reinterpret_cast<someipsdhdroptionsipv6*>(getDataPtr());
137
637
    IPv6Address ipAddr(hdr->ipv6Address);
138
139
637
    return ipAddr;
140
637
  }
141
142
  uint16_t SomeIpSdIPv6Option::getPort() const
143
637
  {
144
637
    someipsdhdroptionsipv6* hdr = reinterpret_cast<someipsdhdroptionsipv6*>(getDataPtr());
145
637
    return be16toh(hdr->portNumber);
146
637
  }
147
148
  SomeIpSdProtocolType SomeIpSdIPv6Option::getProtocol() const
149
637
  {
150
637
    someipsdhdroptionsipv6* hdr = reinterpret_cast<someipsdhdroptionsipv6*>(getDataPtr());
151
637
    return hdr->l4Protocol;
152
637
  }
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
456
      : SomeIpSdOption(dataContainer, offset)
169
456
  {
170
456
    m_DataLen = sizeof(someipsdhdroptionsbase) - 1 + be16toh(getSomeIpSdOptionHeader()->length);
171
456
  }
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 = reinterpret_cast<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.07k
      : SomeIpSdOption(dataContainer, offset)
196
1.07k
  {
197
1.07k
    m_DataLen = sizeof(someipsdhdroptionsload);
198
1.07k
  }
199
200
  uint16_t SomeIpSdLoadBalancingOption::getPriority() const
201
0
  {
202
0
    someipsdhdroptionsload* hdr = reinterpret_cast<someipsdhdroptionsload*>(getDataPtr());
203
0
    return be16toh(hdr->priority);
204
0
  }
205
206
  uint16_t SomeIpSdLoadBalancingOption::getWeight() const
207
0
  {
208
0
    someipsdhdroptionsload* hdr = reinterpret_cast<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.37k
      : m_Layer(pSomeIpSdLayer), m_Offset(offset), m_ShadowData(nullptr)
231
3.37k
  {
232
3.37k
    EntryType entryType;
233
234
3.37k
    someipsdhdrentry* hdr = getSomeIpSdEntryHeader();
235
3.37k
    TypeInternal internalType = static_cast<TypeInternal>(hdr->type);
236
3.37k
    auto ttl = getTtl();
237
238
3.37k
    switch (internalType)
239
3.37k
    {
240
403
    case SomeIpSdEntry::TypeInternal::FindService_Internal:
241
403
      entryType = SomeIpSdEntry::EntryType::FindService;
242
403
      break;
243
2.03k
    case SomeIpSdEntry::TypeInternal::OfferService_Internal:
244
2.03k
      if (ttl == 0)
245
324
      {
246
324
        entryType = EntryType::StopOfferService;
247
324
      }
248
1.70k
      else
249
1.70k
      {
250
1.70k
        entryType = EntryType::OfferService;
251
1.70k
      }
252
2.03k
      break;
253
12
    case SomeIpSdEntry::TypeInternal::SubscribeEventgroup_Internal:
254
12
      if (ttl == 0)
255
1
      {
256
1
        entryType = EntryType::StopSubscribeEventgroup;
257
1
      }
258
11
      else
259
11
      {
260
11
        entryType = EntryType::SubscribeEventgroup;
261
11
      }
262
12
      break;
263
316
    case SomeIpSdEntry::TypeInternal::SubscribeEventgroupAck_Internal:
264
316
      if (ttl == 0)
265
110
      {
266
110
        entryType = EntryType::SubscribeEventgroupNack;
267
110
      }
268
206
      else
269
206
      {
270
206
        entryType = EntryType::SubscribeEventgroupAck;
271
206
      }
272
316
      break;
273
616
    default:
274
616
      entryType = EntryType::UnknownEntryType;
275
616
      break;
276
3.37k
    }
277
278
3.37k
    m_EntryType = entryType;
279
3.37k
  }
280
281
  SomeIpSdEntry::~SomeIpSdEntry()
282
3.37k
  {
283
3.37k
    if (m_ShadowData != nullptr)
284
0
      delete[] m_ShadowData;
285
3.37k
  }
286
287
  uint8_t* SomeIpSdEntry::getDataPtr() const
288
30.4k
  {
289
30.4k
    if (m_Layer != nullptr)
290
30.4k
      return m_Layer->getDataPtr(m_Offset);
291
292
0
    return m_ShadowData;
293
30.4k
  }
294
295
  SomeIpSdEntry::someipsdhdrentry* SomeIpSdEntry::getSomeIpSdEntryHeader() const
296
30.4k
  {
297
30.4k
    return reinterpret_cast<someipsdhdrentry*>(getDataPtr());
298
30.4k
  }
299
300
  uint32_t SomeIpSdEntry::getNumOptions() const
301
3.37k
  {
302
3.37k
    auto* hdr = getSomeIpSdEntryHeader();
303
3.37k
    return hdr->nrOpt1 + hdr->nrOpt2;
304
3.37k
  }
305
306
  uint16_t SomeIpSdEntry::getServiceId() const
307
3.37k
  {
308
3.37k
    return be16toh(getSomeIpSdEntryHeader()->serviceID);
309
3.37k
  }
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.37k
  {
318
3.37k
    return be16toh(getSomeIpSdEntryHeader()->instanceID);
319
3.37k
  }
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.37k
  {
328
3.37k
    return (be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & ~SOMEIPSD_HDR_ENTRY_MASK_TTL) >> 24;
329
3.37k
  }
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.37k
  {
340
3.37k
    return be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & SOMEIPSD_HDR_ENTRY_MASK_TTL;
341
3.37k
  }
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.37k
  {
353
3.37k
    return be32toh(getSomeIpSdEntryHeader()->data);
354
3.37k
  }
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.37k
  {
363
3.37k
    return static_cast<uint8_t>((be32toh(getSomeIpSdEntryHeader()->data) >> 16) & 0x0F);
364
3.37k
  }
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.37k
  {
374
3.37k
    return static_cast<uint16_t>(be32toh(getSomeIpSdEntryHeader()->data) & 0x0000FFFF);
375
3.37k
  }
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
23.4k
      : SomeIpLayer(data, dataLen, prevLayer, packet)
434
23.4k
  {
435
23.4k
    countOptions(m_NumOptions, data);
436
23.4k
  }
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
    allocData(sizeof(someipsdhdr) + 2 * sizeof(uint32_t));
443
444
0
    m_NumOptions = 0;
445
446
0
    setServiceID(serviceID);
447
0
    setMethodID(methodID);
448
0
    setPayloadLength(sizeof(uint32_t) * 3);  // Flags+Reserved, Length Entries, Length Options
449
0
    setClientID(clientID);
450
0
    setSessionID(sessionID);
451
0
    setProtocolVersion(0x01);
452
0
    setInterfaceVersion(interfaceVersion);
453
0
    setMessageType(type);
454
0
    setReturnCode(returnCode);
455
0
    setFlags(flags);
456
0
  }
457
458
  uint8_t SomeIpSdLayer::getFlags() const
459
3.45k
  {
460
3.45k
    someipsdhdr* hdr = reinterpret_cast<someipsdhdr*>(m_Data);
461
3.45k
    return hdr->flags;
462
3.45k
  }
463
464
  void SomeIpSdLayer::setFlags(uint8_t flags)
465
0
  {
466
0
    someipsdhdr* hdr = reinterpret_cast<someipsdhdr*>(m_Data);
467
0
    hdr->flags = flags;
468
0
  }
469
470
  uint32_t SomeIpSdLayer::getNumEntries() const
471
10.2k
  {
472
10.2k
    return static_cast<uint32_t>(getLenEntries() / sizeof(SomeIpSdEntry::someipsdhdrentry));
473
10.2k
  }
474
475
  uint32_t SomeIpSdLayer::getNumOptions() const
476
6.91k
  {
477
6.91k
    return m_NumOptions;
478
6.91k
  }
479
480
  const SomeIpSdLayer::EntriesVec SomeIpSdLayer::getEntries() const
481
3.45k
  {
482
3.45k
    size_t remainingLen = getLenEntries();
483
3.45k
    size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t);
484
485
3.45k
    EntriesVec vecEntries;
486
3.45k
    EntryPtr entry;
487
488
6.83k
    while (remainingLen > 0)
489
3.48k
    {
490
      // Ensure there is enough remaining length for a new entry
491
3.48k
      if (remainingLen < sizeof(SomeIpSdEntry::someipsdhdrentry))
492
108
      {
493
108
        break;
494
108
      }
495
3.37k
      entry = new SomeIpSdEntry(this, offset);
496
497
3.37k
      size_t entryLen = entry->getLength();
498
3.37k
      remainingLen -= entryLen;
499
3.37k
      offset += entryLen;
500
501
3.37k
      vecEntries.push_back(entry);
502
3.37k
    }
503
504
3.45k
    return vecEntries;
505
3.45k
  };
506
507
  const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptions() const
508
3.45k
  {
509
3.45k
    OptionsVec vecOptions;
510
3.45k
    OptionPtr option;
511
512
3.45k
    size_t remainingLen = getLenOptions();
513
3.45k
    size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t);
514
515
7.19k
    while (remainingLen > 0)
516
3.74k
    {
517
3.74k
      SomeIpSdOption::someipsdhdroptionsbase* hdr =
518
3.74k
          reinterpret_cast<SomeIpSdOption::someipsdhdroptionsbase*>(m_Data + offset);
519
3.74k
      SomeIpSdOption::OptionType optionType = static_cast<SomeIpSdOption::OptionType>(hdr->type);
520
521
3.74k
      option = parseOption(optionType, offset, remainingLen);
522
523
3.74k
      if (option != nullptr)
524
2.34k
      {
525
2.34k
        vecOptions.push_back(std::move(option));
526
2.34k
      }
527
528
3.74k
      size_t optionLen = be16toh(hdr->length) + 3;
529
3.74k
      remainingLen -= optionLen;
530
3.74k
      offset += optionLen;
531
3.74k
    }
532
533
3.45k
    return vecOptions;
534
3.45k
  }
535
536
  const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptionsFromEntry(uint32_t index) const
537
3.37k
  {
538
3.37k
    OptionsVec vecOptions;
539
3.37k
    OptionPtr option;
540
541
3.37k
    if (index >= getNumEntries())
542
0
      return vecOptions;
543
544
3.37k
    size_t remainingLen = getLenOptions();
545
3.37k
    size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t);
546
547
3.37k
    size_t offsetToEntry = sizeof(someipsdhdr) + sizeof(uint32_t) + index * sizeof(SomeIpSdEntry::someipsdhdrentry);
548
3.37k
    SomeIpSdEntry::someipsdhdrentry* hdrEntry =
549
3.37k
        reinterpret_cast<SomeIpSdEntry::someipsdhdrentry*>(m_Data + offsetToEntry);
550
3.37k
    uint8_t startIdxRun1 = hdrEntry->indexFirstOption;
551
3.37k
    uint8_t lenRun1 = hdrEntry->nrOpt1;
552
3.37k
    uint8_t startIdxRun2 = hdrEntry->indexSecondOption;
553
3.37k
    uint8_t lenRun2 = hdrEntry->nrOpt2;
554
555
3.37k
    int idx = 0;
556
557
7.11k
    while (remainingLen > 0)
558
3.74k
    {
559
3.74k
      SomeIpSdOption::someipsdhdroptionsbase* hdrOption =
560
3.74k
          reinterpret_cast<SomeIpSdOption::someipsdhdroptionsbase*>(m_Data + offset);
561
562
3.74k
      if (((idx >= startIdxRun1) && (idx < (startIdxRun1 + lenRun1))) ||
563
1.62k
          ((idx >= startIdxRun2) && (idx < (startIdxRun2 + lenRun2))))
564
2.37k
      {
565
2.37k
        SomeIpSdOption::OptionType optionType = static_cast<SomeIpSdOption::OptionType>(hdrOption->type);
566
567
2.37k
        option = parseOption(optionType, offset, remainingLen);
568
569
2.37k
        if (option != nullptr)
570
1.66k
        {
571
1.66k
          vecOptions.push_back(std::move(option));
572
1.66k
        }
573
2.37k
      }
574
575
3.74k
      size_t optionLen = be16toh(hdrOption->length) + 3;
576
3.74k
      remainingLen -= optionLen;
577
3.74k
      offset += optionLen;
578
3.74k
      ++idx;
579
3.74k
    }
580
581
3.37k
    return vecOptions;
582
3.37k
  }
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
6.91k
  {
609
6.91k
    std::stringstream dataStream;
610
611
6.91k
    dataStream << "SOME/IP-SD Layer, " << getNumEntries() << " entries, " << getNumOptions() << " options";
612
613
6.91k
    return dataStream.str();
614
6.91k
  }
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.8k
  {
635
30.8k
    uint32_t count;
636
30.8k
    if (!data || dataLen < sizeof(someipsdhdr) + sizeof(uint32_t) ||
637
30.8k
        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.0k
        !countOptions(count, data))
641
7.42k
    {
642
7.42k
      return false;
643
7.42k
    }
644
645
23.4k
    return true;
646
30.8k
  }
647
648
  bool SomeIpSdLayer::countOptions(uint32_t& count, const uint8_t* data)
649
50.5k
  {
650
50.5k
    size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t);
651
50.5k
    size_t lenOptions = getLenOptions(data);
652
50.5k
    uint32_t len = 0;
653
654
50.5k
    count = 0;
655
99.7k
    while (len < lenOptions)
656
52.8k
    {
657
52.8k
      if (len + sizeof(uint16_t) + 3 * sizeof(uint8_t) > lenOptions)
658
80
        return false;
659
660
52.7k
      uint32_t lenOption =
661
52.7k
          be16toh(*(reinterpret_cast<uint16_t const*>(data + offsetOption + len))) + 3 * sizeof(uint8_t);
662
52.7k
      len += lenOption;
663
52.7k
      if (len > lenOptions)  // the last one must be equal to lenOptions
664
3.50k
        return false;
665
666
49.2k
      ++(count);
667
49.2k
    }
668
46.9k
    return true;
669
50.5k
  }
670
671
  uint32_t SomeIpSdLayer::findOption(const SomeIpSdOption& option)
672
0
  {
673
0
    size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t);
674
675
0
    uint32_t i = 0;
676
0
    while (i < m_NumOptions)
677
0
    {
678
0
      uint32_t lenOption = be16toh(*(reinterpret_cast<uint16_t*>(m_Data + offsetOption))) + 3 * sizeof(uint8_t);
679
680
0
      if (option.getLength() == lenOption)
681
0
      {
682
0
        if (memcmp(m_Data + offsetOption, option.getDataPtr(), option.getLength()) == 0)
683
0
        {
684
0
          return i;
685
0
        }
686
0
      }
687
688
0
      offsetOption += lenOption;
689
0
      ++i;
690
0
    }
691
0
    return i;
692
0
  }
693
694
  void SomeIpSdLayer::addOption(const SomeIpSdOption& option)
695
0
  {
696
0
    int offsetToAddAt = (int)getHeaderLen();
697
698
0
    extendLayer(offsetToAddAt, option.getLength());
699
0
    memcpy(m_Data + offsetToAddAt, option.getDataPtr(), option.getLength());
700
701
0
    setLenOptions(uint32_t(getLenOptions() + option.getLength()));
702
703
0
    auto hdr = getSomeIpHeader();
704
0
    hdr->length = htobe32(be32toh(hdr->length) + (uint32_t)option.getLength());
705
706
0
    ++m_NumOptions;
707
0
  }
708
709
  bool SomeIpSdLayer::addOptionIndex(uint32_t indexEntry, uint32_t indexOffset)
710
0
  {
711
    //    The SOME/IP-SD protocol supports two option runs. Runs meaning that two different starting indices with
712
    //    differing length can be provided. Of course, this only works if the indices in both runs are consecutive.
713
    //
714
    //    So, indices like this would work:
715
    //        1 2 3 ; 7 8
716
    //
717
    //    What wouldn't work is this:
718
    //        1 2 3 ; 7 9
719
    //        1 3 ; 7 8
720
721
0
    const size_t someipsdhdrentrySize = sizeof(SomeIpSdEntry::someipsdhdrentry);
722
0
    size_t offsetToAddAt = sizeof(someipsdhdr) + sizeof(uint32_t) + indexEntry * someipsdhdrentrySize;
723
0
    auto hdrEntry = reinterpret_cast<SomeIpSdEntry::someipsdhdrentry*>(m_Data + offsetToAddAt);
724
725
0
    uint8_t indexFirstOption = hdrEntry->indexFirstOption;
726
0
    uint8_t lenFirstOption = hdrEntry->nrOpt1;
727
728
0
    if (lenFirstOption == 0)
729
0
    {
730
0
      hdrEntry->indexFirstOption = indexOffset;
731
0
      ++hdrEntry->nrOpt1;
732
0
      return true;
733
0
    }
734
735
0
    if (static_cast<uint32_t>(indexFirstOption + lenFirstOption + 1) == indexOffset)
736
0
    {
737
0
      ++hdrEntry->nrOpt1;
738
0
      return true;
739
0
    }
740
741
0
    uint8_t indexSecondOption = hdrEntry->indexSecondOption;
742
0
    uint8_t lenSecondOption = hdrEntry->nrOpt2;
743
744
0
    if (lenSecondOption == 0)
745
0
    {
746
0
      hdrEntry->indexFirstOption = indexOffset;
747
0
      ++hdrEntry->nrOpt1;
748
0
      return true;
749
0
    }
750
751
0
    if (static_cast<uint32_t>(indexSecondOption + lenSecondOption + 1) == indexOffset)
752
0
    {
753
0
      ++hdrEntry->nrOpt2;
754
0
      return true;
755
0
    }
756
757
0
    return false;
758
0
  }
759
760
  SomeIpSdLayer::OptionPtr SomeIpSdLayer::parseOption(SomeIpSdOption::OptionType type, size_t offset,
761
                                                      size_t remainingLength) const
762
6.11k
  {
763
6.11k
    switch (type)
764
6.11k
    {
765
955
    case SomeIpSdOption::OptionType::IPv4Endpoint:
766
1.16k
    case SomeIpSdOption::OptionType::IPv4Multicast:
767
1.52k
    case SomeIpSdOption::OptionType::IPv4SdEndpoint:
768
1.52k
    {
769
1.52k
      if (SomeIpSdIPv4Option::isDataValid(this, remainingLength))
770
1.52k
      {
771
1.52k
        return new SomeIpSdIPv4Option(this, offset);
772
1.52k
      }
773
0
      return nullptr;
774
1.52k
    }
775
72
    case SomeIpSdOption::OptionType::IPv6Endpoint:
776
402
    case SomeIpSdOption::OptionType::IPv6Multicast:
777
956
    case SomeIpSdOption::OptionType::IPv6SdEndpoint:
778
956
    {
779
956
      if (SomeIpSdIPv6Option::isDataValid(this, remainingLength))
780
954
      {
781
954
        return new SomeIpSdIPv6Option(this, offset);
782
954
      }
783
2
      return nullptr;
784
956
    }
785
456
    case SomeIpSdOption::OptionType::ConfigurationString:
786
456
    {
787
456
      if (SomeIpSdConfigurationOption::isDataValid(this, remainingLength))
788
456
      {
789
456
        return new SomeIpSdConfigurationOption(this, offset);
790
456
      }
791
0
      return nullptr;
792
456
    }
793
1.07k
    case SomeIpSdOption::OptionType::LoadBalancing:
794
1.07k
    {
795
1.07k
      if (SomeIpSdLoadBalancingOption::isDataValid(this, remainingLength))
796
1.07k
      {
797
1.07k
        return new SomeIpSdLoadBalancingOption(this, offset);
798
1.07k
      }
799
0
      return nullptr;
800
1.07k
    }
801
2.10k
    default:
802
2.10k
      break;
803
6.11k
    }
804
2.10k
    return nullptr;
805
6.11k
  }
806
807
  size_t SomeIpSdLayer::getLenEntries() const
808
20.5k
  {
809
20.5k
    return getLenEntries(m_Data);
810
20.5k
  }
811
812
  size_t SomeIpSdLayer::getLenEntries(const uint8_t* data)
813
214k
  {
814
214k
    return be32toh(*(reinterpret_cast<const uint32_t*>(data + sizeof(someipsdhdr))));
815
214k
  }
816
817
  size_t SomeIpSdLayer::getLenOptions() const
818
6.83k
  {
819
6.83k
    return getLenOptions(m_Data);
820
6.83k
  }
821
822
  size_t SomeIpSdLayer::getLenOptions(const uint8_t* data)
823
84.9k
  {
824
84.9k
    return be32toh(
825
84.9k
        *(reinterpret_cast<const uint32_t*>(data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data))));
826
84.9k
  }
827
828
  void SomeIpSdLayer::setLenEntries(uint32_t length)
829
0
  {
830
0
    *(reinterpret_cast<uint32_t*>(m_Data + sizeof(someipsdhdr))) = htobe32(length);
831
0
  }
832
833
  void SomeIpSdLayer::setLenOptions(uint32_t length)
834
0
  {
835
0
    *(reinterpret_cast<uint32_t*>(m_Data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries())) =
836
        htobe32(length);
837
0
  }
838
}  // namespace pcpp