• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, 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 the local Thread Network Data.
32  */
33 
34 #include "network_data_local.hpp"
35 
36 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
37 
38 #include "common/code_utils.hpp"
39 #include "common/debug.hpp"
40 #include "common/instance.hpp"
41 #include "common/locator_getters.hpp"
42 #include "common/log.hpp"
43 #include "mac/mac_types.hpp"
44 #include "thread/mle_types.hpp"
45 #include "thread/thread_netif.hpp"
46 
47 namespace ot {
48 namespace NetworkData {
49 
50 RegisterLogModule("NetworkData");
51 
52 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
53 
AddOnMeshPrefix(const OnMeshPrefixConfig & aConfig)54 Error Local::AddOnMeshPrefix(const OnMeshPrefixConfig &aConfig)
55 {
56     Error error = kErrorInvalidArgs;
57 
58     VerifyOrExit(aConfig.IsValid(GetInstance()));
59 
60     error =
61         AddPrefix(aConfig.GetPrefix(), NetworkDataTlv::kTypeBorderRouter, aConfig.ConvertToTlvFlags(), aConfig.mStable);
62 
63 exit:
64     return error;
65 }
66 
ContainsOnMeshPrefix(const Ip6::Prefix & aPrefix) const67 bool Local::ContainsOnMeshPrefix(const Ip6::Prefix &aPrefix) const
68 {
69     const PrefixTlv *tlv;
70     bool             contains = false;
71 
72     VerifyOrExit((tlv = FindPrefix(aPrefix)) != nullptr);
73     VerifyOrExit(tlv->FindSubTlv(NetworkDataTlv::kTypeBorderRouter) != nullptr);
74 
75     contains = true;
76 
77 exit:
78     return contains;
79 }
80 
AddHasRoutePrefix(const ExternalRouteConfig & aConfig)81 Error Local::AddHasRoutePrefix(const ExternalRouteConfig &aConfig)
82 {
83     Error error = kErrorInvalidArgs;
84 
85     VerifyOrExit(aConfig.IsValid(GetInstance()));
86 
87     error = AddPrefix(aConfig.GetPrefix(), NetworkDataTlv::kTypeHasRoute, aConfig.ConvertToTlvFlags(), aConfig.mStable);
88 
89 exit:
90     return error;
91 }
92 
AddPrefix(const Ip6::Prefix & aPrefix,NetworkDataTlv::Type aSubTlvType,uint16_t aFlags,bool aStable)93 Error Local::AddPrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType, uint16_t aFlags, bool aStable)
94 {
95     Error      error = kErrorNone;
96     uint8_t    subTlvLength;
97     PrefixTlv *prefixTlv;
98 
99     IgnoreError(RemovePrefix(aPrefix));
100 
101     subTlvLength = (aSubTlvType == NetworkDataTlv::kTypeBorderRouter)
102                        ? sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry)
103                        : sizeof(HasRouteTlv) + sizeof(HasRouteEntry);
104 
105     prefixTlv = As<PrefixTlv>(AppendTlv(sizeof(PrefixTlv) + aPrefix.GetBytesSize() + subTlvLength));
106     VerifyOrExit(prefixTlv != nullptr, error = kErrorNoBufs);
107 
108     prefixTlv->Init(0, aPrefix);
109     prefixTlv->SetSubTlvsLength(subTlvLength);
110 
111     if (aSubTlvType == NetworkDataTlv::kTypeBorderRouter)
112     {
113         BorderRouterTlv *brTlv = As<BorderRouterTlv>(prefixTlv->GetSubTlvs());
114         brTlv->Init();
115         brTlv->SetLength(brTlv->GetLength() + sizeof(BorderRouterEntry));
116         brTlv->GetEntry(0)->Init();
117         brTlv->GetEntry(0)->SetFlags(aFlags);
118     }
119     else // aSubTlvType is NetworkDataTlv::kTypeHasRoute
120     {
121         HasRouteTlv *hasRouteTlv = As<HasRouteTlv>(prefixTlv->GetSubTlvs());
122         hasRouteTlv->Init();
123         hasRouteTlv->SetLength(hasRouteTlv->GetLength() + sizeof(HasRouteEntry));
124         hasRouteTlv->GetEntry(0)->Init();
125         hasRouteTlv->GetEntry(0)->SetFlags(static_cast<uint8_t>(aFlags));
126     }
127 
128     if (aStable)
129     {
130         prefixTlv->SetStable();
131         prefixTlv->GetSubTlvs()->SetStable();
132     }
133 
134     DumpDebg("AddPrefix", GetBytes(), GetLength());
135 
136 exit:
137     return error;
138 }
139 
RemovePrefix(const Ip6::Prefix & aPrefix)140 Error Local::RemovePrefix(const Ip6::Prefix &aPrefix)
141 {
142     Error      error = kErrorNone;
143     PrefixTlv *tlv;
144 
145     VerifyOrExit((tlv = FindPrefix(aPrefix)) != nullptr, error = kErrorNotFound);
146     RemoveTlv(tlv);
147 
148 exit:
149     DumpDebg("RmvPrefix", GetBytes(), GetLength());
150     return error;
151 }
152 
UpdateRloc(PrefixTlv & aPrefixTlv)153 void Local::UpdateRloc(PrefixTlv &aPrefixTlv)
154 {
155     uint16_t rloc16 = Get<Mle::MleRouter>().GetRloc16();
156 
157     for (NetworkDataTlv *cur = aPrefixTlv.GetSubTlvs(); cur < aPrefixTlv.GetNext(); cur = cur->GetNext())
158     {
159         switch (cur->GetType())
160         {
161         case NetworkDataTlv::kTypeHasRoute:
162             As<HasRouteTlv>(cur)->GetEntry(0)->SetRloc(rloc16);
163             break;
164 
165         case NetworkDataTlv::kTypeBorderRouter:
166             As<BorderRouterTlv>(cur)->GetEntry(0)->SetRloc(rloc16);
167             break;
168 
169         default:
170             OT_ASSERT(false);
171             OT_UNREACHABLE_CODE(break);
172         }
173     }
174 }
175 
176 #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
177 
178 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
AddService(uint32_t aEnterpriseNumber,const ServiceData & aServiceData,bool aServerStable,const ServerData & aServerData)179 Error Local::AddService(uint32_t           aEnterpriseNumber,
180                         const ServiceData &aServiceData,
181                         bool               aServerStable,
182                         const ServerData & aServerData)
183 {
184     Error       error = kErrorNone;
185     ServiceTlv *serviceTlv;
186     ServerTlv * serverTlv;
187     uint16_t    serviceTlvSize = ServiceTlv::CalculateSize(aEnterpriseNumber, aServiceData.GetLength()) +
188                               sizeof(ServerTlv) + aServerData.GetLength();
189 
190     IgnoreError(RemoveService(aEnterpriseNumber, aServiceData));
191 
192     VerifyOrExit(serviceTlvSize <= kMaxSize, error = kErrorNoBufs);
193 
194     serviceTlv = As<ServiceTlv>(AppendTlv(serviceTlvSize));
195     VerifyOrExit(serviceTlv != nullptr, error = kErrorNoBufs);
196 
197     serviceTlv->Init(/* aServiceId */ 0, aEnterpriseNumber, aServiceData);
198     serviceTlv->SetSubTlvsLength(sizeof(ServerTlv) + aServerData.GetLength());
199 
200     serverTlv = As<ServerTlv>(serviceTlv->GetSubTlvs());
201     serverTlv->Init(Get<Mle::MleRouter>().GetRloc16(), aServerData);
202 
203     // According to Thread spec 1.1.1, section 5.18.6 Service TLV:
204     // "The Stable flag is set if any of the included sub-TLVs have their Stable flag set."
205     // The meaning also seems to be 'if and only if'.
206     if (aServerStable)
207     {
208         serviceTlv->SetStable();
209         serverTlv->SetStable();
210     }
211 
212     DumpDebg("AddService", GetBytes(), GetLength());
213 
214 exit:
215     return error;
216 }
217 
RemoveService(uint32_t aEnterpriseNumber,const ServiceData & aServiceData)218 Error Local::RemoveService(uint32_t aEnterpriseNumber, const ServiceData &aServiceData)
219 {
220     Error       error = kErrorNone;
221     ServiceTlv *tlv;
222 
223     VerifyOrExit((tlv = FindService(aEnterpriseNumber, aServiceData, kServiceExactMatch)) != nullptr,
224                  error = kErrorNotFound);
225     RemoveTlv(tlv);
226 
227 exit:
228     DumpDebg("RmvService", GetBytes(), GetLength());
229     return error;
230 }
231 
UpdateRloc(ServiceTlv & aService)232 void Local::UpdateRloc(ServiceTlv &aService)
233 {
234     uint16_t rloc16 = Get<Mle::MleRouter>().GetRloc16();
235 
236     for (NetworkDataTlv *cur = aService.GetSubTlvs(); cur < aService.GetNext(); cur = cur->GetNext())
237     {
238         switch (cur->GetType())
239         {
240         case NetworkDataTlv::kTypeServer:
241             As<ServerTlv>(cur)->SetServer16(rloc16);
242             break;
243 
244         default:
245             OT_ASSERT(false);
246             OT_UNREACHABLE_CODE(break);
247         }
248     }
249 }
250 
251 #endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
252 
UpdateRloc(void)253 void Local::UpdateRloc(void)
254 {
255     for (NetworkDataTlv *cur = GetTlvsStart(); cur < GetTlvsEnd(); cur = cur->GetNext())
256     {
257         switch (cur->GetType())
258         {
259 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
260         case NetworkDataTlv::kTypePrefix:
261             UpdateRloc(*As<PrefixTlv>(cur));
262             break;
263 #endif
264 
265 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
266 
267         case NetworkDataTlv::kTypeService:
268             UpdateRloc(*As<ServiceTlv>(cur));
269             break;
270 #endif
271 
272         default:
273             OT_ASSERT(false);
274             OT_UNREACHABLE_CODE(break);
275         }
276     }
277 }
278 
IsConsistent(void) const279 bool Local::IsConsistent(void) const
280 {
281     return Get<Leader>().ContainsEntriesFrom(*this, Get<Mle::MleRouter>().GetRloc16()) &&
282            ContainsEntriesFrom(Get<Leader>(), Get<Mle::MleRouter>().GetRloc16());
283 }
284 
UpdateInconsistentServerData(Coap::ResponseHandler aHandler,void * aContext)285 Error Local::UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext)
286 {
287     Error    error = kErrorNone;
288     uint16_t rloc  = Get<Mle::MleRouter>().GetRloc16();
289 
290 #if OPENTHREAD_FTD
291     // Don't send this Server Data Notification if the device is going to upgrade to Router
292     if (Get<Mle::MleRouter>().IsExpectedToBecomeRouterSoon())
293     {
294         ExitNow(error = kErrorInvalidState);
295     }
296 #endif
297 
298     UpdateRloc();
299 
300     VerifyOrExit(!IsConsistent(), error = kErrorNotFound);
301 
302     if (mOldRloc == rloc)
303     {
304         mOldRloc = Mac::kShortAddrInvalid;
305     }
306 
307     SuccessOrExit(error = SendServerDataNotification(mOldRloc, /* aAppendNetDataTlv */ true, aHandler, aContext));
308     mOldRloc = rloc;
309 
310 exit:
311     return error;
312 }
313 
314 } // namespace NetworkData
315 } // namespace ot
316 
317 #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
318