Coverage Report

Created: 2026-10-17 07:09

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
12.0k
  {
15
12.0k
    if (m_ShadowData != nullptr)
16
0
      delete[] m_ShadowData;
17
12.0k
  }
18
19
  SomeIpSdOption::OptionType SomeIpSdOption::getType() const
20
6.57k
  {
21
6.57k
    return static_cast<OptionType>(getSomeIpSdOptionHeader()->type);
22
6.57k
  }
23
24
  uint8_t* SomeIpSdOption::getDataPtr() const
25
24.2k
  {
26
24.2k
    if (m_DataContainer != nullptr)
27
24.2k
      return m_DataContainer->getDataPtr(m_Offset);
28
29
0
    return m_ShadowData;
30
24.2k
  }
31
32
  SomeIpSdOption::someipsdhdroptionsbase* SomeIpSdOption::getSomeIpSdOptionHeader() const
33
6.91k
  {
34
6.91k
    return reinterpret_cast<someipsdhdroptionsbase*>(getDataPtr());
35
6.91k
  }
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
10.0k
      : SomeIpSdOption(dataContainer, offset)
76
10.0k
  {
77
10.0k
    m_DataLen = sizeof(someipsdhdroptionsipv4);
78
10.0k
  }
79
80
  IPv4Address SomeIpSdIPv4Option::getIpAddress() const
81
5.28k
  {
82
5.28k
    someipsdhdroptionsipv4* hdr = reinterpret_cast<someipsdhdroptionsipv4*>(getDataPtr());
83
5.28k
    IPv4Address ipAddr(hdr->ipv4Address);
84
85
5.28k
    return ipAddr;
86
5.28k
  }
87
88
  uint16_t SomeIpSdIPv4Option::getPort() const
89
5.28k
  {
90
5.28k
    someipsdhdroptionsipv4* hdr = reinterpret_cast<someipsdhdroptionsipv4*>(getDataPtr());
91
5.28k
    return be16toh(hdr->portNumber);
92
5.28k
  }
93
94
  SomeIpSdProtocolType SomeIpSdIPv4Option::getProtocol() const
95
5.28k
  {
96
5.28k
    someipsdhdroptionsipv4* hdr = reinterpret_cast<someipsdhdroptionsipv4*>(getDataPtr());
97
5.28k
    return hdr->l4Protocol;
98
5.28k
  }
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
727
      : SomeIpSdOption(dataContainer, offset)
130
727
  {
131
727
    m_DataLen = sizeof(someipsdhdroptionsipv6);
132
727
  }
133
134
  IPv6Address SomeIpSdIPv6Option::getIpAddress() const
135
501
  {
136
501
    someipsdhdroptionsipv6* hdr = reinterpret_cast<someipsdhdroptionsipv6*>(getDataPtr());
137
501
    IPv6Address ipAddr(hdr->ipv6Address);
138
139
501
    return ipAddr;
140
501
  }
141
142
  uint16_t SomeIpSdIPv6Option::getPort() const
143
501
  {
144
501
    someipsdhdroptionsipv6* hdr = reinterpret_cast<someipsdhdroptionsipv6*>(getDataPtr());
145
501
    return be16toh(hdr->portNumber);
146
501
  }
147
148
  SomeIpSdProtocolType SomeIpSdIPv6Option::getProtocol() const
149
501
  {
150
501
    someipsdhdroptionsipv6* hdr = reinterpret_cast<someipsdhdroptionsipv6*>(getDataPtr());
151
501
    return hdr->l4Protocol;
152
501
  }
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
346
      : SomeIpSdOption(dataContainer, offset)
169
346
  {
170
346
    m_DataLen = sizeof(someipsdhdroptionsbase) - 1 + be16toh(getSomeIpSdOptionHeader()->length);
171
346
  }
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
896
      : SomeIpSdOption(dataContainer, offset)
196
896
  {
197
896
    m_DataLen = sizeof(someipsdhdroptionsload);
198
896
  }
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
10.6k
      : m_Layer(pSomeIpSdLayer), m_Offset(offset), m_ShadowData(nullptr)
