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