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