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 DnsSrpUnicast::kServiceData;
53 
54 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
55 
AddService(const void * aServiceData,uint8_t aServiceDataLength,bool aServerStable,const void * aServerData,uint8_t aServerDataLength)56 Error Manager::AddService(const void *aServiceData,
57                           uint8_t     aServiceDataLength,
58                           bool        aServerStable,
59                           const void *aServerData,
60                           uint8_t     aServerDataLength)
61 {
62     return Get<Local>().AddService(kThreadEnterpriseNumber, reinterpret_cast<const uint8_t *>(aServiceData),
63                                    aServiceDataLength, aServerStable, reinterpret_cast<const uint8_t *>(aServerData),
64                                    aServerDataLength);
65 }
66 
RemoveService(const void * aServiceData,uint8_t aServiceDataLength)67 Error Manager::RemoveService(const void *aServiceData, uint8_t aServiceDataLength)
68 {
69     return Get<Local>().RemoveService(kThreadEnterpriseNumber, reinterpret_cast<const uint8_t *>(aServiceData),
70                                       aServiceDataLength);
71 }
72 
73 #endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
74 
GetServiceId(const void * aServiceData,uint8_t aServiceDataLength,bool aServerStable,uint8_t & aServiceId) const75 Error Manager::GetServiceId(const void *aServiceData,
76                             uint8_t     aServiceDataLength,
77                             bool        aServerStable,
78                             uint8_t &   aServiceId) const
79 {
80     return Get<Leader>().GetServiceId(kThreadEnterpriseNumber, reinterpret_cast<const uint8_t *>(aServiceData),
81                                       aServiceDataLength, aServerStable, aServiceId);
82 }
83 
84 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
85 
GetBackboneRouterPrimary(ot::BackboneRouter::BackboneRouterConfig & aConfig) const86 void Manager::GetBackboneRouterPrimary(ot::BackboneRouter::BackboneRouterConfig &aConfig) const
87 {
88     const ServerTlv *                 rvalServerTlv  = nullptr;
89     const BackboneRouter::ServerData *rvalServerData = nullptr;
90     const ServiceTlv *                serviceTlv     = nullptr;
91 
92     aConfig.mServer16 = Mac::kShortAddrInvalid;
93 
94     while ((serviceTlv = Get<Leader>().FindNextService(
95                 serviceTlv, kThreadEnterpriseNumber, &BackboneRouter::kServiceData, BackboneRouter::kServiceDataMinSize,
96                 NetworkData::kServicePrefixMatch)) != nullptr)
97     {
98         Iterator iterator;
99 
100         iterator.mServiceTlv = serviceTlv;
101 
102         while (IterateToNextServer(iterator) == kErrorNone)
103         {
104             const BackboneRouter::ServerData *serverData;
105 
106             if (iterator.mServerSubTlv->GetServerDataLength() < sizeof(BackboneRouter::ServerData))
107             {
108                 continue;
109             }
110 
111             serverData = reinterpret_cast<const BackboneRouter::ServerData *>(iterator.mServerSubTlv->GetServerData());
112 
113             if (rvalServerTlv == nullptr ||
114                 IsBackboneRouterPreferredTo(*iterator.mServerSubTlv, *serverData, *rvalServerTlv, *rvalServerData))
115             {
116                 rvalServerTlv  = iterator.mServerSubTlv;
117                 rvalServerData = serverData;
118             }
119         }
120     }
121 
122     VerifyOrExit(rvalServerTlv != nullptr);
123 
124     aConfig.mServer16            = rvalServerTlv->GetServer16();
125     aConfig.mSequenceNumber      = rvalServerData->GetSequenceNumber();
126     aConfig.mReregistrationDelay = rvalServerData->GetReregistrationDelay();
127     aConfig.mMlrTimeout          = rvalServerData->GetMlrTimeout();
128 
129 exit:
130     return;
131 }
132 
IsBackboneRouterPreferredTo(const ServerTlv & aServerTlv,const BackboneRouter::ServerData & aServerData,const ServerTlv & aOtherServerTlv,const BackboneRouter::ServerData & aOtherServerData) const133 bool Manager::IsBackboneRouterPreferredTo(const ServerTlv &                 aServerTlv,
134                                           const BackboneRouter::ServerData &aServerData,
135                                           const ServerTlv &                 aOtherServerTlv,
136                                           const BackboneRouter::ServerData &aOtherServerData) const
137 {
138     bool     isPreferred;
139     uint16_t leaderRloc16 = Mle::Mle::Rloc16FromRouterId(Get<Mle::MleRouter>().GetLeaderId());
140 
141     VerifyOrExit(aServerTlv.GetServer16() != leaderRloc16, isPreferred = true);
142     VerifyOrExit(aOtherServerTlv.GetServer16() != leaderRloc16, isPreferred = false);
143 
144     isPreferred = aServerData.GetSequenceNumber() > aOtherServerData.GetSequenceNumber() ||
145                   (aServerData.GetSequenceNumber() == aOtherServerData.GetSequenceNumber() &&
146                    aServerTlv.GetServer16() > aOtherServerTlv.GetServer16());
147 exit:
148     return isPreferred;
149 }
150 
151 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
152 
GetNextDnsSrpAnycastInfo(Iterator & aIterator,DnsSrpAnycast::Info & aInfo) const153 Error Manager::GetNextDnsSrpAnycastInfo(Iterator &aIterator, DnsSrpAnycast::Info &aInfo) const
154 {
155     Error             error       = kErrorNone;
156     uint8_t           serviceData = DnsSrpAnycast::kServiceNumber;
157     const ServiceTlv *tlv         = aIterator.mServiceTlv;
158 
159     do
160     {
161         tlv = Get<Leader>().FindNextService(tlv, kThreadEnterpriseNumber, &serviceData, sizeof(serviceData),
162                                             NetworkData::kServicePrefixMatch);
163         VerifyOrExit(tlv != nullptr, error = kErrorNotFound);
164 
165     } while (tlv->GetServiceDataLength() < sizeof(DnsSrpAnycast::ServiceData));
166 
167     aInfo.mAnycastAddress.SetToAnycastLocator(Get<Mle::Mle>().GetMeshLocalPrefix(),
168                                               Mle::Mle::ServiceAlocFromId(tlv->GetServiceId()));
169     aInfo.mSequenceNumber =
170         reinterpret_cast<const DnsSrpAnycast::ServiceData *>(tlv->GetServiceData())->GetSequenceNumber();
171 
172     aIterator.mServiceTlv = tlv;
173 
174 exit:
175     return error;
176 }
177 
FindPreferredDnsSrpAnycastInfo(DnsSrpAnycast::Info & aInfo) const178 Error Manager::FindPreferredDnsSrpAnycastInfo(DnsSrpAnycast::Info &aInfo) const
179 {
180     Iterator            iterator;
181     DnsSrpAnycast::Info info;
182     bool                found = false;
183 
184     while (GetNextDnsSrpAnycastInfo(iterator, info) == kErrorNone)
185     {
186         if (!found || info.IsSequenceNumberAheadOf(aInfo))
187         {
188             aInfo = info;
189             found = true;
190         }
191     }
192 
193     return found ? kErrorNone : kErrorNotFound;
194 }
195 
GetNextDnsSrpUnicastInfo(Iterator & aIterator,DnsSrpUnicast::Info & aInfo) const196 Error Manager::GetNextDnsSrpUnicastInfo(Iterator &aIterator, DnsSrpUnicast::Info &aInfo) const
197 {
198     Error error = kErrorNone;
199 
200     while (true)
201     {
202         // Process Server sub-TLVs in the current Service TLV.
203 
204         while (IterateToNextServer(aIterator) == kErrorNone)
205         {
206             // Server sub-TLV can contain address and port info
207             // (then we parse and return the info), or it can be
208             // empty (then we skip over it).
209 
210             if (aIterator.mServerSubTlv->GetServerDataLength() >= sizeof(DnsSrpUnicast::ServerData))
211             {
212                 const DnsSrpUnicast::ServerData *serverData =
213                     reinterpret_cast<const DnsSrpUnicast::ServerData *>(aIterator.mServerSubTlv->GetServerData());
214 
215                 aInfo.mSockAddr.SetAddress(serverData->GetAddress());
216                 aInfo.mSockAddr.SetPort(serverData->GetPort());
217                 ExitNow();
218             }
219 
220             if (aIterator.mServerSubTlv->GetServerDataLength() == sizeof(uint16_t))
221             {
222                 // Handle the case where the server TLV data only
223                 // contains a port number and use the RLOC as the
224                 // IPv6 address.
225                 aInfo.mSockAddr.GetAddress().SetToRoutingLocator(Get<Mle::Mle>().GetMeshLocalPrefix(),
226                                                                  aIterator.mServerSubTlv->GetServer16());
227                 aInfo.mSockAddr.SetPort(Encoding::BigEndian::ReadUint16(aIterator.mServerSubTlv->GetServerData()));
228                 ExitNow();
229             }
230         }
231 
232         // Find the next matching Service TLV.
233 
234         aIterator.mServiceTlv =
235             Get<Leader>().FindNextService(aIterator.mServiceTlv, kThreadEnterpriseNumber, &DnsSrpUnicast::kServiceData,
236                                           sizeof(DnsSrpUnicast::kServiceData), NetworkData::kServicePrefixMatch);
237 
238         VerifyOrExit(aIterator.mServiceTlv != nullptr, error = kErrorNotFound);
239 
240         if (aIterator.mServiceTlv->GetServiceDataLength() >= sizeof(DnsSrpUnicast::ServiceData))
241         {
242             // The Service TLV data contains the address and port info.
243 
244             const DnsSrpUnicast::ServiceData *serviceData;
245 
246             serviceData = reinterpret_cast<const DnsSrpUnicast::ServiceData *>(aIterator.mServiceTlv->GetServiceData());
247             aInfo.mSockAddr.SetAddress(serviceData->GetAddress());
248             aInfo.mSockAddr.SetPort(serviceData->GetPort());
249             ExitNow();
250         }
251 
252         // Go back to the start of `while (true)` loop to
253         // process the Server sub-TLVs in the new Service TLV.
254     }
255 
256 exit:
257     return error;
258 }
259 
IterateToNextServer(Iterator & aIterator) const260 Error Manager::IterateToNextServer(Iterator &aIterator) const
261 {
262     Error error = kErrorNotFound;
263 
264     VerifyOrExit(aIterator.mServiceTlv != nullptr);
265 
266     aIterator.mServerSubTlv = NetworkDataTlv::Find<ServerTlv>(
267         /* aStart */ (aIterator.mServerSubTlv != nullptr) ? aIterator.mServerSubTlv->GetNext()
268                                                           : aIterator.mServiceTlv->GetSubTlvs(),
269         /* aEnd */ aIterator.mServiceTlv->GetNext());
270 
271     if (aIterator.mServerSubTlv != nullptr)
272     {
273         error = kErrorNone;
274     }
275 
276 exit:
277     return error;
278 }
279 
280 } // namespace Service
281 } // namespace NetworkData
282 } // namespace ot
283