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