• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 the Thread Network Data managed by the Thread Leader.
32  */
33 
34 #include "network_data_leader.hpp"
35 
36 #include "coap/coap_message.hpp"
37 #include "common/code_utils.hpp"
38 #include "common/debug.hpp"
39 #include "common/encoding.hpp"
40 #include "common/instance.hpp"
41 #include "common/locator_getters.hpp"
42 #include "common/logging.hpp"
43 #include "common/message.hpp"
44 #include "common/random.hpp"
45 #include "common/timer.hpp"
46 #include "mac/mac_types.hpp"
47 #include "thread/lowpan.hpp"
48 #include "thread/mle_router.hpp"
49 #include "thread/thread_netif.hpp"
50 #include "thread/thread_tlvs.hpp"
51 #include "thread/uri_paths.hpp"
52 
53 namespace ot {
54 namespace NetworkData {
55 
56 RegisterLogModule("NetworkData");
57 
Reset(void)58 void LeaderBase::Reset(void)
59 {
60     mVersion       = Random::NonCrypto::GetUint8();
61     mStableVersion = Random::NonCrypto::GetUint8();
62     SetLength(0);
63     Get<ot::Notifier>().Signal(kEventThreadNetdataChanged);
64 }
65 
GetServiceId(uint32_t aEnterpriseNumber,const ServiceData & aServiceData,bool aServerStable,uint8_t & aServiceId) const66 Error LeaderBase::GetServiceId(uint32_t           aEnterpriseNumber,
67                                const ServiceData &aServiceData,
68                                bool               aServerStable,
69                                uint8_t &          aServiceId) const
70 {
71     Error         error    = kErrorNotFound;
72     Iterator      iterator = kIteratorInit;
73     ServiceConfig serviceConfig;
74     ServiceData   serviceData;
75 
76     while (GetNextService(iterator, serviceConfig) == kErrorNone)
77     {
78         serviceConfig.GetServiceData(serviceData);
79 
80         if (aEnterpriseNumber == serviceConfig.mEnterpriseNumber && aServiceData == serviceData &&
81             aServerStable == serviceConfig.mServerConfig.mStable)
82         {
83             aServiceId = serviceConfig.mServiceId;
84             ExitNow(error = kErrorNone);
85         }
86     }
87 
88 exit:
89     return error;
90 }
91 
GetPreferredNat64Prefix(ExternalRouteConfig & aConfig) const92 Error LeaderBase::GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const
93 {
94     Error               error    = kErrorNotFound;
95     Iterator            iterator = kIteratorInit;
96     ExternalRouteConfig config;
97 
98     while (GetNextExternalRoute(iterator, config) == kErrorNone)
99     {
100         if (!config.mNat64 || !config.GetPrefix().IsValidNat64())
101         {
102             continue;
103         }
104 
105         if ((error == kErrorNotFound) || (config.mPreference > aConfig.mPreference))
106         {
107             aConfig = config;
108             error   = kErrorNone;
109         }
110     }
111 
112     return error;
113 }
114 
FindNextMatchingPrefix(const Ip6::Address & aAddress,const PrefixTlv * aPrevTlv) const115 const PrefixTlv *LeaderBase::FindNextMatchingPrefix(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const
116 {
117     const PrefixTlv *prefixTlv;
118     TlvIterator      tlvIterator((aPrevTlv == nullptr) ? GetTlvsStart() : aPrevTlv->GetNext(), GetTlvsEnd());
119 
120     while ((prefixTlv = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
121     {
122         if (aAddress.MatchesPrefix(prefixTlv->GetPrefix(), prefixTlv->GetPrefixLength()))
123         {
124             break;
125         }
126     }
127 
128     return prefixTlv;
129 }
130 
GetContext(const Ip6::Address & aAddress,Lowpan::Context & aContext) const131 Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const
132 {
133     const PrefixTlv * prefix = nullptr;
134     const ContextTlv *contextTlv;
135 
136     aContext.mPrefix.SetLength(0);
137 
138     if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
139     {
140         aContext.mPrefix.Set(Get<Mle::MleRouter>().GetMeshLocalPrefix());
141         aContext.mContextId    = Mle::kMeshLocalPrefixContextId;
142         aContext.mCompressFlag = true;
143     }
144 
145     while ((prefix = FindNextMatchingPrefix(aAddress, prefix)) != nullptr)
146     {
147         contextTlv = prefix->FindSubTlv<ContextTlv>();
148 
149         if (contextTlv == nullptr)
150         {
151             continue;
152         }
153 
154         if (prefix->GetPrefixLength() > aContext.mPrefix.GetLength())
155         {
156             aContext.mPrefix.Set(prefix->GetPrefix(), prefix->GetPrefixLength());
157             aContext.mContextId    = contextTlv->GetContextId();
158             aContext.mCompressFlag = contextTlv->IsCompress();
159         }
160     }
161 
162     return (aContext.mPrefix.GetLength() > 0) ? kErrorNone : kErrorNotFound;
163 }
164 
GetContext(uint8_t aContextId,Lowpan::Context & aContext) const165 Error LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const
166 {
167     Error            error = kErrorNotFound;
168     TlvIterator      tlvIterator(GetTlvsStart(), GetTlvsEnd());
169     const PrefixTlv *prefix;
170 
171     if (aContextId == Mle::kMeshLocalPrefixContextId)
172     {
173         aContext.mPrefix.Set(Get<Mle::MleRouter>().GetMeshLocalPrefix());
174         aContext.mContextId    = Mle::kMeshLocalPrefixContextId;
175         aContext.mCompressFlag = true;
176         ExitNow(error = kErrorNone);
177     }
178 
179     while ((prefix = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
180     {
181         const ContextTlv *contextTlv = prefix->FindSubTlv<ContextTlv>();
182 
183         if ((contextTlv == nullptr) || (contextTlv->GetContextId() != aContextId))
184         {
185             continue;
186         }
187 
188         aContext.mPrefix.Set(prefix->GetPrefix(), prefix->GetPrefixLength());
189         aContext.mContextId    = contextTlv->GetContextId();
190         aContext.mCompressFlag = contextTlv->IsCompress();
191         ExitNow(error = kErrorNone);
192     }
193 
194 exit:
195     return error;
196 }
197 
IsOnMesh(const Ip6::Address & aAddress) const198 bool LeaderBase::IsOnMesh(const Ip6::Address &aAddress) const
199 {
200     const PrefixTlv *prefix = nullptr;
201     bool             rval   = false;
202 
203     VerifyOrExit(!Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress), rval = true);
204 
205     while ((prefix = FindNextMatchingPrefix(aAddress, prefix)) != nullptr)
206     {
207         // check both stable and temporary Border Router TLVs
208         for (int i = 0; i < 2; i++)
209         {
210             const BorderRouterTlv *borderRouter = prefix->FindSubTlv<BorderRouterTlv>(/* aStable */ (i == 0));
211 
212             if (borderRouter == nullptr)
213             {
214                 continue;
215             }
216 
217             for (const BorderRouterEntry *entry = borderRouter->GetFirstEntry(); entry <= borderRouter->GetLastEntry();
218                  entry                          = entry->GetNext())
219             {
220                 if (entry->IsOnMesh())
221                 {
222                     ExitNow(rval = true);
223                 }
224             }
225         }
226     }
227 
228 exit:
229     return rval;
230 }
231 
RouteLookup(const Ip6::Address & aSource,const Ip6::Address & aDestination,uint8_t * aPrefixMatchLength,uint16_t * aRloc16) const232 Error LeaderBase::RouteLookup(const Ip6::Address &aSource,
233                               const Ip6::Address &aDestination,
234                               uint8_t *           aPrefixMatchLength,
235                               uint16_t *          aRloc16) const
236 {
237     Error            error  = kErrorNoRoute;
238     const PrefixTlv *prefix = nullptr;
239 
240     while ((prefix = FindNextMatchingPrefix(aSource, prefix)) != nullptr)
241     {
242         if (ExternalRouteLookup(prefix->GetDomainId(), aDestination, aPrefixMatchLength, aRloc16) == kErrorNone)
243         {
244             ExitNow(error = kErrorNone);
245         }
246 
247         if (DefaultRouteLookup(*prefix, aRloc16) == kErrorNone)
248         {
249             if (aPrefixMatchLength)
250             {
251                 *aPrefixMatchLength = 0;
252             }
253 
254             ExitNow(error = kErrorNone);
255         }
256     }
257 
258 exit:
259     return error;
260 }
261 
ExternalRouteLookup(uint8_t aDomainId,const Ip6::Address & aDestination,uint8_t * aPrefixMatchLength,uint16_t * aRloc16) const262 Error LeaderBase::ExternalRouteLookup(uint8_t             aDomainId,
263                                       const Ip6::Address &aDestination,
264                                       uint8_t *           aPrefixMatchLength,
265                                       uint16_t *          aRloc16) const
266 {
267     Error                error = kErrorNoRoute;
268     TlvIterator          tlvIterator(GetTlvsStart(), GetTlvsEnd());
269     const PrefixTlv *    prefixTlv;
270     const HasRouteEntry *bestRouteEntry  = nullptr;
271     uint8_t              bestMatchLength = 0;
272 
273     while ((prefixTlv = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
274     {
275         const HasRouteTlv *hasRoute;
276         uint8_t            prefixLength = prefixTlv->GetPrefixLength();
277         TlvIterator        subTlvIterator(*prefixTlv);
278 
279         if (prefixTlv->GetDomainId() != aDomainId)
280         {
281             continue;
282         }
283 
284         if (!aDestination.MatchesPrefix(prefixTlv->GetPrefix(), prefixLength))
285         {
286             continue;
287         }
288 
289         if ((bestRouteEntry != nullptr) && (prefixLength <= bestMatchLength))
290         {
291             continue;
292         }
293 
294         while ((hasRoute = subTlvIterator.Iterate<HasRouteTlv>()) != nullptr)
295         {
296             for (const HasRouteEntry *entry = hasRoute->GetFirstEntry(); entry <= hasRoute->GetLastEntry();
297                  entry                      = entry->GetNext())
298             {
299                 if (bestRouteEntry == nullptr || entry->GetPreference() > bestRouteEntry->GetPreference() ||
300                     (entry->GetPreference() == bestRouteEntry->GetPreference() &&
301                      (entry->GetRloc() == Get<Mle::MleRouter>().GetRloc16() ||
302                       (bestRouteEntry->GetRloc() != Get<Mle::MleRouter>().GetRloc16() &&
303                        Get<Mle::MleRouter>().GetCost(entry->GetRloc()) <
304                            Get<Mle::MleRouter>().GetCost(bestRouteEntry->GetRloc())))))
305                 {
306                     bestRouteEntry  = entry;
307                     bestMatchLength = prefixLength;
308                 }
309             }
310         }
311     }
312 
313     if (bestRouteEntry != nullptr)
314     {
315         if (aRloc16 != nullptr)
316         {
317             *aRloc16 = bestRouteEntry->GetRloc();
318         }
319 
320         if (aPrefixMatchLength != nullptr)
321         {
322             *aPrefixMatchLength = bestMatchLength;
323         }
324 
325         error = kErrorNone;
326     }
327 
328     return error;
329 }
330 
DefaultRouteLookup(const PrefixTlv & aPrefix,uint16_t * aRloc16) const331 Error LeaderBase::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t *aRloc16) const
332 {
333     Error                    error = kErrorNoRoute;
334     TlvIterator              subTlvIterator(aPrefix);
335     const BorderRouterTlv *  borderRouter;
336     const BorderRouterEntry *route = nullptr;
337 
338     while ((borderRouter = subTlvIterator.Iterate<BorderRouterTlv>()) != nullptr)
339     {
340         for (const BorderRouterEntry *entry = borderRouter->GetFirstEntry(); entry <= borderRouter->GetLastEntry();
341              entry                          = entry->GetNext())
342         {
343             if (!entry->IsDefaultRoute())
344             {
345                 continue;
346             }
347 
348             if (route == nullptr || entry->GetPreference() > route->GetPreference() ||
349                 (entry->GetPreference() == route->GetPreference() &&
350                  (entry->GetRloc() == Get<Mle::MleRouter>().GetRloc16() ||
351                   (route->GetRloc() != Get<Mle::MleRouter>().GetRloc16() &&
352                    Get<Mle::MleRouter>().GetCost(entry->GetRloc()) < Get<Mle::MleRouter>().GetCost(route->GetRloc())))))
353             {
354                 route = entry;
355             }
356         }
357     }
358 
359     if (route != nullptr)
360     {
361         if (aRloc16 != nullptr)
362         {
363             *aRloc16 = route->GetRloc();
364         }
365 
366         error = kErrorNone;
367     }
368 
369     return error;
370 }
371 
SetNetworkData(uint8_t aVersion,uint8_t aStableVersion,Type aType,const Message & aMessage,uint16_t aMessageOffset)372 Error LeaderBase::SetNetworkData(uint8_t        aVersion,
373                                  uint8_t        aStableVersion,
374                                  Type           aType,
375                                  const Message &aMessage,
376                                  uint16_t       aMessageOffset)
377 {
378     Error    error = kErrorNone;
379     Mle::Tlv tlv;
380     uint16_t length;
381 
382     SuccessOrExit(error = aMessage.Read(aMessageOffset, tlv));
383 
384     length = aMessage.ReadBytes(aMessageOffset + sizeof(tlv), GetBytes(), tlv.GetLength());
385     VerifyOrExit(length == tlv.GetLength(), error = kErrorParse);
386 
387     SetLength(tlv.GetLength());
388     mVersion       = aVersion;
389     mStableVersion = aStableVersion;
390 
391     if (aType == kStableSubset)
392     {
393         RemoveTemporaryData();
394     }
395 
396 #if OPENTHREAD_FTD
397     if (Get<Mle::MleRouter>().IsLeader())
398     {
399         Get<Leader>().HandleNetworkDataRestoredAfterReset();
400     }
401 #endif
402 
403     DumpDebg("SetNetworkData", GetBytes(), GetLength());
404 
405     Get<ot::Notifier>().Signal(kEventThreadNetdataChanged);
406 
407 exit:
408     return error;
409 }
410 
SetCommissioningData(const uint8_t * aValue,uint8_t aValueLength)411 Error LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength)
412 {
413     Error                 error = kErrorNone;
414     CommissioningDataTlv *commissioningDataTlv;
415 
416     RemoveCommissioningData();
417 
418     if (aValueLength > 0)
419     {
420         VerifyOrExit(aValueLength <= kMaxSize - sizeof(CommissioningDataTlv), error = kErrorNoBufs);
421         commissioningDataTlv = As<CommissioningDataTlv>(AppendTlv(sizeof(CommissioningDataTlv) + aValueLength));
422         VerifyOrExit(commissioningDataTlv != nullptr, error = kErrorNoBufs);
423 
424         commissioningDataTlv->Init();
425         commissioningDataTlv->SetLength(aValueLength);
426         memcpy(commissioningDataTlv->GetValue(), aValue, aValueLength);
427     }
428 
429     mVersion++;
430     Get<ot::Notifier>().Signal(kEventThreadNetdataChanged);
431 
432 exit:
433     return error;
434 }
435 
GetCommissioningData(void) const436 const CommissioningDataTlv *LeaderBase::GetCommissioningData(void) const
437 {
438     return NetworkDataTlv::Find<CommissioningDataTlv>(GetTlvsStart(), GetTlvsEnd());
439 }
440 
GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const441 const MeshCoP::Tlv *LeaderBase::GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const
442 {
443     const MeshCoP::Tlv *  rval = nullptr;
444     const NetworkDataTlv *commissioningDataTlv;
445 
446     commissioningDataTlv = GetCommissioningData();
447     VerifyOrExit(commissioningDataTlv != nullptr);
448 
449     rval = MeshCoP::Tlv::FindTlv(commissioningDataTlv->GetValue(), commissioningDataTlv->GetLength(), aType);
450 
451 exit:
452     return rval;
453 }
454 
IsJoiningEnabled(void) const455 bool LeaderBase::IsJoiningEnabled(void) const
456 {
457     const MeshCoP::Tlv *steeringData;
458     bool                rval = false;
459 
460     VerifyOrExit(GetCommissioningDataSubTlv(MeshCoP::Tlv::kBorderAgentLocator) != nullptr);
461 
462     steeringData = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
463     VerifyOrExit(steeringData != nullptr);
464 
465     for (int i = 0; i < steeringData->GetLength(); i++)
466     {
467         if (steeringData->GetValue()[i] != 0)
468         {
469             ExitNow(rval = true);
470         }
471     }
472 
473 exit:
474     return rval;
475 }
476 
RemoveCommissioningData(void)477 void LeaderBase::RemoveCommissioningData(void)
478 {
479     CommissioningDataTlv *tlv = GetCommissioningData();
480 
481     VerifyOrExit(tlv != nullptr);
482     RemoveTlv(tlv);
483 
484 exit:
485     return;
486 }
487 
SteeringDataCheck(const FilterIndexes & aFilterIndexes) const488 Error LeaderBase::SteeringDataCheck(const FilterIndexes &aFilterIndexes) const
489 {
490     Error                 error = kErrorNone;
491     const MeshCoP::Tlv *  steeringDataTlv;
492     MeshCoP::SteeringData steeringData;
493 
494     steeringDataTlv = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
495     VerifyOrExit(steeringDataTlv != nullptr, error = kErrorInvalidState);
496 
497     As<MeshCoP::SteeringDataTlv>(steeringDataTlv)->CopyTo(steeringData);
498 
499     VerifyOrExit(steeringData.Contains(aFilterIndexes), error = kErrorNotFound);
500 
501 exit:
502     return error;
503 }
504 
SteeringDataCheckJoiner(const Mac::ExtAddress & aEui64) const505 Error LeaderBase::SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const
506 {
507     FilterIndexes   filterIndexes;
508     Mac::ExtAddress joinerId;
509 
510     MeshCoP::ComputeJoinerId(aEui64, joinerId);
511     MeshCoP::SteeringData::CalculateHashBitIndexes(joinerId, filterIndexes);
512 
513     return SteeringDataCheck(filterIndexes);
514 }
515 
SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner & aDiscerner) const516 Error LeaderBase::SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const
517 {
518     FilterIndexes filterIndexes;
519 
520     MeshCoP::SteeringData::CalculateHashBitIndexes(aDiscerner, filterIndexes);
521 
522     return SteeringDataCheck(filterIndexes);
523 }
524 
525 } // namespace NetworkData
526 } // namespace ot
527