• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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