1 /*
2 * Copyright (c) 2021, 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 function for managing Thread Network Data service/server entries.
32 */
33
34 #include "network_data_service.hpp"
35
36 #include "instance/instance.hpp"
37
38 namespace ot {
39 namespace NetworkData {
40 namespace Service {
41
42 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
43
AddDnsSrpAnycastService(uint8_t aSequenceNumber,uint8_t aVersion)44 Error Manager::AddDnsSrpAnycastService(uint8_t aSequenceNumber, uint8_t aVersion)
45 {
46 DnsSrpAnycastServiceData anycastData(aSequenceNumber);
47
48 return (aVersion == 0) ? AddService(anycastData) : AddService(anycastData, aVersion);
49 }
50
AddService(const void * aServiceData,uint8_t aServiceDataLength,const void * aServerData,uint8_t aServerDataLength)51 Error Manager::AddService(const void *aServiceData,
52 uint8_t aServiceDataLength,
53 const void *aServerData,
54 uint8_t aServerDataLength)
55 {
56 ServiceData serviceData;
57 ServerData serverData;
58
59 serviceData.Init(aServiceData, aServiceDataLength);
60 serverData.Init(aServerData, aServerDataLength);
61
62 return Get<Local>().AddService(kThreadEnterpriseNumber, serviceData, /* aServerStable */ true, serverData);
63 }
64
RemoveService(const void * aServiceData,uint8_t aServiceDataLength)65 Error Manager::RemoveService(const void *aServiceData, uint8_t aServiceDataLength)
66 {
67 ServiceData serviceData;
68
69 serviceData.Init(aServiceData, aServiceDataLength);
70
71 return Get<Local>().RemoveService(kThreadEnterpriseNumber, serviceData);
72 }
73
74 #endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
75
GetServiceId(uint8_t aServiceNumber,uint8_t & aServiceId) const76 Error Manager::GetServiceId(uint8_t aServiceNumber, uint8_t &aServiceId) const
77 {
78 ServiceData serviceData;
79
80 serviceData.InitFrom(aServiceNumber);
81
82 return Get<Leader>().GetServiceId(kThreadEnterpriseNumber, serviceData, /* aServerStable */ true, aServiceId);
83 }
84
85 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
86
GetBackboneRouterPrimary(ot::BackboneRouter::Config & aConfig) const87 void Manager::GetBackboneRouterPrimary(ot::BackboneRouter::Config &aConfig) const
88 {
89 const ServerTlv *rvalServerTlv = nullptr;
90 const BbrServerData *rvalServerData = nullptr;
91 const ServiceTlv *serviceTlv = nullptr;
92 uint8_t bbrServiceNumber = kBackboneRouterServiceNumber;
93 ServiceData serviceData;
94
95 serviceData.InitFrom(bbrServiceNumber);
96
97 aConfig.mServer16 = Mle::kInvalidRloc16;
98
99 while ((serviceTlv = Get<Leader>().FindNextThreadService(serviceTlv, serviceData,
100 NetworkData::kServicePrefixMatch)) != nullptr)
101 {
102 Iterator iterator;
103
104 iterator.mServiceTlv = serviceTlv;
105
106 while (IterateToNextServer(iterator) == kErrorNone)
107 {
108 ServerData data;
109 const BbrServerData *serverData;
110
111 iterator.mServerSubTlv->GetServerData(data);
112
113 if (data.GetLength() < sizeof(BbrServerData))
114 {
115 continue;
116 }
117
118 serverData = reinterpret_cast<const BbrServerData *>(data.GetBytes());
119
120 if (rvalServerTlv == nullptr ||
121 IsBackboneRouterPreferredTo(*iterator.mServerSubTlv, *serverData, *rvalServerTlv, *rvalServerData))
122 {
123 rvalServerTlv = iterator.mServerSubTlv;
124 rvalServerData = serverData;
125 }
126 }
127 }
128
129 VerifyOrExit(rvalServerTlv != nullptr);
130
131 aConfig.mServer16 = rvalServerTlv->GetServer16();
132 aConfig.mSequenceNumber = rvalServerData->GetSequenceNumber();
133 aConfig.mReregistrationDelay = rvalServerData->GetReregistrationDelay();
134 aConfig.mMlrTimeout = rvalServerData->GetMlrTimeout();
135
136 exit:
137 return;
138 }
139
IsBackboneRouterPreferredTo(const ServerTlv & aServerTlv,const BbrServerData & aServerData,const ServerTlv & aOtherServerTlv,const BbrServerData & aOtherServerData) const140 bool Manager::IsBackboneRouterPreferredTo(const ServerTlv &aServerTlv,
141 const BbrServerData &aServerData,
142 const ServerTlv &aOtherServerTlv,
143 const BbrServerData &aOtherServerData) const
144 {
145 bool isPreferred;
146 uint16_t leaderRloc16 = Get<Mle::MleRouter>().GetLeaderRloc16();
147
148 VerifyOrExit(aServerTlv.GetServer16() != leaderRloc16, isPreferred = true);
149 VerifyOrExit(aOtherServerTlv.GetServer16() != leaderRloc16, isPreferred = false);
150
151 isPreferred = aServerData.GetSequenceNumber() > aOtherServerData.GetSequenceNumber() ||
152 (aServerData.GetSequenceNumber() == aOtherServerData.GetSequenceNumber() &&
153 aServerTlv.GetServer16() > aOtherServerTlv.GetServer16());
154 exit:
155 return isPreferred;
156 }
157
158 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
159
GetNextDnsSrpAnycastInfo(Iterator & aIterator,DnsSrpAnycastInfo & aInfo) const160 Error Manager::GetNextDnsSrpAnycastInfo(Iterator &aIterator, DnsSrpAnycastInfo &aInfo) const
161 {
162 Error error = kErrorNone;
163 uint8_t serviceNumber = kDnsSrpAnycastServiceNumber;
164
165 do
166 {
167 ServiceData serviceData;
168
169 // Process the next Server sub-TLV in the current Service TLV.
170
171 if (IterateToNextServer(aIterator) == kErrorNone)
172 {
173 uint8_t dataLength = aIterator.mServiceTlv->GetServiceDataLength();
174
175 if (dataLength >= sizeof(DnsSrpAnycastServiceData))
176 {
177 const DnsSrpAnycastServiceData *anycastData =
178 reinterpret_cast<const DnsSrpAnycastServiceData *>(aIterator.mServiceTlv->GetServiceData());
179
180 Get<Mle::Mle>().GetServiceAloc(aIterator.mServiceTlv->GetServiceId(), aInfo.mAnycastAddress);
181 aInfo.mSequenceNumber = anycastData->GetSequenceNumber();
182 aInfo.mRloc16 = aIterator.mServerSubTlv->GetServer16();
183 aInfo.mVersion = (aIterator.mServerSubTlv->GetServerDataLength() >= sizeof(uint8_t))
184 ? *aIterator.mServerSubTlv->GetServerData()
185 : 0;
186 ExitNow();
187 }
188 }
189
190 // Find the next matching Service TLV.
191
192 serviceData.InitFrom(serviceNumber);
193 aIterator.mServiceTlv =
194 Get<Leader>().FindNextThreadService(aIterator.mServiceTlv, serviceData, NetworkData::kServicePrefixMatch);
195 aIterator.mServerSubTlv = nullptr;
196
197 // If we have a valid Service TLV, restart the loop
198 // to process its Server sub-TLVs.
199
200 } while (aIterator.mServiceTlv != nullptr);
201
202 error = kErrorNotFound;
203
204 exit:
205 return error;
206 }
207
FindPreferredDnsSrpAnycastInfo(DnsSrpAnycastInfo & aInfo) const208 Error Manager::FindPreferredDnsSrpAnycastInfo(DnsSrpAnycastInfo &aInfo) const
209 {
210 Error error = kErrorNotFound;
211 Iterator iterator;
212 DnsSrpAnycastInfo info;
213 DnsSrpAnycastInfo maxNumericalSeqNumInfo;
214
215 // Determine the entry with largest seq number in two ways:
216 // `aInfo` will track the largest using serial number arithmetic
217 // comparison, while `maxNumericalSeqNumInfo` tracks the largest
218 // using normal numerical comparison.
219
220 while (GetNextDnsSrpAnycastInfo(iterator, info) == kErrorNone)
221 {
222 if (error == kErrorNotFound)
223 {
224 aInfo = info;
225 maxNumericalSeqNumInfo = info;
226 error = kErrorNone;
227 continue;
228 }
229
230 if (SerialNumber::IsGreater(info.mSequenceNumber, aInfo.mSequenceNumber))
231 {
232 aInfo = info;
233 }
234
235 if (info.mSequenceNumber > maxNumericalSeqNumInfo.mSequenceNumber)
236 {
237 maxNumericalSeqNumInfo = info;
238 }
239 }
240
241 SuccessOrExit(error);
242
243 // Check that the largest seq number using serial number arithmetic is
244 // well-defined (i.e., the seq number is larger than all other seq
245 // numbers values). If it is not, we prefer `maxNumericalSeqNumInfo`.
246
247 iterator.Reset();
248
249 while (GetNextDnsSrpAnycastInfo(iterator, info) == kErrorNone)
250 {
251 constexpr uint8_t kMidValue = (NumericLimits<uint8_t>::kMax / 2) + 1;
252 uint8_t seqNumber = info.mSequenceNumber;
253 uint8_t diff;
254
255 if (seqNumber == aInfo.mSequenceNumber)
256 {
257 continue;
258 }
259
260 diff = seqNumber - aInfo.mSequenceNumber;
261
262 if ((diff == kMidValue) || !SerialNumber::IsGreater(aInfo.mSequenceNumber, seqNumber))
263 {
264 aInfo = maxNumericalSeqNumInfo;
265
266 break;
267 }
268 }
269
270 // Determine the minimum version supported among all entries
271 // matching the selected `aInfo.mSequenceNumber`.
272
273 iterator.Reset();
274
275 while (GetNextDnsSrpAnycastInfo(iterator, info) == kErrorNone)
276 {
277 if (info.mSequenceNumber == aInfo.mSequenceNumber)
278 {
279 aInfo.mVersion = Min(aInfo.mVersion, info.mVersion);
280 }
281 }
282
283 exit:
284 return error;
285 }
286
ParseFrom(const uint8_t * aData,uint8_t aLength,DnsSrpUnicastInfo & aInfo)287 Error Manager::DnsSrpUnicast::AddrData::ParseFrom(const uint8_t *aData, uint8_t aLength, DnsSrpUnicastInfo &aInfo)
288 {
289 Error error = kErrorNone;
290 const AddrData *addrData = reinterpret_cast<const AddrData *>(aData);
291
292 VerifyOrExit(aLength >= kMinLength, error = kErrorParse);
293
294 aInfo.mSockAddr.SetAddress(addrData->GetAddress());
295 aInfo.mSockAddr.SetPort(addrData->GetPort());
296 aInfo.mVersion = (aLength >= sizeof(AddrData)) ? addrData->GetVersion() : 0;
297
298 exit:
299 return error;
300 }
301
GetNextDnsSrpUnicastInfo(Iterator & aIterator,DnsSrpUnicastType aType,DnsSrpUnicastInfo & aInfo) const302 Error Manager::GetNextDnsSrpUnicastInfo(Iterator &aIterator, DnsSrpUnicastType aType, DnsSrpUnicastInfo &aInfo) const
303 {
304 Error error = kErrorNone;
305 uint8_t serviceNumber = kDnsSrpUnicastServiceNumber;
306
307 do
308 {
309 ServiceData serviceData;
310
311 // Process Server sub-TLVs in the current Service TLV.
312
313 while (IterateToNextServer(aIterator) == kErrorNone)
314 {
315 aInfo.mRloc16 = aIterator.mServerSubTlv->GetServer16();
316
317 if (aType == kAddrInServiceData)
318 {
319 if (DnsSrpUnicast::ServiceData::ParseFrom(*aIterator.mServiceTlv, aInfo) == kErrorNone)
320 {
321 ExitNow();
322 }
323
324 // If Service Data does not contain address info, we
325 // break from `while (IterateToNextServer())` loop
326 // to skip over the entire Service TLV and all its
327 // sub-TLVs and go to the next one.
328
329 break;
330 }
331
332 // `aType` is `kAddrInServerData`.
333
334 // Server sub-TLV can contain address and port info
335 // (then we parse and return the info), or it can be
336 // empty (then we skip over it).
337
338 if (DnsSrpUnicast::ServerData::ParseFrom(*aIterator.mServerSubTlv, aInfo) == kErrorNone)
339 {
340 ExitNow();
341 }
342
343 if (aIterator.mServerSubTlv->GetServerDataLength() == sizeof(uint16_t))
344 {
345 // Handle the case where the server TLV data only
346 // contains a port number and use the RLOC as the
347 // IPv6 address.
348
349 aInfo.mSockAddr.GetAddress().SetToRoutingLocator(Get<Mle::Mle>().GetMeshLocalPrefix(),
350 aIterator.mServerSubTlv->GetServer16());
351 aInfo.mSockAddr.SetPort(BigEndian::ReadUint16(aIterator.mServerSubTlv->GetServerData()));
352 aInfo.mVersion = 0;
353 ExitNow();
354 }
355 }
356
357 // Find the next matching Service TLV.
358
359 serviceData.InitFrom(serviceNumber);
360 aIterator.mServiceTlv =
361 Get<Leader>().FindNextThreadService(aIterator.mServiceTlv, serviceData, NetworkData::kServicePrefixMatch);
362 aIterator.mServerSubTlv = nullptr;
363
364 // If we have a valid Service TLV, restart the loop
365 // to process its Server sub-TLVs.
366
367 } while (aIterator.mServiceTlv != nullptr);
368
369 error = kErrorNotFound;
370
371 exit:
372 return error;
373 }
374
IterateToNextServer(Iterator & aIterator) const375 Error Manager::IterateToNextServer(Iterator &aIterator) const
376 {
377 Error error = kErrorNotFound;
378
379 VerifyOrExit(aIterator.mServiceTlv != nullptr);
380
381 aIterator.mServerSubTlv = NetworkDataTlv::Find<ServerTlv>(
382 /* aStart */ (aIterator.mServerSubTlv != nullptr) ? aIterator.mServerSubTlv->GetNext()
383 : aIterator.mServiceTlv->GetSubTlvs(),
384 /* aEnd */ aIterator.mServiceTlv->GetNext());
385
386 if (aIterator.mServerSubTlv != nullptr)
387 {
388 error = kErrorNone;
389 }
390
391 exit:
392 return error;
393 }
394
395 } // namespace Service
396 } // namespace NetworkData
397 } // namespace ot
398