231
10.6k
  {
232
10.6k
    EntryType entryType;
233
234
10.6k
    someipsdhdrentry* hdr = getSomeIpSdEntryHeader();
235
10.6k
    TypeInternal internalType = static_cast<TypeInternal>(hdr->type);
236
10.6k
    auto ttl = getTtl();
237
238
10.6k
    switch (internalType)
239
10.6k
    {
240
850
    case SomeIpSdEntry::TypeInternal::FindService_Internal:
241
850
      entryType = SomeIpSdEntry::EntryType::FindService;
242
850
      break;
243
3.88k
    case SomeIpSdEntry::TypeInternal::OfferService_Internal:
244
3.88k
      if (ttl == 0)
245
2.45k
      {
246
2.45k
        entryType = EntryType::StopOfferService;
247
2.45k
      }
248
1.43k
      else
249
1.43k
      {
250
1.43k
        entryType = EntryType::OfferService;
251
1.43k
      }
252
3.88k
      break;
253
3.14k
    case SomeIpSdEntry::TypeInternal::SubscribeEventgroup_Internal:
254
3.14k
      if (ttl == 0)
255
2.12k
      {
256
2.12k
        entryType = EntryType::StopSubscribeEventgroup;
257
2.12k
      }
258
1.02k
      else
259
1.02k
      {
260
1.02k
        entryType = EntryType::SubscribeEventgroup;
261
1.02k
      }
262
3.14k
      break;
263
500
    case SomeIpSdEntry::TypeInternal::SubscribeEventgroupAck_Internal:
264
500
      if (ttl == 0)
265
93
      {
266
93
        entryType = EntryType::SubscribeEventgroupNack;
267
93
      }
268
407
      else
269
407
      {
270
407
        entryType = EntryType::SubscribeEventgroupAck;
271
407
      }
272
500
      break;
273
2.30k
    default:
274
2.30k
      entryType = EntryType::UnknownEntryType;
275
2.30k
      break;
276
10.6k
    }
277
278
10.6k
    m_EntryType = entryType;
279
10.6k
  }
280
281
  SomeIpSdEntry::~SomeIpSdEntry()
282
10.6k
  {
283
10.6k
    if (m_ShadowData != nullptr)
284
0
      delete[] m_ShadowData;
285
10.6k
  }
286
287
  uint8_t* SomeIpSdEntry::getDataPtr() const
288
96.2k
  {
289
96.2k
    if (m_Layer != nullptr)
290
96.2k
      return m_Layer->getDataPtr(m_Offset);
291
292
0
    return m_ShadowData;
293
96.2k
  }
294
295
  SomeIpSdEntry::someipsdhdrentry* SomeIpSdEntry::getSomeIpSdEntryHeader() const
296
96.2k
  {
297
96.2k
    return reinterpret_cast<someipsdhdrentry*>(getDataPtr());
298
96.2k
  }
299
300
  uint32_t SomeIpSdEntry::getNumOptions() const
301
10.6k
  {
302
10.6k
    auto* hdr = getSomeIpSdEntryHeader();
303
10.6k
    return hdr->nrOpt1 + hdr->nrOpt2;
304
10.6k
  }
305
306
  uint16_t SomeIpSdEntry::getServiceId() const
307
10.6k
  {
308
10.6k
    return be16toh(getSomeIpSdEntryHeader()->serviceID);
309
10.6k
  }
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
10.6k
  {
318
10.6k
    return be16toh(getSomeIpSdEntryHeader()->instanceID);
319
10.6k
  }
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
10.6k
  {
328
10.6k
    return (be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & ~SOMEIPSD_HDR_ENTRY_MASK_TTL) >> 24;
329
10.6k
  }
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
10.6k
  {
340
10.6k
    return be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & SOMEIPSD_HDR_ENTRY_MASK_TTL;
341
10.6k
  }
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
10.6k
  {
353
10.6k
    return be32toh(getSomeIpSdEntryHeader()->data);
354
10.6k
  }
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
10.6k
  {
363
10.6k
    return static_cast<uint8_t>((be32toh(getSomeIpSdEntryHeader()->data) >> 16) & 0x0F);
364
10.6k
  }
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
10.6k
  {
374
10.6k
    return static_cast<uint16_t>(be32toh(getSomeIpSdEntryHeader()->data) & 0x0000FFFF);
375
10.6k
  }
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
57.0k
      : SomeIpLayer(data, dataLen, prevLayer, packet)
434
57.0k
  {
435
57.0k
    countOptions(m_NumOptions, data);
436
57.0k
  }
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
10.2k
  {
460
10.2k
    someipsdhdr* hdr = reinterpret_cast<someipsdhdr*>(m_Data);
461
10.2k
    return hdr->flags;
462
10.2k
  }
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
30.6k
  {
472
30.6k
    return static_cast<uint32_t>(getLenEntries() / sizeof(SomeIpSdEntry::someipsdhdrentry));
473
30.6k
  }
474
475
  uint32_t SomeIpSdLayer::getNumOptions() const
476
20.5k
  {
477
20.5k
    return m_NumOptions;
478
20.5k
  }
479
480
  const SomeIpSdLayer::EntriesVec SomeIpSdLayer::getEntries() const
