/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 |