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