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