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 
LeaderBase(Instance & aInstance)56 LeaderBase::LeaderBase(Instance &aInstance)
57     : NetworkData(aInstance, kTypeLeader)
58 {
59     Reset();
60 }
61 
Reset(void)62 void LeaderBase::Reset(void)
63 {
64     mVersion       = Random::NonCrypto::GetUint8();
65     mStableVersion = Random::NonCrypto::GetUint8();
66     mLength        = 0;
67     Get<ot::Notifier>().Signal(kEventThreadNetdataChanged);
68 }
69 
GetServiceId(uint32_t aEnterpriseNumber,const uint8_t * aServiceData,uint8_t aServiceDataLength,bool aServerStable,uint8_t & aServiceId) const70 Error LeaderBase::GetServiceId(uint32_t       aEnterpriseNumber,
71                                const uint8_t *aServiceData,
72                                uint8_t        aServiceDataLength,
73                                bool           aServerStable,
74                                uint8_t &      aServiceId) const
75 {
76     Error         error    = kErrorNotFound;
77     Iterator      iterator = kIteratorInit;
78     ServiceConfig serviceConfig;
79 
80     while (GetNextService(iterator, serviceConfig) == kErrorNone)
81     {
82         if (aEnterpriseNumber == serviceConfig.mEnterpriseNumber &&
83             aServiceDataLength == serviceConfig.mServiceDataLength &&
84             memcmp(aServiceData, serviceConfig.mServiceData, aServiceDataLength) == 0 &&
85             aServerStable == serviceConfig.mServerConfig.mStable)
86         {
87             aServiceId = serviceConfig.mServiceId;
88             ExitNow(error = kErrorNone);
89         }
90     }
91 
92 exit:
93     return error;
94 }
95 
FindNextMatchingPrefix(const Ip6::Address & aAddress,const PrefixTlv * aPrevTlv) const96 const PrefixTlv *LeaderBase::FindNextMatchingPrefix(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const
97 {
98     const PrefixTlv *prefixTlv;
99     TlvIterator      tlvIterator((aPrevTlv == nullptr) ? GetTlvsStart() : aPrevTlv->GetNext(), GetTlvsEnd());
100 
101     while ((prefixTlv = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
102     {
103         if (aAddress.MatchesPrefix(prefixTlv->GetPrefix(), prefixTlv->GetPrefixLength()))
104         {
105             break;
106         }
107     }
108 
109     return prefixTlv;
110 }
111 
GetContext(const Ip6::Address & aAddress,Lowpan::Context & aContext) const112 Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const
113 {
114     const PrefixTlv * prefix = nullptr;
115     const ContextTlv *contextTlv;
116 
117     aContext.mPrefix.SetLength(0);
118 
119     if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
120     {
121         aContext.mPrefix.Set(Get<Mle::MleRouter>().GetMeshLocalPrefix());
122         aContext.mContextId    = Mle::kMeshLocalPrefixContextId;
123         aContext.mCompressFlag = true;
124     }
125 
126     while ((prefix = FindNextMatchingPrefix(aAddress, prefix)) != nullptr)
127     {
128         contextTlv = prefix->FindSubTlv<ContextTlv>();
129 
130         if (contextTlv == nullptr)
131         {
132             continue;
133         }
134 
135         if (prefix->GetPrefixLength() > aContext.mPrefix.GetLength())
136         {
137             aContext.mPrefix.Set(prefix->GetPrefix(), prefix->GetPrefixLength());
138             aContext.mContextId    = contextTlv->GetContextId();
139             aContext.mCompressFlag = contextTlv->IsCompress();
140         }
141     }
142 
143     return (aContext.mPrefix.GetLength() > 0) ? kErrorNone : kErrorNotFound;
144 }
145 
GetContext(uint8_t aContextId,Lowpan::Context & aContext) const146 Error LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const
147 {
148     Error            error = kErrorNotFound;
149     TlvIterator      tlvIterator(GetTlvsStart(), GetTlvsEnd());
150     const PrefixTlv *prefix;
151 
152     if (aContextId == Mle::kMeshLocalPrefixContextId)
153     {
154         aContext.mPrefix.Set(Get<Mle::MleRouter>().GetMeshLocalPrefix());
155         aContext.mContextId    = Mle::kMeshLocalPrefixContextId;
156         aContext.mCompressFlag = true;
157         ExitNow(error = kErrorNone);
158     }
159 
160     while ((prefix = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
161     {
162         const ContextTlv *contextTlv = prefix->FindSubTlv<ContextTlv>();
163 
164         if ((contextTlv == nullptr) || (contextTlv->GetContextId() != aContextId))
165         {
166             continue;
167         }
168 
169         aContext.mPrefix.Set(prefix->GetPrefix(), prefix->GetPrefixLength());
170         aContext.mContextId    = contextTlv->GetContextId();
171         aContext.mCompressFlag = contextTlv->IsCompress();
172         ExitNow(error = kErrorNone);
173     }
174 
175 exit:
176     return error;
177 }
178 
IsOnMesh(const Ip6::Address & aAddress) const179 bool LeaderBase::IsOnMesh(const Ip6::Address &aAddress) const
180 {
181     const PrefixTlv *prefix = nullptr;
182     bool             rval   = false;
183 
184     VerifyOrExit(!Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress), rval = true);
185 
186     while ((prefix = FindNextMatchingPrefix(aAddress, prefix)) != nullptr)
187     {
188         // check both stable and temporary Border Router TLVs
189         for (int i = 0; i < 2; i++)
190         {
191             const BorderRouterTlv *borderRouter = prefix->FindSubTlv<BorderRouterTlv>(/* aStable */ (i == 0));
192 
193             if (borderRouter == nullptr)
194             {
195                 continue;
196             }
197 
198             for (const BorderRouterEntry *entry = borderRouter->GetFirstEntry(); entry <= borderRouter->GetLastEntry();
199                  entry                          = entry->GetNext())
200             {
201                 if (entry->IsOnMesh())
202                 {
203                     ExitNow(rval = true);
204                 }
205             }
206         }
207     }
208 
209 exit:
210     return rval;
211 }
212 
RouteLookup(const Ip6::Address & aSource,const Ip6::Address & aDestination,uint8_t * aPrefixMatchLength,uint16_t * aRloc16) const213 Error LeaderBase::RouteLookup(const Ip6::Address &aSource,
214                               const Ip6::Address &aDestination,
215                               uint8_t *           aPrefixMatchLength,
216                               uint16_t *          aRloc16) const
217 {
218     Error            error  = kErrorNoRoute;
219     const PrefixTlv *prefix = nullptr;
220 
221     while ((prefix = FindNextMatchingPrefix(aSource, prefix)) != nullptr)
222     {
223         if (ExternalRouteLookup(prefix->GetDomainId(), aDestination, aPrefixMatchLength, aRloc16) == kErrorNone)
224         {
225             ExitNow(error = kErrorNone);
226         }
227 
228         if (DefaultRouteLookup(*prefix, aRloc16) == kErrorNone)
229         {
230             if (aPrefixMatchLength)
231             {
232                 *aPrefixMatchLength = 0;
233             }
234 
235             ExitNow(error = kErrorNone);
236         }
237     }
238 
239 exit:
240     return error;
241 }
242 
ExternalRouteLookup(uint8_t aDomainId,const Ip6::Address & aDestination,uint8_t * aPrefixMatchLength,uint16_t * aRloc16) const243 Error LeaderBase::ExternalRouteLookup(uint8_t             aDomainId,
244                                       const Ip6::Address &aDestination,
245                                       uint8_t *           aPrefixMatchLength,
246                                       uint16_t *          aRloc16) const
247 {
248     Error                error = kErrorNoRoute;
249     TlvIterator          tlvIterator(GetTlvsStart(), GetTlvsEnd());
250     const PrefixTlv *    prefixTlv;
251     const HasRouteEntry *bestRouteEntry  = nullptr;
252     uint8_t              bestMatchLength = 0;
253 
254     while ((prefixTlv = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
255     {
256         const HasRouteTlv *hasRoute;
257         uint8_t            prefixLength = prefixTlv->GetPrefixLength();
258         TlvIterator        subTlvIterator(*prefixTlv);
259 
260         if (prefixTlv->GetDomainId() != aDomainId)
261         {
262             continue;
263         }
264 
265         if (!aDestination.MatchesPrefix(prefixTlv->GetPrefix(), prefixLength))
266         {
267             continue;
268         }
269 
270         if ((bestRouteEntry != nullptr) && (prefixLength <= bestMatchLength))
271         {
272             continue;
273         }
274 
275         while ((hasRoute = subTlvIterator.Iterate<HasRouteTlv>()) != nullptr)
276         {
277             for (const HasRouteEntry *entry = hasRoute->GetFirstEntry(); entry <= hasRoute->GetLastEntry();
278                  entry                      = entry->GetNext())
279             {
280                 if (bestRouteEntry == nullptr || entry->GetPreference() > bestRouteEntry->GetPreference() ||
281                     (entry->GetPreference() == bestRouteEntry->GetPreference() &&
282                      (entry->GetRloc() == Get<Mle::MleRouter>().GetRloc16() ||
283                       (bestRouteEntry->GetRloc() != Get<Mle::MleRouter>().GetRloc16() &&
284                        Get<Mle::MleRouter>().GetCost(entry->GetRloc()) <
285                            Get<Mle::MleRouter>().GetCost(bestRouteEntry->GetRloc())))))
286                 {
287                     bestRouteEntry  = entry;
288                     bestMatchLength = prefixLength;
289                 }
290             }
291         }
292     }
293 
294     if (bestRouteEntry != nullptr)
295     {
296         if (aRloc16 != nullptr)
297         {
298             *aRloc16 = bestRouteEntry->GetRloc();
299         }
300 
301         if (aPrefixMatchLength != nullptr)
302         {
303             *aPrefixMatchLength = bestMatchLength;
304         }
305 
306         error = kErrorNone;
307     }
308 
309     return error;
310 }
311 
DefaultRouteLookup(const PrefixTlv & aPrefix,uint16_t * aRloc16) const312 Error LeaderBase::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t *aRloc16) const
313 {
314     Error                    error = kErrorNoRoute;
315     TlvIterator              subTlvIterator(aPrefix);
316     const BorderRouterTlv *  borderRouter;
317     const BorderRouterEntry *route = nullptr;
318 
319     while ((borderRouter = subTlvIterator.Iterate<BorderRouterTlv>()) != nullptr)
320     {
321         for (const BorderRouterEntry *entry = borderRouter->GetFirstEntry(); entry <= borderRouter->GetLastEntry();
322              entry                          = entry->GetNext())
323         {
324             if (!entry->IsDefaultRoute())
325             {
326                 continue;
327             }
328 
329             if (route == nullptr || entry->GetPreference() > route->GetPreference() ||
330                 (entry->GetPreference() == route->GetPreference() &&
331                  (entry->GetRloc() == Get<Mle::MleRouter>().GetRloc16() ||
332                   (route->GetRloc() != Get<Mle::MleRouter>().GetRloc16() &&
333                    Get<Mle::MleRouter>().GetCost(entry->GetRloc()) < Get<Mle::MleRouter>().GetCost(route->GetRloc())))))
334             {
335                 route = entry;
336             }
337         }
338     }
339 
340     if (route != nullptr)
341     {
342         if (aRloc16 != nullptr)
343         {
344             *aRloc16 = route->GetRloc();
345         }
346 
347         error = kErrorNone;
348     }
349 
350     return error;
351 }
352 
SetNetworkData(uint8_t aVersion,uint8_t aStableVersion,bool aStableOnly,const Message & aMessage,uint16_t aMessageOffset)353 Error LeaderBase::SetNetworkData(uint8_t        aVersion,
354                                  uint8_t        aStableVersion,
355                                  bool           aStableOnly,
356                                  const Message &aMessage,
357                                  uint16_t       aMessageOffset)
358 {
359     Error    error = kErrorNone;
360     Mle::Tlv tlv;
361     uint16_t length;
362 
363     SuccessOrExit(error = aMessage.Read(aMessageOffset, tlv));
364 
365     length = aMessage.ReadBytes(aMessageOffset + sizeof(tlv), mTlvs, tlv.GetLength());
366     VerifyOrExit(length == tlv.GetLength(), error = kErrorParse);
367 
368     mLength        = tlv.GetLength();
369     mVersion       = aVersion;
370     mStableVersion = aStableVersion;
371 
372     if (aStableOnly)
373     {
374         RemoveTemporaryData(mTlvs, mLength);
375     }
376 
377 #if OPENTHREAD_FTD
378     // Synchronize internal 6LoWPAN Context ID Set with recently obtained Network Data.
379     if (Get<Mle::MleRouter>().IsLeader())
380     {
381         Get<Leader>().UpdateContextsAfterReset();
382     }
383 #endif
384 
385     otDumpDebgNetData("set network data", mTlvs, mLength);
386 
387     Get<ot::Notifier>().Signal(kEventThreadNetdataChanged);
388 
389 exit:
390     return error;
391 }
392 
SetCommissioningData(const uint8_t * aValue,uint8_t aValueLength)393 Error LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength)
394 {
395     Error                 error = kErrorNone;
396     CommissioningDataTlv *commissioningDataTlv;
397 
398     RemoveCommissioningData();
399 
400     if (aValueLength > 0)
401     {
402         VerifyOrExit(aValueLength <= kMaxSize - sizeof(CommissioningDataTlv), error = kErrorNoBufs);
403         commissioningDataTlv =
404             static_cast<CommissioningDataTlv *>(AppendTlv(sizeof(CommissioningDataTlv) + aValueLength));
405         VerifyOrExit(commissioningDataTlv != nullptr, error = kErrorNoBufs);
406 
407         commissioningDataTlv->Init();
408         commissioningDataTlv->SetLength(aValueLength);
409         memcpy(commissioningDataTlv->GetValue(), aValue, aValueLength);
410     }
411 
412     mVersion++;
413     Get<ot::Notifier>().Signal(kEventThreadNetdataChanged);
414 
415 exit:
416     return error;
417 }
418 
GetCommissioningData(void) const419 const CommissioningDataTlv *LeaderBase::GetCommissioningData(void) const
420 {
421     return NetworkDataTlv::Find<CommissioningDataTlv>(GetTlvsStart(), GetTlvsEnd());
422 }
423 
GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const424 const MeshCoP::Tlv *LeaderBase::GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const
425 {
426     const MeshCoP::Tlv *  rval = nullptr;
427     const NetworkDataTlv *commissioningDataTlv;
428 
429     commissioningDataTlv = GetCommissioningData();
430     VerifyOrExit(commissioningDataTlv != nullptr);
431 
432     rval = MeshCoP::Tlv::FindTlv(commissioningDataTlv->GetValue(), commissioningDataTlv->GetLength(), aType);
433 
434 exit:
435     return rval;
436 }
437 
IsJoiningEnabled(void) const438 bool LeaderBase::IsJoiningEnabled(void) const
439 {
440     const MeshCoP::Tlv *steeringData;
441     bool                rval = false;
442 
443     VerifyOrExit(GetCommissioningDataSubTlv(MeshCoP::Tlv::kBorderAgentLocator) != nullptr);
444 
445     steeringData = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
446     VerifyOrExit(steeringData != nullptr);
447 
448     for (int i = 0; i < steeringData->GetLength(); i++)
449     {
450         if (steeringData->GetValue()[i] != 0)
451         {
452             ExitNow(rval = true);
453         }
454     }
455 
456 exit:
457     return rval;
458 }
459 
RemoveCommissioningData(void)460 void LeaderBase::RemoveCommissioningData(void)
461 {
462     CommissioningDataTlv *tlv = GetCommissioningData();
463 
464     VerifyOrExit(tlv != nullptr);
465     RemoveTlv(tlv);
466 
467 exit:
468     return;
469 }
470 
SteeringDataCheck(const FilterIndexes & aFilterIndexes) const471 Error LeaderBase::SteeringDataCheck(const FilterIndexes &aFilterIndexes) const
472 {
473     Error                 error = kErrorNone;
474     const MeshCoP::Tlv *  steeringDataTlv;
475     MeshCoP::SteeringData steeringData;
476 
477     steeringDataTlv = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
478     VerifyOrExit(steeringDataTlv != nullptr, error = kErrorInvalidState);
479 
480     static_cast<const MeshCoP::SteeringDataTlv *>(steeringDataTlv)->CopyTo(steeringData);
481 
482     VerifyOrExit(steeringData.Contains(aFilterIndexes), error = kErrorNotFound);
483 
484 exit:
485     return error;
486 }
487 
SteeringDataCheckJoiner(const Mac::ExtAddress & aEui64) const488 Error LeaderBase::SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const
489 {
490     FilterIndexes   filterIndexes;
491     Mac::ExtAddress joinerId;
492 
493     MeshCoP::ComputeJoinerId(aEui64, joinerId);
494     MeshCoP::SteeringData::CalculateHashBitIndexes(joinerId, filterIndexes);
495 
496     return SteeringDataCheck(filterIndexes);
497 }
498 
SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner & aDiscerner) const499 Error LeaderBase::SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const
500 {
501     FilterIndexes filterIndexes;
502 
503     MeshCoP::SteeringData::CalculateHashBitIndexes(aDiscerner, filterIndexes);
504 
505     return SteeringDataCheck(filterIndexes);
506 }
507 
508 } // namespace NetworkData
509 } // namespace ot
510