1 /*
2 * Copyright (c) 2016-21, 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 Thread Network Data related types and constants.
32 */
33
34 #include "network_data_types.hpp"
35
36 #include "instance/instance.hpp"
37 #include "thread/network_data_tlvs.hpp"
38
39 namespace ot {
40 namespace NetworkData {
41
42 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
43
IsPrefixValid(Instance & aInstance,const Ip6::Prefix & aPrefix)44 static bool IsPrefixValid(Instance &aInstance, const Ip6::Prefix &aPrefix)
45 {
46 // Check that prefix length is within the valid range and the prefix
47 // does not overlap with the mesh-local prefix.
48
49 return aPrefix.IsValid() && !aPrefix.ContainsPrefix(aInstance.Get<Mle::Mle>().GetMeshLocalPrefix());
50 }
51
IsValid(Instance & aInstance) const52 bool OnMeshPrefixConfig::IsValid(Instance &aInstance) const
53 {
54 bool isValid = false;
55
56 if (mDhcp && mSlaac)
57 {
58 // A valid prefix MUST NOT allow both DHCPv6 and SLAAC for
59 // address configuration.
60 ExitNow();
61 }
62
63 if (mSlaac)
64 {
65 // An IPv6 address prefix used for stateless auto-configuration
66 // [RFC4862] of an IEEE 802.15.4 interface MUST have a length of
67 // 64 bits.
68 VerifyOrExit(GetPrefix().GetLength() == Ip6::NetworkPrefix::kLength);
69 }
70
71 VerifyOrExit(IsRoutePreferenceValid(mPreference));
72 VerifyOrExit(IsPrefixValid(aInstance, GetPrefix()));
73 VerifyOrExit(GetPrefix().GetLength() > 0);
74
75 isValid = true;
76
77 exit:
78 return isValid;
79 }
80
ConvertToTlvFlags(void) const81 uint16_t OnMeshPrefixConfig::ConvertToTlvFlags(void) const
82 {
83 uint16_t flags = 0;
84
85 if (mPreferred)
86 {
87 flags |= BorderRouterEntry::kPreferredFlag;
88 }
89
90 if (mSlaac)
91 {
92 flags |= BorderRouterEntry::kSlaacFlag;
93 }
94
95 if (mDhcp)
96 {
97 flags |= BorderRouterEntry::kDhcpFlag;
98 }
99
100 if (mConfigure)
101 {
102 flags |= BorderRouterEntry::kConfigureFlag;
103 }
104
105 if (mDefaultRoute)
106 {
107 flags |= BorderRouterEntry::kDefaultRouteFlag;
108 }
109
110 if (mOnMesh)
111 {
112 flags |= BorderRouterEntry::kOnMeshFlag;
113 }
114
115 if (mNdDns)
116 {
117 flags |= BorderRouterEntry::kNdDnsFlag;
118 }
119
120 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
121 if (mDp)
122 {
123 flags |= BorderRouterEntry::kDpFlag;
124 }
125 #endif
126
127 flags |= (static_cast<uint16_t>(RoutePreferenceToValue(mPreference)) << BorderRouterEntry::kPreferenceOffset);
128
129 return flags;
130 }
131
132 #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
133
SetFrom(const PrefixTlv & aPrefixTlv,const BorderRouterTlv & aBorderRouterTlv,const BorderRouterEntry & aBorderRouterEntry)134 void OnMeshPrefixConfig::SetFrom(const PrefixTlv &aPrefixTlv,
135 const BorderRouterTlv &aBorderRouterTlv,
136 const BorderRouterEntry &aBorderRouterEntry)
137 {
138 Clear();
139
140 aPrefixTlv.CopyPrefixTo(GetPrefix());
141 SetFromTlvFlags(aBorderRouterEntry.GetFlags());
142 mRloc16 = aBorderRouterEntry.GetRloc();
143 mStable = aBorderRouterTlv.IsStable();
144 }
145
SetFromTlvFlags(uint16_t aFlags)146 void OnMeshPrefixConfig::SetFromTlvFlags(uint16_t aFlags)
147 {
148 mPreferred = ((aFlags & BorderRouterEntry::kPreferredFlag) != 0);
149 mSlaac = ((aFlags & BorderRouterEntry::kSlaacFlag) != 0);
150 mDhcp = ((aFlags & BorderRouterEntry::kDhcpFlag) != 0);
151 mConfigure = ((aFlags & BorderRouterEntry::kConfigureFlag) != 0);
152 mDefaultRoute = ((aFlags & BorderRouterEntry::kDefaultRouteFlag) != 0);
153 mOnMesh = ((aFlags & BorderRouterEntry::kOnMeshFlag) != 0);
154 mNdDns = ((aFlags & BorderRouterEntry::kNdDnsFlag) != 0);
155 mDp = ((aFlags & BorderRouterEntry::kDpFlag) != 0);
156 mPreference = RoutePreferenceFromValue(static_cast<uint8_t>(aFlags >> BorderRouterEntry::kPreferenceOffset));
157 }
158
159 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
IsValid(Instance & aInstance) const160 bool ExternalRouteConfig::IsValid(Instance &aInstance) const
161 {
162 bool isValid = false;
163
164 if (mNat64)
165 {
166 VerifyOrExit(GetPrefix().IsValidNat64());
167 }
168
169 VerifyOrExit(IsRoutePreferenceValid(mPreference));
170 VerifyOrExit(IsPrefixValid(aInstance, GetPrefix()));
171
172 isValid = true;
173
174 exit:
175 return isValid;
176 }
177
ConvertToTlvFlags(void) const178 uint8_t ExternalRouteConfig::ConvertToTlvFlags(void) const
179 {
180 uint8_t flags = 0;
181
182 if (mNat64)
183 {
184 flags |= HasRouteEntry::kNat64Flag;
185 }
186
187 if (mAdvPio)
188 {
189 flags |= HasRouteEntry::kAdvPioFlag;
190 }
191
192 flags |= (RoutePreferenceToValue(mPreference) << HasRouteEntry::kPreferenceOffset);
193
194 return flags;
195 }
196
197 #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
198
SetFrom(Instance & aInstance,const PrefixTlv & aPrefixTlv,const HasRouteTlv & aHasRouteTlv,const HasRouteEntry & aHasRouteEntry)199 void ExternalRouteConfig::SetFrom(Instance &aInstance,
200 const PrefixTlv &aPrefixTlv,
201 const HasRouteTlv &aHasRouteTlv,
202 const HasRouteEntry &aHasRouteEntry)
203 {
204 Clear();
205
206 aPrefixTlv.CopyPrefixTo(GetPrefix());
207 SetFromTlvFlags(aHasRouteEntry.GetFlags());
208 mStable = aHasRouteTlv.IsStable();
209 mRloc16 = aHasRouteEntry.GetRloc();
210 mNextHopIsThisDevice = (aHasRouteEntry.GetRloc() == aInstance.Get<Mle::MleRouter>().GetRloc16());
211 }
212
SetFromTlvFlags(uint8_t aFlags)213 void ExternalRouteConfig::SetFromTlvFlags(uint8_t aFlags)
214 {
215 mNat64 = ((aFlags & HasRouteEntry::kNat64Flag) != 0);
216 mAdvPio = ((aFlags & HasRouteEntry::kAdvPioFlag) != 0);
217 mPreference = RoutePreferenceFromValue(aFlags >> HasRouteEntry::kPreferenceOffset);
218 }
219
operator ==(const ServerConfig & aOther) const220 bool ServiceConfig::ServerConfig::operator==(const ServerConfig &aOther) const
221 {
222 return (mStable == aOther.mStable) && (mServerDataLength == aOther.mServerDataLength) &&
223 (memcmp(mServerData, aOther.mServerData, mServerDataLength) == 0);
224 }
225
SetFrom(const ServerTlv & aServerTlv)226 void ServiceConfig::ServerConfig::SetFrom(const ServerTlv &aServerTlv)
227 {
228 ServerData serverData;
229
230 aServerTlv.GetServerData(serverData);
231 mStable = aServerTlv.IsStable();
232 mRloc16 = aServerTlv.GetServer16();
233 mServerDataLength = serverData.GetLength();
234 serverData.CopyBytesTo(mServerData);
235 }
236
operator ==(const ServiceConfig & aOther) const237 bool ServiceConfig::operator==(const ServiceConfig &aOther) const
238 {
239 return (mEnterpriseNumber == aOther.mEnterpriseNumber) && (mServiceDataLength == aOther.mServiceDataLength) &&
240 (memcmp(mServiceData, aOther.mServiceData, mServiceDataLength) == 0) &&
241 (GetServerConfig() == aOther.GetServerConfig());
242 }
243
SetFrom(const ServiceTlv & aServiceTlv,const ServerTlv & aServerTlv)244 void ServiceConfig::SetFrom(const ServiceTlv &aServiceTlv, const ServerTlv &aServerTlv)
245 {
246 ServiceData serviceData;
247
248 Clear();
249
250 aServiceTlv.GetServiceData(serviceData);
251 mServiceId = aServiceTlv.GetServiceId();
252 mEnterpriseNumber = aServiceTlv.GetEnterpriseNumber();
253 mServiceDataLength = serviceData.GetLength();
254 serviceData.CopyBytesTo(mServiceData);
255 GetServerConfig().SetFrom(aServerTlv);
256 }
257
SetFrom(const PrefixTlv & aPrefixTlv,const ContextTlv & aContextTlv)258 void LowpanContextInfo::SetFrom(const PrefixTlv &aPrefixTlv, const ContextTlv &aContextTlv)
259 {
260 mContextId = aContextTlv.GetContextId();
261 mCompressFlag = aContextTlv.IsCompress();
262 aPrefixTlv.CopyPrefixTo(GetPrefix());
263 GetPrefix().SetLength(aContextTlv.GetContextLength());
264 }
265
266 } // namespace NetworkData
267 } // namespace ot
268