481
10.2k
  {
482
10.2k
    size_t remainingLen = getLenEntries();
483
10.2k
    size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t);
484
485
10.2k
    EntriesVec vecEntries;
486
10.2k
    EntryPtr entry;
487
488
20.9k
    while (remainingLen > 0)
489
10.8k
    {
490
      // Ensure there is enough remaining length for a new entry
491
10.8k
      if (remainingLen < sizeof(SomeIpSdEntry::someipsdhdrentry))
492
171
      {
493
171
        break;
494
171
      }
495
10.6k
      entry = new SomeIpSdEntry(this, offset);
496
497
10.6k
      size_t entryLen = entry->getLength();
498
10.6k
      remainingLen -= entryLen;
499
10.6k
      offset += entryLen;
500
501
10.6k
      vecEntries.push_back(entry);
502
10.6k
    }
503
504
10.2k
    return vecEntries;
505
10.2k
  };
506
507
  const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptions() const
508
10.2k
  {
509
10.2k
    OptionsVec vecOptions;
510
10.2k
    OptionPtr option;
511
512
10.2k
    size_t remainingLen = getLenOptions();
513
10.2k
    size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t);
514
515
20.6k
    while (remainingLen > 0)
516
10.4k
    {
517
10.4k
      SomeIpSdOption::someipsdhdroptionsbase* hdr =
518
10.4k
          reinterpret_cast<SomeIpSdOption::someipsdhdroptionsbase*>(m_Data + offset);
519
10.4k
      SomeIpSdOption::OptionType optionType = static_cast<SomeIpSdOption::OptionType>(hdr->type);
520
521
10.4k
      option = parseOption(optionType, offset, remainingLen);
522
523
10.4k
      if (option != nullptr)
524
6.57k
      {
525
6.57k
        vecOptions.push_back(std::move(option));
526
6.57k
      }
527
528
10.4k
      size_t optionLen = be16toh(hdr->length) + 3;
529
10.4k
      remainingLen -= optionLen;
530
10.4k
      offset += optionLen;
531
10.4k
    }
532
533
10.2k
    return vecOptions;
534
10.2k
  }
535
536
  const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptionsFromEntry(uint32_t index) const
537
10.1k
  {
538
10.1k
    OptionsVec vecOptions;
539
10.1k
    OptionPtr option;
540
541
10.1k
    if (index >= getNumEntries())
542
0
      return vecOptions;
543
544
10.1k
    size_t remainingLen = getLenOptions();
545
10.1k
    size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t);
546
547
10.1k
    size_t offsetToEntry = sizeof(someipsdhdr) + sizeof(uint32_t) + index * sizeof(SomeIpSdEntry::someipsdhdrentry);
548
10.1k
    SomeIpSdEntry::someipsdhdrentry* hdrEntry =
549
10.1k
        reinterpret_cast<SomeIpSdEntry::someipsdhdrentry*>(m_Data + offsetToEntry);
550
10.1k
    uint8_t startIdxRun1 = hdrEntry->indexFirstOption;
551
10.1k
    uint8_t lenRun1 = hdrEntry->nrOpt1;
552
10.1k
    uint8_t startIdxRun2 = hdrEntry->indexSecondOption;
553
10.1k
    uint8_t lenRun2 = hdrEntry->nrOpt2;
554
555
10.1k
    int idx = 0;
556
557
20.3k
    while (remainingLen > 0)
558
10.2k
    {
559
10.2k
      SomeIpSdOption::someipsdhdroptionsbase* hdrOption =
560
10.2k
          reinterpret_cast<SomeIpSdOption::someipsdhdroptionsbase*>(m_Data + offset);
561
562
10.2k
      if (((idx >= startIdxRun1) && (idx < (startIdxRun1 + lenRun1))) ||
563
5.35k
          ((idx >= startIdxRun2) && (idx < (startIdxRun2 + lenRun2))))
564
6.77k
      {
565
6.77k
        SomeIpSdOption::OptionType optionType = static_cast<SomeIpSdOption::OptionType>(hdrOption->type);
566
567
6.77k
        option = parseOption(optionType, offset, remainingLen);
568
569
6.77k
        if (option != nullptr)
570
5.44k
        {
571
5.44k
          vecOptions.push_back(std::move(option));
572
5.44k
        }
573
6.77k
      }
574
575
10.2k
      size_t optionLen = be16toh(hdrOption->length) + 3;
576
10.2k
      remainingLen -= optionLen;
577
10.2k
      offset += optionLen;
578
10.2k
      ++idx;
579
10.2k
    }
580
581
10.1k
    return vecOptions;
