1 /*
2 * Copyright (c) 2016, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /**
30 * @file
31 * This file implements common methods for manipulating Thread Network Data.
32 */
33
34 #include "network_data.hpp"
35
36 #include "coap/coap_message.hpp"
37 #include "common/code_utils.hpp"
38 #include "common/debug.hpp"
39 #include "common/instance.hpp"
40 #include "common/locator_getters.hpp"
41 #include "common/logging.hpp"
42 #include "mac/mac_types.hpp"
43 #include "thread/thread_netif.hpp"
44 #include "thread/thread_tlvs.hpp"
45 #include "thread/uri_paths.hpp"
46
47 namespace ot {
48 namespace NetworkData {
49
NetworkData(Instance & aInstance,Type aType)50 NetworkData::NetworkData(Instance &aInstance, Type aType)
51 : InstanceLocator(aInstance)
52 , mType(aType)
53 {
54 mLength = 0;
55 }
56
GetNetworkData(bool aStable,uint8_t * aData,uint8_t & aDataLength) const57 Error NetworkData::GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength) const
58 {
59 Error error = kErrorNone;
60
61 OT_ASSERT(aData != nullptr);
62 VerifyOrExit(aDataLength >= mLength, error = kErrorNoBufs);
63
64 memcpy(aData, mTlvs, mLength);
65 aDataLength = mLength;
66
67 if (aStable)
68 {
69 RemoveTemporaryData(aData, aDataLength);
70 }
71
72 exit:
73 return error;
74 }
75
GetNextOnMeshPrefix(Iterator & aIterator,OnMeshPrefixConfig & aConfig) const76 Error NetworkData::GetNextOnMeshPrefix(Iterator &aIterator, OnMeshPrefixConfig &aConfig) const
77 {
78 return GetNextOnMeshPrefix(aIterator, Mac::kShortAddrBroadcast, aConfig);
79 }
80
GetNextOnMeshPrefix(Iterator & aIterator,uint16_t aRloc16,OnMeshPrefixConfig & aConfig) const81 Error NetworkData::GetNextOnMeshPrefix(Iterator &aIterator, uint16_t aRloc16, OnMeshPrefixConfig &aConfig) const
82 {
83 Config config;
84
85 config.mOnMeshPrefix = &aConfig;
86 config.mExternalRoute = nullptr;
87 config.mService = nullptr;
88
89 return Iterate(aIterator, aRloc16, config);
90 }
91
GetNextExternalRoute(Iterator & aIterator,ExternalRouteConfig & aConfig) const92 Error NetworkData::GetNextExternalRoute(Iterator &aIterator, ExternalRouteConfig &aConfig) const
93 {
94 return GetNextExternalRoute(aIterator, Mac::kShortAddrBroadcast, aConfig);
95 }
96
GetNextExternalRoute(Iterator & aIterator,uint16_t aRloc16,ExternalRouteConfig & aConfig) const97 Error NetworkData::GetNextExternalRoute(Iterator &aIterator, uint16_t aRloc16, ExternalRouteConfig &aConfig) const
98 {
99 Config config;
100
101 config.mOnMeshPrefix = nullptr;
102 config.mExternalRoute = &aConfig;
103 config.mService = nullptr;
104
105 return Iterate(aIterator, aRloc16, config);
106 }
107
GetNextService(Iterator & aIterator,ServiceConfig & aConfig) const108 Error NetworkData::GetNextService(Iterator &aIterator, ServiceConfig &aConfig) const
109 {
110 return GetNextService(aIterator, Mac::kShortAddrBroadcast, aConfig);
111 }
112
GetNextService(Iterator & aIterator,uint16_t aRloc16,ServiceConfig & aConfig) const113 Error NetworkData::GetNextService(Iterator &aIterator, uint16_t aRloc16, ServiceConfig &aConfig) const
114 {
115 Config config;
116
117 config.mOnMeshPrefix = nullptr;
118 config.mExternalRoute = nullptr;
119 config.mService = &aConfig;
120
121 return Iterate(aIterator, aRloc16, config);
122 }
123
Iterate(Iterator & aIterator,uint16_t aRloc16,Config & aConfig) const124 Error NetworkData::Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aConfig) const
125 {
126 // Iterate to the next entry in Network Data matching `aRloc16`
127 // (can be set to `Mac::kShortAddrBroadcast` to allow any RLOC).
128 // The `aIterator` is used to track and save the current position.
129 // On input, the non-nullptr pointer members in `aConfig` specify the
130 // Network Data entry types (`mOnMeshPrefix`, `mExternalRoute`,
131 // `mService`) to iterate over. On successful exit, the `aConfig`
132 // is updated such that only one member pointer is not nullptr
133 // indicating the type of entry and the non-nullptr config is updated
134 // with the entry info.
135
136 Error error = kErrorNotFound;
137 NetworkDataIterator iterator(aIterator);
138
139 for (const NetworkDataTlv *cur;
140 cur = iterator.GetTlv(mTlvs), (cur + 1 <= GetTlvsEnd()) && (cur->GetNext() <= GetTlvsEnd());
141 iterator.AdvanceTlv(mTlvs))
142 {
143 const NetworkDataTlv *subTlvs = nullptr;
144
145 switch (cur->GetType())
146 {
147 case NetworkDataTlv::kTypePrefix:
148 if ((aConfig.mOnMeshPrefix != nullptr) || (aConfig.mExternalRoute != nullptr))
149 {
150 subTlvs = static_cast<const PrefixTlv *>(cur)->GetSubTlvs();
151 }
152 break;
153 case NetworkDataTlv::kTypeService:
154 if (aConfig.mService != nullptr)
155 {
156 subTlvs = static_cast<const ServiceTlv *>(cur)->GetSubTlvs();
157 }
158 break;
159 default:
160 break;
161 }
162
163 if (subTlvs == nullptr)
164 {
165 continue;
166 }
167
168 for (const NetworkDataTlv *subCur; subCur = iterator.GetSubTlv(subTlvs),
169 (subCur + 1 <= cur->GetNext()) && (subCur->GetNext() <= cur->GetNext());
170 iterator.AdvaceSubTlv(subTlvs))
171 {
172 if (cur->GetType() == NetworkDataTlv::kTypePrefix)
173 {
174 const PrefixTlv *prefixTlv = static_cast<const PrefixTlv *>(cur);
175
176 switch (subCur->GetType())
177 {
178 case NetworkDataTlv::kTypeBorderRouter:
179 {
180 const BorderRouterTlv *borderRouter = static_cast<const BorderRouterTlv *>(subCur);
181
182 if (aConfig.mOnMeshPrefix == nullptr)
183 {
184 continue;
185 }
186
187 for (uint8_t index; (index = iterator.GetAndAdvanceIndex()) < borderRouter->GetNumEntries();)
188 {
189 if (aRloc16 == Mac::kShortAddrBroadcast || borderRouter->GetEntry(index)->GetRloc() == aRloc16)
190 {
191 const BorderRouterEntry *borderRouterEntry = borderRouter->GetEntry(index);
192
193 aConfig.mExternalRoute = nullptr;
194 aConfig.mService = nullptr;
195 aConfig.mOnMeshPrefix->SetFrom(*prefixTlv, *borderRouter, *borderRouterEntry);
196
197 ExitNow(error = kErrorNone);
198 }
199 }
200
201 break;
202 }
203
204 case NetworkDataTlv::kTypeHasRoute:
205 {
206 const HasRouteTlv *hasRoute = static_cast<const HasRouteTlv *>(subCur);
207
208 if (aConfig.mExternalRoute == nullptr)
209 {
210 continue;
211 }
212
213 for (uint8_t index; (index = iterator.GetAndAdvanceIndex()) < hasRoute->GetNumEntries();)
214 {
215 if (aRloc16 == Mac::kShortAddrBroadcast || hasRoute->GetEntry(index)->GetRloc() == aRloc16)
216 {
217 const HasRouteEntry *hasRouteEntry = hasRoute->GetEntry(index);
218
219 aConfig.mOnMeshPrefix = nullptr;
220 aConfig.mService = nullptr;
221 aConfig.mExternalRoute->SetFrom(GetInstance(), *prefixTlv, *hasRoute, *hasRouteEntry);
222
223 ExitNow(error = kErrorNone);
224 }
225 }
226
227 break;
228 }
229
230 default:
231 break;
232 }
233 }
234 else // cur is `ServiceTLv`
235 {
236 const ServiceTlv *service = static_cast<const ServiceTlv *>(cur);
237
238 if (aConfig.mService == nullptr)
239 {
240 continue;
241 }
242
243 if (subCur->GetType() == NetworkDataTlv::kTypeServer)
244 {
245 const ServerTlv *server = static_cast<const ServerTlv *>(subCur);
246
247 if (!iterator.IsNewEntry())
248 {
249 continue;
250 }
251
252 if ((aRloc16 == Mac::kShortAddrBroadcast) || (server->GetServer16() == aRloc16))
253 {
254 aConfig.mOnMeshPrefix = nullptr;
255 aConfig.mExternalRoute = nullptr;
256 aConfig.mService->SetFrom(*service, *server);
257
258 iterator.MarkEntryAsNotNew();
259
260 ExitNow(error = kErrorNone);
261 }
262 }
263 }
264 }
265 }
266
267 exit:
268 return error;
269 }
270
GetNextServiceId(Iterator & aIterator,uint16_t aRloc16,uint8_t & aServiceId) const271 Error NetworkData::GetNextServiceId(Iterator &aIterator, uint16_t aRloc16, uint8_t &aServiceId) const
272 {
273 Error error;
274 ServiceConfig config;
275
276 SuccessOrExit(error = GetNextService(aIterator, aRloc16, config));
277 aServiceId = config.mServiceId;
278
279 exit:
280 return error;
281 }
282
ContainsOnMeshPrefixes(const NetworkData & aCompare,uint16_t aRloc16) const283 bool NetworkData::ContainsOnMeshPrefixes(const NetworkData &aCompare, uint16_t aRloc16) const
284 {
285 Iterator outerIterator = kIteratorInit;
286 OnMeshPrefixConfig outerConfig;
287 bool rval = true;
288
289 while (aCompare.GetNextOnMeshPrefix(outerIterator, aRloc16, outerConfig) == kErrorNone)
290 {
291 Iterator innerIterator = kIteratorInit;
292 OnMeshPrefixConfig innerConfig;
293 Error error;
294
295 while ((error = GetNextOnMeshPrefix(innerIterator, aRloc16, innerConfig)) == kErrorNone)
296 {
297 if (outerConfig == innerConfig)
298 {
299 break;
300 }
301 }
302
303 if (error != kErrorNone)
304 {
305 ExitNow(rval = false);
306 }
307 }
308
309 exit:
310 return rval;
311 }
312
ContainsExternalRoutes(const NetworkData & aCompare,uint16_t aRloc16) const313 bool NetworkData::ContainsExternalRoutes(const NetworkData &aCompare, uint16_t aRloc16) const
314 {
315 Iterator outerIterator = kIteratorInit;
316 ExternalRouteConfig outerConfig;
317 bool rval = true;
318
319 while (aCompare.GetNextExternalRoute(outerIterator, aRloc16, outerConfig) == kErrorNone)
320 {
321 Iterator innerIterator = kIteratorInit;
322 ExternalRouteConfig innerConfig;
323 Error error;
324
325 while ((error = GetNextExternalRoute(innerIterator, aRloc16, innerConfig)) == kErrorNone)
326 {
327 if (outerConfig == innerConfig)
328 {
329 break;
330 }
331 }
332
333 if (error != kErrorNone)
334 {
335 ExitNow(rval = false);
336 }
337 }
338
339 exit:
340 return rval;
341 }
342
ContainsServices(const NetworkData & aCompare,uint16_t aRloc16) const343 bool NetworkData::ContainsServices(const NetworkData &aCompare, uint16_t aRloc16) const
344 {
345 Iterator outerIterator = kIteratorInit;
346 ServiceConfig outerConfig;
347 bool rval = true;
348
349 while (aCompare.GetNextService(outerIterator, aRloc16, outerConfig) == kErrorNone)
350 {
351 Iterator innerIterator = kIteratorInit;
352 ServiceConfig innerConfig;
353 Error error;
354
355 while ((error = GetNextService(innerIterator, aRloc16, innerConfig)) == kErrorNone)
356 {
357 if (outerConfig == innerConfig)
358 {
359 break;
360 }
361 }
362
363 if (error != kErrorNone)
364 {
365 ExitNow(rval = false);
366 }
367 }
368
369 exit:
370 return rval;
371 }
372
ContainsService(uint8_t aServiceId,uint16_t aRloc16) const373 bool NetworkData::ContainsService(uint8_t aServiceId, uint16_t aRloc16) const
374 {
375 Iterator iterator = kIteratorInit;
376 uint8_t serviceId;
377 bool rval = false;
378
379 while (GetNextServiceId(iterator, aRloc16, serviceId) == kErrorNone)
380 {
381 if (serviceId == aServiceId)
382 {
383 ExitNow(rval = true);
384 }
385 }
386
387 exit:
388 return rval;
389 }
390
RemoveTemporaryData(uint8_t * aData,uint8_t & aDataLength)391 void NetworkData::RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength)
392 {
393 NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(aData);
394
395 while (cur < reinterpret_cast<NetworkDataTlv *>(aData + aDataLength))
396 {
397 switch (cur->GetType())
398 {
399 case NetworkDataTlv::kTypePrefix:
400 {
401 PrefixTlv *prefix = static_cast<PrefixTlv *>(cur);
402
403 RemoveTemporaryData(aData, aDataLength, *prefix);
404
405 if (prefix->GetSubTlvsLength() == 0)
406 {
407 RemoveTlv(aData, aDataLength, cur);
408 continue;
409 }
410
411 otDumpDebgNetData("remove prefix done", aData, aDataLength);
412 break;
413 }
414
415 case NetworkDataTlv::kTypeService:
416 {
417 ServiceTlv *service = static_cast<ServiceTlv *>(cur);
418 RemoveTemporaryData(aData, aDataLength, *service);
419
420 if (service->GetSubTlvsLength() == 0)
421 {
422 RemoveTlv(aData, aDataLength, cur);
423 continue;
424 }
425
426 otDumpDebgNetData("remove service done", aData, aDataLength);
427 break;
428 }
429
430 default:
431 // remove temporary tlv
432 if (!cur->IsStable())
433 {
434 RemoveTlv(aData, aDataLength, cur);
435 continue;
436 }
437
438 break;
439 }
440
441 cur = cur->GetNext();
442 }
443
444 otDumpDebgNetData("remove done", aData, aDataLength);
445 }
446
RemoveTemporaryData(uint8_t * aData,uint8_t & aDataLength,PrefixTlv & aPrefix)447 void NetworkData::RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength, PrefixTlv &aPrefix)
448 {
449 NetworkDataTlv *cur = aPrefix.GetSubTlvs();
450
451 while (cur < aPrefix.GetNext())
452 {
453 if (cur->IsStable())
454 {
455 switch (cur->GetType())
456 {
457 case NetworkDataTlv::kTypeBorderRouter:
458 {
459 BorderRouterTlv *borderRouter = static_cast<BorderRouterTlv *>(cur);
460 ContextTlv * context = aPrefix.FindSubTlv<ContextTlv>();
461
462 // Replace p_border_router_16
463 for (BorderRouterEntry *entry = borderRouter->GetFirstEntry(); entry <= borderRouter->GetLastEntry();
464 entry = entry->GetNext())
465 {
466 if ((entry->IsDhcp() || entry->IsConfigure()) && (context != nullptr))
467 {
468 entry->SetRloc(0xfc00 | context->GetContextId());
469 }
470 else
471 {
472 entry->SetRloc(0xfffe);
473 }
474 }
475
476 break;
477 }
478
479 case NetworkDataTlv::kTypeHasRoute:
480 {
481 HasRouteTlv *hasRoute = static_cast<HasRouteTlv *>(cur);
482
483 // Replace r_border_router_16
484 for (HasRouteEntry *entry = hasRoute->GetFirstEntry(); entry <= hasRoute->GetLastEntry();
485 entry = entry->GetNext())
486 {
487 entry->SetRloc(0xfffe);
488 }
489
490 break;
491 }
492
493 default:
494 break;
495 }
496
497 // keep stable tlv
498 cur = cur->GetNext();
499 }
500 else
501 {
502 // remove temporary tlv
503 uint8_t subTlvSize = cur->GetSize();
504 RemoveTlv(aData, aDataLength, cur);
505 aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - subTlvSize);
506 }
507 }
508 }
509
RemoveTemporaryData(uint8_t * aData,uint8_t & aDataLength,ServiceTlv & aService)510 void NetworkData::RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength, ServiceTlv &aService)
511 {
512 NetworkDataTlv *cur = aService.GetSubTlvs();
513
514 while (cur < aService.GetNext())
515 {
516 if (cur->IsStable())
517 {
518 switch (cur->GetType())
519 {
520 case NetworkDataTlv::kTypeServer:
521 {
522 ServerTlv *server = static_cast<ServerTlv *>(cur);
523 server->SetServer16(Mle::Mle::ServiceAlocFromId(aService.GetServiceId()));
524 break;
525 }
526
527 default:
528 break;
529 }
530
531 // keep stable tlv
532 cur = cur->GetNext();
533 }
534 else
535 {
536 // remove temporary tlv
537 uint8_t subTlvSize = cur->GetSize();
538 RemoveTlv(aData, aDataLength, cur);
539 aService.SetSubTlvsLength(aService.GetSubTlvsLength() - subTlvSize);
540 }
541 }
542 }
543
FindPrefix(const uint8_t * aPrefix,uint8_t aPrefixLength) const544 const PrefixTlv *NetworkData::FindPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) const
545 {
546 return FindPrefix(aPrefix, aPrefixLength, mTlvs, mLength);
547 }
548
FindPrefix(const uint8_t * aPrefix,uint8_t aPrefixLength,const uint8_t * aTlvs,uint8_t aTlvsLength)549 const PrefixTlv *NetworkData::FindPrefix(const uint8_t *aPrefix,
550 uint8_t aPrefixLength,
551 const uint8_t *aTlvs,
552 uint8_t aTlvsLength)
553 {
554 TlvIterator tlvIterator(aTlvs, aTlvsLength);
555 const PrefixTlv *prefixTlv;
556
557 while ((prefixTlv = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
558 {
559 if (prefixTlv->IsEqual(aPrefix, aPrefixLength))
560 {
561 break;
562 }
563 }
564
565 return prefixTlv;
566 }
567
FindService(uint32_t aEnterpriseNumber,const uint8_t * aServiceData,uint8_t aServiceDataLength,ServiceMatchMode aServiceMatchMode) const568 const ServiceTlv *NetworkData::FindService(uint32_t aEnterpriseNumber,
569 const uint8_t * aServiceData,
570 uint8_t aServiceDataLength,
571 ServiceMatchMode aServiceMatchMode) const
572 {
573 return FindService(aEnterpriseNumber, aServiceData, aServiceDataLength, aServiceMatchMode, mTlvs, mLength);
574 }
575
FindService(uint32_t aEnterpriseNumber,const uint8_t * aServiceData,uint8_t aServiceDataLength,ServiceMatchMode aServiceMatchMode,const uint8_t * aTlvs,uint8_t aTlvsLength)576 const ServiceTlv *NetworkData::FindService(uint32_t aEnterpriseNumber,
577 const uint8_t * aServiceData,
578 uint8_t aServiceDataLength,
579 ServiceMatchMode aServiceMatchMode,
580 const uint8_t * aTlvs,
581 uint8_t aTlvsLength)
582 {
583 TlvIterator tlvIterator(aTlvs, aTlvsLength);
584 const ServiceTlv *serviceTlv;
585
586 while ((serviceTlv = tlvIterator.Iterate<ServiceTlv>()) != nullptr)
587 {
588 if (MatchService(*serviceTlv, aEnterpriseNumber, aServiceData, aServiceDataLength, aServiceMatchMode))
589 {
590 break;
591 }
592 }
593
594 return serviceTlv;
595 }
596
FindNextService(const ServiceTlv * aPrevServiceTlv,uint32_t aEnterpriseNumber,const uint8_t * aServiceData,uint8_t aServiceDataLength,ServiceMatchMode aServiceMatchMode) const597 const ServiceTlv *NetworkData::FindNextService(const ServiceTlv *aPrevServiceTlv,
598 uint32_t aEnterpriseNumber,
599 const uint8_t * aServiceData,
600 uint8_t aServiceDataLength,
601 ServiceMatchMode aServiceMatchMode) const
602 {
603 const uint8_t *tlvs;
604 uint8_t length;
605
606 if (aPrevServiceTlv == nullptr)
607 {
608 tlvs = mTlvs;
609 length = mLength;
610 }
611 else
612 {
613 tlvs = reinterpret_cast<const uint8_t *>(aPrevServiceTlv->GetNext());
614 length = static_cast<uint8_t>((mTlvs + mLength) - tlvs);
615 }
616
617 return FindService(aEnterpriseNumber, aServiceData, aServiceDataLength, aServiceMatchMode, tlvs, length);
618 }
619
MatchService(const ServiceTlv & aServiceTlv,uint32_t aEnterpriseNumber,const uint8_t * aServiceData,uint8_t aServiceDataLength,ServiceMatchMode aServiceMatchMode)620 bool NetworkData::MatchService(const ServiceTlv &aServiceTlv,
621 uint32_t aEnterpriseNumber,
622 const uint8_t * aServiceData,
623 uint8_t aServiceDataLength,
624 ServiceMatchMode aServiceMatchMode)
625 {
626 bool match = false;
627
628 VerifyOrExit(aServiceTlv.GetEnterpriseNumber() == aEnterpriseNumber &&
629 aServiceTlv.GetServiceDataLength() >= aServiceDataLength);
630
631 switch (aServiceMatchMode)
632 {
633 case kServiceExactMatch:
634 VerifyOrExit(aServiceTlv.GetServiceDataLength() == aServiceDataLength);
635 OT_FALL_THROUGH;
636
637 case kServicePrefixMatch:
638 VerifyOrExit(memcmp(aServiceTlv.GetServiceData(), aServiceData, aServiceDataLength) == 0);
639 break;
640 }
641
642 match = true;
643
644 exit:
645 return match;
646 }
647
AppendTlv(uint16_t aTlvSize)648 NetworkDataTlv *NetworkData::AppendTlv(uint16_t aTlvSize)
649 {
650 NetworkDataTlv *tlv;
651
652 VerifyOrExit(CanInsert(aTlvSize), tlv = nullptr);
653
654 tlv = GetTlvsEnd();
655 mLength += static_cast<uint8_t>(aTlvSize);
656
657 exit:
658 return tlv;
659 }
660
Insert(void * aStart,uint8_t aLength)661 void NetworkData::Insert(void *aStart, uint8_t aLength)
662 {
663 uint8_t *start = reinterpret_cast<uint8_t *>(aStart);
664
665 OT_ASSERT(CanInsert(aLength) && mTlvs <= start && start <= mTlvs + mLength);
666 memmove(start + aLength, start, mLength - static_cast<size_t>(start - mTlvs));
667 mLength += aLength;
668 }
669
Remove(uint8_t * aData,uint8_t & aDataLength,uint8_t * aRemoveStart,uint8_t aRemoveLength)670 void NetworkData::Remove(uint8_t *aData, uint8_t &aDataLength, uint8_t *aRemoveStart, uint8_t aRemoveLength)
671 {
672 uint8_t *dataEnd = aData + aDataLength;
673 uint8_t *removeEnd = aRemoveStart + aRemoveLength;
674
675 OT_ASSERT((aRemoveLength <= aDataLength) && (aData <= aRemoveStart) && (removeEnd <= dataEnd));
676
677 memmove(aRemoveStart, removeEnd, static_cast<uint8_t>(dataEnd - removeEnd));
678 aDataLength -= aRemoveLength;
679 }
680
RemoveTlv(uint8_t * aData,uint8_t & aDataLength,NetworkDataTlv * aTlv)681 void NetworkData::RemoveTlv(uint8_t *aData, uint8_t &aDataLength, NetworkDataTlv *aTlv)
682 {
683 Remove(aData, aDataLength, reinterpret_cast<uint8_t *>(aTlv), aTlv->GetSize());
684 }
685
Remove(void * aRemoveStart,uint8_t aRemoveLength)686 void NetworkData::Remove(void *aRemoveStart, uint8_t aRemoveLength)
687 {
688 NetworkData::Remove(mTlvs, mLength, reinterpret_cast<uint8_t *>(aRemoveStart), aRemoveLength);
689 }
690
RemoveTlv(NetworkDataTlv * aTlv)691 void NetworkData::RemoveTlv(NetworkDataTlv *aTlv)
692 {
693 NetworkData::RemoveTlv(mTlvs, mLength, aTlv);
694 }
695
SendServerDataNotification(uint16_t aRloc16,Coap::ResponseHandler aHandler,void * aContext)696 Error NetworkData::SendServerDataNotification(uint16_t aRloc16, Coap::ResponseHandler aHandler, void *aContext)
697 {
698 Error error = kErrorNone;
699 Coap::Message * message = nullptr;
700 Ip6::MessageInfo messageInfo;
701
702 VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
703
704 SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kServerData));
705 SuccessOrExit(error = message->SetPayloadMarker());
706
707 if (mType == kTypeLocal)
708 {
709 ThreadTlv tlv;
710 tlv.SetType(ThreadTlv::kThreadNetworkData);
711 tlv.SetLength(mLength);
712 SuccessOrExit(error = message->Append(tlv));
713 SuccessOrExit(error = message->AppendBytes(mTlvs, mLength));
714 }
715
716 if (aRloc16 != Mac::kShortAddrInvalid)
717 {
718 SuccessOrExit(error = Tlv::Append<ThreadRloc16Tlv>(*message, aRloc16));
719 }
720
721 IgnoreError(Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
722 messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
723 messageInfo.SetPeerPort(Tmf::kUdpPort);
724 SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, aHandler, aContext));
725
726 otLogInfoNetData("Sent server data notification");
727
728 exit:
729 FreeMessageOnError(message, error);
730 return error;
731 }
732
GetNextServer(Iterator & aIterator,uint16_t & aRloc16) const733 Error NetworkData::GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const
734 {
735 Error error;
736 OnMeshPrefixConfig prefixConfig;
737 ExternalRouteConfig routeConfig;
738 ServiceConfig serviceConfig;
739 Config config;
740
741 config.mOnMeshPrefix = &prefixConfig;
742 config.mExternalRoute = &routeConfig;
743 config.mService = &serviceConfig;
744
745 SuccessOrExit(error = Iterate(aIterator, Mac::kShortAddrBroadcast, config));
746
747 if (config.mOnMeshPrefix != nullptr)
748 {
749 aRloc16 = config.mOnMeshPrefix->mRloc16;
750 }
751 else if (config.mExternalRoute != nullptr)
752 {
753 aRloc16 = config.mExternalRoute->mRloc16;
754 }
755 else if (config.mService != nullptr)
756 {
757 aRloc16 = config.mService->mServerConfig.mRloc16;
758 }
759 else
760 {
761 OT_ASSERT(false);
762 }
763
764 exit:
765 return error;
766 }
767
768 } // namespace NetworkData
769 } // namespace ot
770