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 includes definitions for manipulating Thread Network Data managed by the Thread Leader.
32  */
33 
34 #ifndef NETWORK_DATA_LEADER_HPP_
35 #define NETWORK_DATA_LEADER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <stdint.h>
40 
41 #include "coap/coap.hpp"
42 #include "common/const_cast.hpp"
43 #include "common/timer.hpp"
44 #include "net/ip6_address.hpp"
45 #include "thread/mle_router.hpp"
46 #include "thread/network_data.hpp"
47 
48 namespace ot {
49 
50 namespace NetworkData {
51 
52 /**
53  * @addtogroup core-netdata-leader
54  *
55  * @brief
56  *   This module includes definitions for manipulating Thread Network Data managed by the Thread Leader.
57  *
58  * @{
59  *
60  */
61 
62 /**
63  * This class implements the Thread Network Data maintained by the Leader.
64  *
65  */
66 class LeaderBase : public MutableNetworkData
67 {
68 public:
69     /**
70      * This constructor initializes the object.
71      *
72      * @param[in]  aInstance     A reference to the OpenThread instance.
73      *
74      */
LeaderBase(Instance & aInstance)75     explicit LeaderBase(Instance &aInstance)
76         : MutableNetworkData(aInstance, mTlvBuffer, 0, sizeof(mTlvBuffer))
77         , mMaxLength(0)
78     {
79         Reset();
80     }
81 
82     /**
83      * This method reset the Thread Network Data.
84      *
85      */
86     void Reset(void);
87 
88     /**
89      * This method returns the maximum observed Network Data length since OT stack initialization or since the last
90      * call to `ResetMaxLength()`.
91      *
92      * @returns The maximum observed Network Data length (high water mark for Network Data length).
93      *
94      */
GetMaxLength(void) const95     uint8_t GetMaxLength(void) const { return mMaxLength; }
96 
97     /**
98      * This method resets the tracked maximum Network Data Length.
99      *
100      * @sa GetMaxLength
101      *
102      */
ResetMaxLength(void)103     void ResetMaxLength(void) { mMaxLength = GetLength(); }
104 
105     /**
106      * This method returns the Data Version value for a type (full set or stable subset).
107      *
108      * @param[in] aType   The Network Data type (full set or stable subset).
109      *
110      * @returns The Data Version value for @p aType.
111      *
112      */
GetVersion(Type aType) const113     uint8_t GetVersion(Type aType) const { return (aType == kFullSet) ? mVersion : mStableVersion; }
114 
115     /**
116      * This method retrieves the 6LoWPAN Context information based on a given IPv6 address.
117      *
118      * @param[in]   aAddress  A reference to an IPv6 address.
119      * @param[out]  aContext  A reference to 6LoWPAN Context information.
120      *
121      * @retval kErrorNone       Successfully retrieved 6LoWPAN Context information.
122      * @retval kErrorNotFound   Could not find the 6LoWPAN Context information.
123      *
124      */
125     Error GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const;
126 
127     /**
128      * This method retrieves the 6LoWPAN Context information based on a given Context ID.
129      *
130      * @param[in]   aContextId  The Context ID value.
131      * @param[out]  aContext    A reference to the 6LoWPAN Context information.
132      *
133      * @retval kErrorNone       Successfully retrieved 6LoWPAN Context information.
134      * @retval kErrorNotFound   Could not find the 6LoWPAN Context information.
135      *
136      */
137     Error GetContext(uint8_t aContextId, Lowpan::Context &aContext) const;
138 
139     /**
140      * This method indicates whether or not the given IPv6 address is on-mesh.
141      *
142      * @param[in]  aAddress  A reference to an IPv6 address.
143      *
144      * @retval TRUE   If @p aAddress is on-link.
145      * @retval FALSE  If @p aAddress if not on-link.
146      *
147      */
148     bool IsOnMesh(const Ip6::Address &aAddress) const;
149 
150     /**
151      * This method performs a route lookup using the Network Data.
152      *
153      * @param[in]   aSource             A reference to the IPv6 source address.
154      * @param[in]   aDestination        A reference to the IPv6 destination address.
155      * @param[out]  aRloc16             A reference to return the RLOC16 for the selected route.
156      *
157      * @retval kErrorNone      Successfully found a route. @p aRloc16 is updated.
158      * @retval kErrorNoRoute   No valid route was found.
159      *
160      */
161     Error RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, uint16_t &aRloc16) const;
162 
163     /**
164      * This method is used by non-Leader devices to set Network Data by reading it from a message from Leader.
165      *
166      * @param[in]  aVersion        The Version value.
167      * @param[in]  aStableVersion  The Stable Version value.
168      * @param[in]  aType           The Network Data type to set, the full set or stable subset.
169      * @param[in]  aMessage        A reference to the message.
170      * @param[in]  aOffset         The offset in @p aMessage pointing to start of Network Data.
171      * @param[in]  aLength         The length of Network Data.
172      *
173      * @retval kErrorNone   Successfully set the network data.
174      * @retval kErrorParse  Network Data in @p aMessage is not valid.
175      *
176      */
177     Error SetNetworkData(uint8_t        aVersion,
178                          uint8_t        aStableVersion,
179                          Type           aType,
180                          const Message &aMessage,
181                          uint16_t       aOffset,
182                          uint16_t       aLength);
183 
184     /**
185      * This method returns a pointer to the Commissioning Data.
186      *
187      * @returns A pointer to the Commissioning Data or `nullptr` if no Commissioning Data exists.
188      *
189      */
GetCommissioningData(void)190     CommissioningDataTlv *GetCommissioningData(void) { return AsNonConst(AsConst(this)->GetCommissioningData()); }
191 
192     /**
193      * This method returns a pointer to the Commissioning Data.
194      *
195      * @returns A pointer to the Commissioning Data or `nullptr` if no Commissioning Data exists.
196      *
197      */
198     const CommissioningDataTlv *GetCommissioningData(void) const;
199 
200     /**
201      * This method returns a pointer to the Commissioning Data Sub-TLV.
202      *
203      * @param[in]  aType  The TLV type value.
204      *
205      * @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no Sub-TLV exists.
206      *
207      */
GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType)208     MeshCoP::Tlv *GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType)
209     {
210         return AsNonConst(AsConst(this)->GetCommissioningDataSubTlv(aType));
211     }
212 
213     /**
214      * This method returns a pointer to the Commissioning Data Sub-TLV.
215      *
216      * @param[in]  aType  The TLV type value.
217      *
218      * @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no Sub-TLV exists.
219      *
220      */
221     const MeshCoP::Tlv *GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const;
222 
223     /**
224      * This method indicates whether or not the Commissioning Data TLV indicates Joining is enabled.
225      *
226      * Joining is enabled if a Border Agent Locator TLV exist and the Steering Data TLV is non-zero.
227      *
228      * @returns TRUE if the Commissioning Data TLV says Joining is enabled, FALSE otherwise.
229      *
230      */
231     bool IsJoiningEnabled(void) const;
232 
233     /**
234      * This method adds Commissioning Data to the Thread Network Data.
235      *
236      * @param[in]  aValue        A pointer to the Commissioning Data value.
237      * @param[in]  aValueLength  The length of @p aValue.
238      *
239      * @retval kErrorNone     Successfully added the Commissioning Data.
240      * @retval kErrorNoBufs   Insufficient space to add the Commissioning Data.
241      *
242      */
243     Error SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength);
244 
245     /**
246      * This method checks if the steering data includes a Joiner.
247      *
248      * @param[in]  aEui64             A reference to the Joiner's IEEE EUI-64.
249      *
250      * @retval kErrorNone          @p aEui64 is in the bloom filter.
251      * @retval kErrorInvalidState  No steering data present.
252      * @retval kErrorNotFound      @p aEui64 is not in the bloom filter.
253      *
254      */
255     Error SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const;
256 
257     /**
258      * This method checks if the steering data includes a Joiner with a given discerner value.
259      *
260      * @param[in]  aDiscerner         A reference to the Joiner Discerner.
261      *
262      * @retval kErrorNone          @p aDiscerner is in the bloom filter.
263      * @retval kErrorInvalidState  No steering data present.
264      * @retval kErrorNotFound      @p aDiscerner is not in the bloom filter.
265      *
266      */
267     Error SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const;
268 
269     /**
270      * This method gets the Service ID for the specified service.
271      *
272      * @param[in]  aEnterpriseNumber  Enterprise Number (IANA-assigned) for Service TLV
273      * @param[in]  aServiceData       The Service Data.
274      * @param[in]  aServerStable      The Stable flag value for Server TLV.
275      * @param[out] aServiceId         A reference where to put the Service ID.
276      *
277      * @retval kErrorNone       Successfully got the Service ID.
278      * @retval kErrorNotFound   The specified service was not found.
279      *
280      */
281     Error GetServiceId(uint32_t           aEnterpriseNumber,
282                        const ServiceData &aServiceData,
283                        bool               aServerStable,
284                        uint8_t           &aServiceId) const;
285 
286     /**
287      * This methods gets the preferred NAT64 prefix from network data.
288      *
289      * The returned prefix is the highest preference external route entry in Network Data with NAT64 flag set. If there
290      * are multiple such entries the first one is returned.
291      *
292      * @param[out] aConfig      A reference to an `ExternalRouteConfig` to return the prefix.
293      *
294      * @retval kErrorNone       Found the NAT64 prefix and updated @p aConfig.
295      * @retval kErrorNotFound   Could not find any NAT64 entry.
296      *
297      */
298     Error GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const;
299 
300 protected:
301     void SignalNetDataChanged(void);
302 
303     uint8_t mStableVersion;
304     uint8_t mVersion;
305 
306 private:
307     using FilterIndexes = MeshCoP::SteeringData::HashBitIndexes;
308 
309     const PrefixTlv *FindNextMatchingPrefixTlv(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const;
310 
311     void RemoveCommissioningData(void);
312 
313     template <typename EntryType> int CompareRouteEntries(const EntryType &aFirst, const EntryType &aSecond) const;
314     int                               CompareRouteEntries(int8_t   aFirstPreference,
315                                                           uint16_t aFirstRloc,
316                                                           int8_t   aSecondPreference,
317                                                           uint16_t aSecondRloc) const;
318 
319     Error ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDestination, uint16_t &aRloc16) const;
320     Error DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) const;
321     Error SteeringDataCheck(const FilterIndexes &aFilterIndexes) const;
322     void  GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const;
323 
324     uint8_t mTlvBuffer[kMaxSize];
325     uint8_t mMaxLength;
326 };
327 
328 /**
329  * @}
330  */
331 
332 } // namespace NetworkData
333 } // namespace ot
334 
335 #if OPENTHREAD_MTD
336 namespace ot {
337 namespace NetworkData {
338 class Leader : public LeaderBase
339 {
340 public:
341     using LeaderBase::LeaderBase;
342 };
343 } // namespace NetworkData
344 } // namespace ot
345 #elif OPENTHREAD_FTD
346 #include "network_data_leader_ftd.hpp"
347 #else
348 #error "Please define OPENTHREAD_MTD=1 or OPENTHREAD_FTD=1"
349 #endif
350 
351 #endif // NETWORK_DATA_LEADER_HPP_
352