• 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 
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