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