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