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