582
10.1k
  }
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
20.5k
  {
609
20.5k
    std::stringstream dataStream;
610
611
20.5k
    dataStream << "SOME/IP-SD Layer, " << getNumEntries() << " entries, " << getNumOptions() << " options";
612
613
20.5k
    return dataStream.str();
614
20.5k
  }
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
73.2k
  {
635
73.2k
    uint32_t count;
636
73.2k
    if (!data || dataLen < sizeof(someipsdhdr) + sizeof(uint32_t) ||
637
73.2k
        dataLen < sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t) ||
638
69.8k
        dataLen <
639
69.8k
            sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t) + getLenOptions(data) ||
640
68.4k
        !countOptions(count, data))
641
16.1k
    {
642
16.1k
      return false;
643
16.1k
    }
644
645
57.0k
    return true;
646
73.2k
  }
647
648
  bool SomeIpSdLayer::countOptions(uint32_t& count, const uint8_t* data)
649
125k
  {
650
125k
    size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t);
651
125k
    size_t lenOptions = getLenOptions(data);
652
125k
    uint32_t len = 0;
653
654
125k
    count = 0;
655
240k
    while (len < lenOptions)
656
126k
    {
657
126k
      if (len + sizeof(uint16_t) + 3 * sizeof(uint8_t) > lenOptions)
658
0
        return false;
659
660
126k
      uint32_t lenOption =
661
126k
          be16toh(*(reinterpret_cast<uint16_t const*>(data + offsetOption + len))) + 3 * sizeof(uint8_t);
662
126k
      len += lenOption;
663
126k
      if (len > lenOptions)  // the last one must be equal to lenOptions
664
11.4k
        return false;
665
666
115k
      ++(count);
667
115k
    }
668
114k
    return true;
669
125k
  }
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
17.1k
  {
763
17.1k
    switch (type)
764
17.1k
    {
765
1.87k
    case SomeIpSdOption::OptionType::IPv4Endpoint:
766
2.25k
    case SomeIpSdOption::OptionType::IPv4Multicast:
767
10.0k
    case SomeIpSdOption::OptionType::IPv4SdEndpoint:
768
10.0k
    {
769
10.0k
      if (SomeIpSdIPv4Option::isDataValid(this, remainingLength))
770
10.0k
      {
771
10.0k
        return new SomeIpSdIPv4Option(this, offset);
772
10.0k
      }
773
0
      return nullptr;
774
10.0k
    }
775
99
    case SomeIpSdOption::OptionType::IPv6Endpoint:
776
367
    case SomeIpSdOption::OptionType::IPv6Multicast:
777
798
    case SomeIpSdOption::OptionType::IPv6SdEndpoint:
778
798
    {
779
798
      if (SomeIpSdIPv6Option::isDataValid(this, remainingLength))
780
727
      {
781
727
        return new SomeIpSdIPv6Option(this, offset);
782
727
      }
783
71
      return nullptr;
784
798
    }
785
346
    case SomeIpSdOption::OptionType::ConfigurationString:
786
346
    {
787
346
      if (SomeIpSdConfigurationOption::isDataValid(this, remainingLength))
788
346
      {
789
346
        return new SomeIpSdConfigurationOption(this, offset);
790
346
      }
791
0
      return nullptr;
792
346
    }
793
896
    case SomeIpSdOption::OptionType::LoadBalancing:
794
896
    {
795
896
      if (SomeIpSdLoadBalancingOption::isDataValid(this, remainingLength))
796
896
      {
797
896
        return new SomeIpSdLoadBalancingOption(this, offset);
798
896
      }
799
0
      return nullptr;
800
896
    }
801
5.08k
    default:
802
5.08k
      break;
803
17.1k
    }
804
5.08k
    return nullptr;
805
17.1k
  }
806
807
  size_t SomeIpSdLayer::getLenEntries() const
808
61.3k
  {
809
61.3k
    return getLenEntries(m_Data);
810
61.3k
  }
811
812
  size_t SomeIpSdLayer::getLenEntries(const uint8_t* data)
813
545k
  {
814
545k
    return be32toh(*(reinterpret_cast<const uint32_t*>(data + sizeof(someipsdhdr))));
815
545k
  }
816
817
  size_t SomeIpSdLayer::getLenOptions() const
818
20.4k
  {
819
20.4k
    return getLenOptions(m_Data);
820
20.4k
  }
821
822
  size_t SomeIpSdLayer::getLenOptions(const uint8_t* data)
823
215k
  {
824
215k
    return be32toh(
825
215k
        *(reinterpret_cast<const uint32_t*>(data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data))));
826
215k
  }
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