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 "instance/instance.hpp"
39 
40 namespace ot {
41 namespace NetworkData {
42 
43 RegisterLogModule("NetworkData");
44 
45 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
46 
AddOnMeshPrefix(const OnMeshPrefixConfig & aConfig)47 Error Local::AddOnMeshPrefix(const OnMeshPrefixConfig &aConfig)
48 {
49     Error error = kErrorInvalidArgs;
50 
51     VerifyOrExit(aConfig.IsValid(GetInstance()));
52 
53     error =
54         AddPrefix(aConfig.GetPrefix(), NetworkDataTlv::kTypeBorderRouter, aConfig.ConvertToTlvFlags(), aConfig.mStable);
55 
56 exit:
57     return error;
58 }
59 
ContainsOnMeshPrefix(const Ip6::Prefix & aPrefix) const60 bool Local::ContainsOnMeshPrefix(const Ip6::Prefix &aPrefix) const
61 {
62     const PrefixTlv *tlv;
63     bool             contains = false;
64 
65     VerifyOrExit((tlv = FindPrefix(aPrefix)) != nullptr);
66     VerifyOrExit(tlv->FindSubTlv(NetworkDataTlv::kTypeBorderRouter) != nullptr);
67 
68     contains = true;
69 
70 exit:
71     return contains;
72 }
73 
AddHasRoutePrefix(const ExternalRouteConfig & aConfig)74 Error Local::AddHasRoutePrefix(const ExternalRouteConfig &aConfig)
75 {
76     Error error = kErrorInvalidArgs;
77 
78     VerifyOrExit(aConfig.IsValid(GetInstance()));
79 
80     error = AddPrefix(aConfig.GetPrefix(), NetworkDataTlv::kTypeHasRoute, aConfig.ConvertToTlvFlags(), aConfig.mStable);
81 
82 exit:
83     return error;
84 }
85 
AddPrefix(const Ip6::Prefix & aPrefix,NetworkDataTlv::Type aSubTlvType,uint16_t aFlags,bool aStable)86 Error Local::AddPrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType, uint16_t aFlags, bool aStable)
87 {
88     Error      error = kErrorNone;
89     uint8_t    subTlvLength;
90     PrefixTlv *prefixTlv;
91 
92     IgnoreError(RemovePrefix(aPrefix));
93 
94     subTlvLength = (aSubTlvType == NetworkDataTlv::kTypeBorderRouter)
95                        ? sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry)
96                        : sizeof(HasRouteTlv) + sizeof(HasRouteEntry);
97 
98     prefixTlv = As<PrefixTlv>(AppendTlv(sizeof(PrefixTlv) + aPrefix.GetBytesSize() + subTlvLength));
99     VerifyOrExit(prefixTlv != nullptr, error = kErrorNoBufs);
100 
101     prefixTlv->Init(0, aPrefix);
102     prefixTlv->SetSubTlvsLength(subTlvLength);
103 
104     if (aSubTlvType == NetworkDataTlv::kTypeBorderRouter)
105     {
106         BorderRouterTlv *brTlv = As<BorderRouterTlv>(prefixTlv->GetSubTlvs());
107         brTlv->Init();
108         brTlv->SetLength(brTlv->GetLength() + sizeof(BorderRouterEntry));
109         brTlv->GetEntry(0)->Init();
110         brTlv->GetEntry(0)->SetFlags(aFlags);
111     }
112     else // aSubTlvType is NetworkDataTlv::kTypeHasRoute
113     {
114         HasRouteTlv *hasRouteTlv = As<HasRouteTlv>(prefixTlv->GetSubTlvs());
115         hasRouteTlv->Init();
116         hasRouteTlv->SetLength(hasRouteTlv->GetLength() + sizeof(HasRouteEntry));
117         hasRouteTlv->GetEntry(0)->Init();
118         hasRouteTlv->GetEntry(0)->SetFlags(static_cast<uint8_t>(aFlags));
119     }
120 
121     if (aStable)
122     {
123         prefixTlv->SetStable();
124         prefixTlv->GetSubTlvs()->SetStable();
125     }
126 
127     DumpDebg("AddPrefix", GetBytes(), GetLength());
128 
129 exit:
130 #if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
131     if (error == kErrorNoBufs)
132     {
133         Get<Notifier>().SignalNetworkDataFull();
134     }
135 #endif
136 
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         }
172     }
173 }
174 
175 #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
176 
177 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
AddService(uint32_t aEnterpriseNumber,const ServiceData & aServiceData,bool aServerStable,const ServerData & aServerData)178 Error Local::AddService(uint32_t           aEnterpriseNumber,
179                         const ServiceData &aServiceData,
180                         bool               aServerStable,
181                         const ServerData  &aServerData)
182 {
183     Error       error = kErrorNone;
184     ServiceTlv *serviceTlv;
185     ServerTlv  *serverTlv;
186     uint16_t    serviceTlvSize = ServiceTlv::CalculateSize(aEnterpriseNumber, aServiceData.GetLength()) +
187                               sizeof(ServerTlv) + aServerData.GetLength();
188 
189     IgnoreError(RemoveService(aEnterpriseNumber, aServiceData));
190 
191     VerifyOrExit(serviceTlvSize <= kMaxSize, error = kErrorNoBufs);
192 
193     serviceTlv = As<ServiceTlv>(AppendTlv(serviceTlvSize));
194     VerifyOrExit(serviceTlv != nullptr, error = kErrorNoBufs);
195 
196     serviceTlv->Init(/* aServiceId */ 0, aEnterpriseNumber, aServiceData);
197     serviceTlv->SetSubTlvsLength(sizeof(ServerTlv) + aServerData.GetLength());
198 
199     serverTlv = As<ServerTlv>(serviceTlv->GetSubTlvs());
200     serverTlv->Init(Get<Mle::MleRouter>().GetRloc16(), aServerData);
201 
202     // According to Thread spec 1.1.1, section 5.18.6 Service TLV:
203     // "The Stable flag is set if any of the included sub-TLVs have their Stable flag set."
204     // The meaning also seems to be 'if and only if'.
205     if (aServerStable)
206     {
207         serviceTlv->SetStable();
208         serverTlv->SetStable();
209     }
210 
211     DumpDebg("AddService", GetBytes(), GetLength());
212 
213 exit:
214 #if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
215     if (error == kErrorNoBufs)
216     {
217         Get<Notifier>().SignalNetworkDataFull();
218     }
219 #endif
220 
221     return error;
222 }
223 
RemoveService(uint32_t aEnterpriseNumber,const ServiceData & aServiceData)224 Error Local::RemoveService(uint32_t aEnterpriseNumber, const ServiceData &aServiceData)
225 {
226     Error       error = kErrorNone;
227     ServiceTlv *tlv;
228 
229     VerifyOrExit((tlv = FindService(aEnterpriseNumber, aServiceData, kServiceExactMatch)) != nullptr,
230                  error = kErrorNotFound);
231     RemoveTlv(tlv);
232 
233 exit:
234     DumpDebg("RmvService", GetBytes(), GetLength());
235     return error;
236 }
237 
UpdateRloc(ServiceTlv & aService)238 void Local::UpdateRloc(ServiceTlv &aService)
239 {
240     uint16_t rloc16 = Get<Mle::MleRouter>().GetRloc16();
241 
242     for (NetworkDataTlv *cur = aService.GetSubTlvs(); cur < aService.GetNext(); cur = cur->GetNext())
243     {
244         switch (cur->GetType())
245         {
246         case NetworkDataTlv::kTypeServer:
247             As<ServerTlv>(cur)->SetServer16(rloc16);
248             break;
249 
250         default:
251             OT_ASSERT(false);
252         }
253     }
254 }
255 
256 #endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
257 
UpdateRloc(void)258 void Local::UpdateRloc(void)
259 {
260     for (NetworkDataTlv *cur = GetTlvsStart(); cur < GetTlvsEnd(); cur = cur->GetNext())
261     {
262         switch (cur->GetType())
263         {
264 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
265         case NetworkDataTlv::kTypePrefix:
266             UpdateRloc(*As<PrefixTlv>(cur));
267             break;
268 #endif
269 
270 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
271 
272         case NetworkDataTlv::kTypeService:
273             UpdateRloc(*As<ServiceTlv>(cur));
274             break;
275 #endif
276 
277         default:
278             OT_ASSERT(false);
279         }
280     }
281 }
282 
283 } // namespace NetworkData
284 } // namespace ot
285 
286 #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
287