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 managing Thread Network Data.
32  */
33 
34 #ifndef NETWORK_DATA_HPP_
35 #define NETWORK_DATA_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/border_router.h>
40 #include <openthread/server.h>
41 
42 #include "coap/coap.hpp"
43 #include "common/clearable.hpp"
44 #include "common/const_cast.hpp"
45 #include "common/equatable.hpp"
46 #include "common/locator.hpp"
47 #include "common/timer.hpp"
48 #include "net/udp6.hpp"
49 #include "thread/lowpan.hpp"
50 #include "thread/mle_router.hpp"
51 #include "thread/network_data_tlvs.hpp"
52 #include "thread/network_data_types.hpp"
53 
54 namespace ot {
55 
56 /**
57  * @addtogroup core-netdata
58  * @brief
59  *   This module includes definitions for generating, processing, and managing Thread Network Data.
60  *
61  * @{
62  *
63  * @defgroup core-netdata-core Core
64  * @defgroup core-netdata-leader Leader
65  * @defgroup core-netdata-local Local
66  * @defgroup core-netdata-tlvs TLVs
67  *
68  * @}
69  *
70  */
71 
72 /**
73  * @namespace ot::NetworkData
74  *
75  * @brief
76  *   This namespace includes definitions for managing Thread Network Data.
77  *
78  */
79 namespace NetworkData {
80 
81 namespace Service {
82 class Manager;
83 }
84 
85 /**
86  * @addtogroup core-netdata-core
87  *
88  * @brief
89  *   This module includes definitions for managing Thread Network Data.
90  *
91  * @{
92  *
93  */
94 
95 class Leader;
96 class Publisher;
97 class MutableNetworkData;
98 
99 /**
100  * This type represents a Iterator used to iterate through Network Data info (e.g., see `GetNextOnMeshPrefix()`)
101  *
102  */
103 typedef otNetworkDataIterator Iterator;
104 
105 constexpr Iterator kIteratorInit = OT_NETWORK_DATA_ITERATOR_INIT; ///< Initializer for `Iterator` type.
106 
107 /**
108  * This class represents an immutable Network Data.
109  *
110  */
111 class NetworkData : public InstanceLocator
112 {
113     friend class Leader;
114     friend class Publisher;
115     friend class MutableNetworkData;
116     friend class Service::Manager;
117 
118 public:
119     static constexpr uint8_t kMaxSize = 254; ///< Maximum size of Thread Network Data in bytes.
120 
121     /**
122      * This constructor initializes the `NetworkData` from a given pointer to a buffer and length.
123      *
124      * @param[in] aInstance     A reference to the OpenThread instance.
125      * @param[in] aTlvs         A pointer to the buffer containing the TLVs.
126      * @param[in] aLength       The length (number of bytes) of @p aTlvs buffer.
127      *
128      */
NetworkData(Instance & aInstance,const uint8_t * aTlvs=nullptr,uint8_t aLength=0)129     explicit NetworkData(Instance &aInstance, const uint8_t *aTlvs = nullptr, uint8_t aLength = 0)
130         : InstanceLocator(aInstance)
131         , mTlvs(aTlvs)
132         , mLength(aLength)
133     {
134     }
135 
136     /**
137      * This constructor initializes the `NetworkData` from a range of TLVs (given as pair of start and end pointers).
138      *
139      * @param[in] aInstance     A reference to the OpenThread instance.
140      * @param[in] aStartTlv     A pointer to the start of the TLVs buffer.
141      * @param[in] aEndTlv       A pointer to the end of the TLVs buffer.
142      *
143      */
NetworkData(Instance & aInstance,const NetworkDataTlv * aStartTlv,const NetworkDataTlv * aEndTlv)144     NetworkData(Instance &aInstance, const NetworkDataTlv *aStartTlv, const NetworkDataTlv *aEndTlv)
145         : InstanceLocator(aInstance)
146         , mTlvs(reinterpret_cast<const uint8_t *>(aStartTlv))
147         , mLength(static_cast<uint8_t>(reinterpret_cast<const uint8_t *>(aEndTlv) -
148                                        reinterpret_cast<const uint8_t *>(aStartTlv)))
149     {
150     }
151 
152     /**
153      * This method returns the length of `NetworkData` (number of bytes).
154      *
155      * @returns The length of `NetworkData` (number of bytes).
156      *
157      */
GetLength(void) const158     uint8_t GetLength(void) const { return mLength; }
159 
160     /**
161      * This method returns a pointer to the start of the TLVs in `NetworkData`.
162      *
163      * @returns A pointer to the start of the TLVs.
164      *
165      */
GetBytes(void) const166     const uint8_t *GetBytes(void) const { return mTlvs; }
167 
168     /**
169      * This method provides full or stable copy of the Thread Network Data.
170      *
171      * @param[in]     aType        The Network Data type to copy, the full set or stable subset.
172      * @param[out]    aData        A pointer to the data buffer to copy the Network Data into.
173      * @param[in,out] aDataLength  On entry, size of the data buffer pointed to by @p aData.
174      *                             On exit, number of copied bytes.
175      *
176      * @retval kErrorNone       Successfully copied Thread Network Data.
177      * @retval kErrorNoBufs     Not enough space in @p aData to fully copy Thread Network Data.
178      *
179      */
180     Error CopyNetworkData(Type aType, uint8_t *aData, uint8_t &aDataLength) const;
181 
182     /**
183      * This method provides full or stable copy of the Thread Network Data.
184      *
185      * @param[in]    aType        The Network Data type to copy, the full set or stable subset.
186      * @param[out]   aNetworkData A reference to a `MutableNetworkData` to copy the Network Data into.
187      *
188      * @retval kErrorNone       Successfully copied Thread Network Data.
189      * @retval kErrorNoBufs     Not enough space in @p aNetworkData to fully copy Thread Network Data.
190      *
191      */
192     Error CopyNetworkData(Type aType, MutableNetworkData &aNetworkData) const;
193 
194     /**
195      * This method provides the next On Mesh prefix in the Thread Network Data.
196      *
197      * @param[in,out]  aIterator  A reference to the Network Data iterator.
198      * @param[out]     aConfig    A reference to a config variable where the On Mesh Prefix information will be placed.
199      *
200      * @retval kErrorNone       Successfully found the next On Mesh prefix.
201      * @retval kErrorNotFound   No subsequent On Mesh prefix exists in the Thread Network Data.
202      *
203      */
204     Error GetNextOnMeshPrefix(Iterator &aIterator, OnMeshPrefixConfig &aConfig) const;
205 
206     /**
207      * This method provides the next On Mesh prefix in the Thread Network Data for a given RLOC16.
208      *
209      * @param[in,out]  aIterator  A reference to the Network Data iterator.
210      * @param[in]      aRloc16    The RLOC16 value.
211      * @param[out]     aConfig    A reference to a config variable where the On Mesh Prefix information will be placed.
212      *
213      * @retval kErrorNone       Successfully found the next On Mesh prefix.
214      * @retval kErrorNotFound   No subsequent On Mesh prefix exists in the Thread Network Data.
215      *
216      */
217     Error GetNextOnMeshPrefix(Iterator &aIterator, uint16_t aRloc16, OnMeshPrefixConfig &aConfig) const;
218 
219     /**
220      * This method provides the next external route in the Thread Network Data.
221      *
222      * @param[in,out]  aIterator  A reference to the Network Data iterator.
223      * @param[out]     aConfig    A reference to a config variable where the external route information will be placed.
224      *
225      * @retval kErrorNone       Successfully found the next external route.
226      * @retval kErrorNotFound   No subsequent external route exists in the Thread Network Data.
227      *
228      */
229     Error GetNextExternalRoute(Iterator &aIterator, ExternalRouteConfig &aConfig) const;
230 
231     /**
232      * This method provides the next external route in the Thread Network Data for a given RLOC16.
233      *
234      * @param[in,out]  aIterator  A reference to the Network Data iterator.
235      * @param[in]      aRloc16    The RLOC16 value.
236      * @param[out]     aConfig    A reference to a config variable where the external route information will be placed.
237      *
238      * @retval kErrorNone       Successfully found the next external route.
239      * @retval kErrorNotFound   No subsequent external route exists in the Thread Network Data.
240      *
241      */
242     Error GetNextExternalRoute(Iterator &aIterator, uint16_t aRloc16, ExternalRouteConfig &aConfig) const;
243 
244     /**
245      * This method provides the next service in the Thread Network Data.
246      *
247      * @param[in,out]  aIterator  A reference to the Network Data iterator.
248      * @param[out]     aConfig    A reference to a config variable where the service information will be placed.
249      *
250      * @retval kErrorNone       Successfully found the next service.
251      * @retval kErrorNotFound   No subsequent service exists in the Thread Network Data.
252      *
253      */
254     Error GetNextService(Iterator &aIterator, ServiceConfig &aConfig) const;
255 
256     /**
257      * This method provides the next service in the Thread Network Data for a given RLOC16.
258      *
259      * @param[in,out]  aIterator  A reference to the Network Data iterator.
260      * @param[in]      aRloc16    The RLOC16 value.
261      * @param[out]     aConfig    A reference to a config variable where the service information will be placed.
262      *
263      * @retval kErrorNone       Successfully found the next service.
264      * @retval kErrorNotFound   No subsequent service exists in the Thread Network Data.
265      *
266      */
267     Error GetNextService(Iterator &aIterator, uint16_t aRloc16, ServiceConfig &aConfig) const;
268 
269     /**
270      * This method gets the next 6LoWPAN Context ID info in the Thread Network Data.
271      *
272      * @param[in,out]  aIterator     A reference to the Network Data iterator.
273      * @param[out]     aContextInfo  A reference to where the retrieved 6LoWPAN Context ID information will be placed.
274      *
275      * @retval kErrorNone      Successfully found the next 6LoWPAN Context ID info.
276      * @retval kErrorNotFound  No subsequent 6LoWPAN Context info exists in the partition's Network Data.
277      *
278      */
279     Error GetNextLowpanContextInfo(Iterator &aIterator, LowpanContextInfo &aContextInfo) const;
280 
281     /**
282      * This method indicates whether or not the Thread Network Data contains a given on mesh prefix entry.
283      *
284      * @param[in]  aPrefix   The on mesh prefix config to check.
285      *
286      * @retval TRUE  if Network Data contains an on mesh prefix matching @p aPrefix.
287      * @retval FALSE if Network Data does not contain an on mesh prefix matching @p aPrefix.
288      *
289      */
290     bool ContainsOnMeshPrefix(const OnMeshPrefixConfig &aPrefix) const;
291 
292     /**
293      * This method indicates whether or not the Thread Network Data contains a given external route entry.
294      *
295      * @param[in]  aRoute   The external route config to check.
296      *
297      * @retval TRUE  if Network Data contains an external route matching @p aRoute.
298      * @retval FALSE if Network Data does not contain an external route matching @p aRoute.
299      *
300      */
301     bool ContainsExternalRoute(const ExternalRouteConfig &aRoute) const;
302 
303     /**
304      * This method indicates whether or not the Thread Network Data contains a given service entry.
305      *
306      * @param[in]  aService   The service config to check.
307      *
308      * @retval TRUE  if Network Data contains a service matching @p aService.
309      * @retval FALSE if Network Data does not contain a service matching @p aService.
310      *
311      */
312     bool ContainsService(const ServiceConfig &aService) const;
313 
314     /**
315      * This method indicates whether or not the Thread Network Data contains all the on mesh prefixes, external
316      * routes, and service entries as in another given Network Data associated with a given RLOC16.
317      *
318      * @param[in] aCompare         The Network Data to compare with.
319      * @param[in] aRloc16          The RLOC16 to consider.
320      *
321      * @retval TRUE  if Network Data contains all the same entries as in @p aCompare for @p aRloc16.
322      * @retval FALSE if Network Data does not contains all the same entries as in @p aCompare for @p aRloc16.
323      *
324      */
325     bool ContainsEntriesFrom(const NetworkData &aCompare, uint16_t aRloc16) const;
326 
327     /**
328      * This method provides the next server RLOC16 in the Thread Network Data.
329      *
330      * @param[in,out]  aIterator  A reference to the Network Data iterator.
331      * @param[out]     aRloc16    The RLOC16 value.
332      *
333      * @retval kErrorNone       Successfully found the next server.
334      * @retval kErrorNotFound   No subsequent server exists in the Thread Network Data.
335      *
336      */
337     Error GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const;
338 
339     /**
340      * This method finds and returns the list of RLOCs of border routers providing external IP connectivity.
341      *
342      * A border router is considered to provide external IP connectivity if it has added at least one external route
343      * entry, or an on-mesh prefix with default-route and on-mesh flags set.
344      *
345      * This method should be used when the RLOC16s are present in the Network Data (when the Network Data contains the
346      * full set and not the stable subset).
347      *
348      * @param[in]      aRoleFilter   Indicates which devices to include (any role, router role only, or child only).
349      * @param[out]     aRlocs        Array to output the list of RLOCs.
350      * @param[in,out]  aRlocsLength  On entry, @p aRlocs array length (max number of elements).
351      *                               On exit, number RLOC16 entries added in @p aRlocs.
352      *
353      * @retval kErrorNone     Successfully found all RLOC16s and updated @p aRlocs and @p aRlocsLength.
354      * @retval kErrorNoBufs   Ran out of space in @p aRlocs array. @p aRlocs and @p aRlocsLength are still updated up
355      *                        to the maximum array length.
356      *
357      */
358     Error FindBorderRouters(RoleFilter aRoleFilter, uint16_t aRlocs[], uint8_t &aRlocsLength) const;
359 
360     /**
361      * This method counts the number of border routers providing external IP connectivity.
362      *
363      * A border router is considered to provide external IP connectivity if at least one of the below conditions hold
364      *
365      * - It has added at least one external route entry.
366      * - It has added at least one prefix entry with default-route and on-mesh flags set.
367      * - It has added at least one domain prefix (domain and on-mesh flags set).
368      *
369      * This method should be used when the RLOC16s are present in the Network Data (when the Network Data contains the
370      * full set and not the stable subset).
371      *
372      * @param[in] aRoleFilter   Indicates which RLOCs to include (any role, router only, or child only).
373      *
374      * @returns The number of border routers in Thread Network Data matching @p aRoleFilter.
375      *
376      */
377     uint8_t CountBorderRouters(RoleFilter aRoleFilter) const;
378 
379     /**
380      * This method indicates whether the network data contains a border providing external IP connectivity with a given
381      * RLOC16.
382      *
383      * A border router is considered to provide external IP connectivity if at least one of the below conditions hold
384      *
385      * - It has added at least one external route entry.
386      * - It has added at least one prefix entry with default-route and on-mesh flags set.
387      * - It has added at least one domain prefix (domain and on-mesh flags set).
388      *
389      * This method should be used when the RLOC16s are present in the Network Data (when the Network Data contains the
390      * full set and not the stable subset).
391      *
392      * @param[in] aRloc16   The RLOC16 to check.
393      *
394      * @returns TRUE  If the network data contains a border router with @p aRloc16 providing IP connectivity.
395      * @returns FALSE If the network data does not contain a border router with @p aRloc16 providing IP connectivity.
396      *
397      */
398     bool ContainsBorderRouterWithRloc(uint16_t aRloc16) const;
399 
400 protected:
401     /**
402      * This enumeration defines Service Data match mode.
403      *
404      */
405     enum ServiceMatchMode : uint8_t
406     {
407         kServicePrefixMatch, ///< Match the Service Data by prefix.
408         kServiceExactMatch,  ///< Match the full Service Data exactly.
409     };
410 
411     /**
412      * This method returns a pointer to the start of Network Data TLV sequence.
413      *
414      * @returns A pointer to the start of Network Data TLV sequence.
415      *
416      */
GetTlvsStart(void) const417     const NetworkDataTlv *GetTlvsStart(void) const { return reinterpret_cast<const NetworkDataTlv *>(mTlvs); }
418 
419     /**
420      * This method returns a pointer to the end of Network Data TLV sequence.
421      *
422      * @returns A pointer to the end of Network Data TLV sequence.
423      *
424      */
GetTlvsEnd(void) const425     const NetworkDataTlv *GetTlvsEnd(void) const { return reinterpret_cast<const NetworkDataTlv *>(mTlvs + mLength); }
426 
427     /**
428      * This method returns a pointer to a Prefix TLV.
429      *
430      * @param[in]  aPrefix        A pointer to an IPv6 prefix.
431      * @param[in]  aPrefixLength  The prefix length pointed to by @p aPrefix (in bits).
432      *
433      * @returns A pointer to the Prefix TLV if one is found or `nullptr` if no matching Prefix TLV exists.
434      *
435      */
436     const PrefixTlv *FindPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) const;
437 
438     /**
439      * This method returns a pointer to a Prefix TLV.
440      *
441      * @param[in]  aPrefix        An IPv6 prefix.
442      *
443      * @returns A pointer to the Prefix TLV if one is found or `nullptr` if no matching Prefix TLV exists.
444      *
445      */
FindPrefix(const Ip6::Prefix & aPrefix) const446     const PrefixTlv *FindPrefix(const Ip6::Prefix &aPrefix) const
447     {
448         return FindPrefix(aPrefix.GetBytes(), aPrefix.GetLength());
449     }
450 
451     /**
452      * This method returns a pointer to a matching Service TLV.
453      *
454      * @param[in]  aEnterpriseNumber  Enterprise Number.
455      * @param[in]  aServiceData       A Service Data.
456      * @param[in]  aServiceMatchMode  The Service Data match mode.
457      *
458      * @returns A pointer to the Service TLV if one is found or `nullptr` if no matching Service TLV exists.
459      *
460      */
461     const ServiceTlv *FindService(uint32_t           aEnterpriseNumber,
462                                   const ServiceData &aServiceData,
463                                   ServiceMatchMode   aServiceMatchMode) const;
464 
465     /**
466      * This method returns the next pointer to a matching Service TLV.
467      *
468      * This method can be used to iterate over all Service TLVs that start with a given Service Data.
469      *
470      * @param[in]  aPrevServiceTlv    Set to `nullptr` to start from the beginning of the TLVs (finding the first
471      *                                matching Service TLV), or a pointer to the previous Service TLV returned from
472      *                                this method to iterate to the next matching Service TLV.
473      * @param[in]  aEnterpriseNumber  Enterprise Number.
474      * @param[in]  aServiceData       A Service Data to match with Service TLVs.
475      * @param[in]  aServiceMatchMode  The Service Data match mode.
476      *
477      * @returns A pointer to the next matching Service TLV if one is found or `nullptr` if it cannot be found.
478      *
479      */
480     const ServiceTlv *FindNextService(const ServiceTlv  *aPrevServiceTlv,
481                                       uint32_t           aEnterpriseNumber,
482                                       const ServiceData &aServiceData,
483                                       ServiceMatchMode   aServiceMatchMode) const;
484 
485     /**
486      * This method returns the next pointer to a matching Thread Service TLV (with Thread Enterprise number).
487      *
488      * This method can be used to iterate over all Thread Service TLVs that start with a given Service Data.
489      *
490      * @param[in]  aPrevServiceTlv    Set to `nullptr` to start from the beginning of the TLVs (finding the first
491      *                                matching Service TLV), or a pointer to the previous Service TLV returned from
492      *                                this method to iterate to the next matching Service TLV.
493      * @param[in]  aServiceData       A Service Data to match with Service TLVs.
494      * @param[in]  aServiceMatchMode  The Service Data match mode.
495      *
496      * @returns A pointer to the next matching Thread Service TLV if one is found or `nullptr` if it cannot be found.
497      *
498      */
499     const ServiceTlv *FindNextThreadService(const ServiceTlv  *aPrevServiceTlv,
500                                             const ServiceData &aServiceData,
501                                             ServiceMatchMode   aServiceMatchMode) const;
502 
503 private:
504     class NetworkDataIterator
505     {
506     public:
NetworkDataIterator(Iterator & aIterator)507         explicit NetworkDataIterator(Iterator &aIterator)
508             : mIteratorBuffer(reinterpret_cast<uint8_t *>(&aIterator))
509         {
510         }
511 
GetTlv(const uint8_t * aTlvs) const512         const NetworkDataTlv *GetTlv(const uint8_t *aTlvs) const
513         {
514             return reinterpret_cast<const NetworkDataTlv *>(aTlvs + GetTlvOffset());
515         }
516 
AdvanceTlv(const uint8_t * aTlvs)517         void AdvanceTlv(const uint8_t *aTlvs)
518         {
519             SaveTlvOffset(GetTlv(aTlvs)->GetNext(), aTlvs);
520             SetSubTlvOffset(0);
521             SetEntryIndex(0);
522         }
523 
GetSubTlv(const NetworkDataTlv * aSubTlvs) const524         const NetworkDataTlv *GetSubTlv(const NetworkDataTlv *aSubTlvs) const
525         {
526             return reinterpret_cast<const NetworkDataTlv *>(reinterpret_cast<const uint8_t *>(aSubTlvs) +
527                                                             GetSubTlvOffset());
528         }
529 
AdvanceSubTlv(const NetworkDataTlv * aSubTlvs)530         void AdvanceSubTlv(const NetworkDataTlv *aSubTlvs)
531         {
532             SaveSubTlvOffset(GetSubTlv(aSubTlvs)->GetNext(), aSubTlvs);
533             SetEntryIndex(0);
534         }
535 
GetAndAdvanceIndex(void)536         uint8_t GetAndAdvanceIndex(void) { return mIteratorBuffer[kEntryPosition]++; }
537 
IsNewEntry(void) const538         bool IsNewEntry(void) const { return GetEntryIndex() == 0; }
MarkEntryAsNotNew(void)539         void MarkEntryAsNotNew(void) { SetEntryIndex(1); }
540 
541     private:
542         static constexpr uint8_t kTlvPosition    = 0;
543         static constexpr uint8_t kSubTlvPosition = 1;
544         static constexpr uint8_t kEntryPosition  = 2;
545 
GetTlvOffset(void) const546         uint8_t GetTlvOffset(void) const { return mIteratorBuffer[kTlvPosition]; }
GetSubTlvOffset(void) const547         uint8_t GetSubTlvOffset(void) const { return mIteratorBuffer[kSubTlvPosition]; }
SetSubTlvOffset(uint8_t aOffset)548         void    SetSubTlvOffset(uint8_t aOffset) { mIteratorBuffer[kSubTlvPosition] = aOffset; }
SetTlvOffset(uint8_t aOffset)549         void    SetTlvOffset(uint8_t aOffset) { mIteratorBuffer[kTlvPosition] = aOffset; }
GetEntryIndex(void) const550         uint8_t GetEntryIndex(void) const { return mIteratorBuffer[kEntryPosition]; }
SetEntryIndex(uint8_t aIndex)551         void    SetEntryIndex(uint8_t aIndex) { mIteratorBuffer[kEntryPosition] = aIndex; }
552 
SaveTlvOffset(const NetworkDataTlv * aTlv,const uint8_t * aTlvs)553         void SaveTlvOffset(const NetworkDataTlv *aTlv, const uint8_t *aTlvs)
554         {
555             SetTlvOffset(static_cast<uint8_t>(reinterpret_cast<const uint8_t *>(aTlv) - aTlvs));
556         }
557 
SaveSubTlvOffset(const NetworkDataTlv * aSubTlv,const NetworkDataTlv * aSubTlvs)558         void SaveSubTlvOffset(const NetworkDataTlv *aSubTlv, const NetworkDataTlv *aSubTlvs)
559         {
560             SetSubTlvOffset(static_cast<uint8_t>(reinterpret_cast<const uint8_t *>(aSubTlv) -
561                                                  reinterpret_cast<const uint8_t *>(aSubTlvs)));
562         }
563 
564         uint8_t *mIteratorBuffer;
565     };
566 
567     struct Config
568     {
569         OnMeshPrefixConfig  *mOnMeshPrefix;
570         ExternalRouteConfig *mExternalRoute;
571         ServiceConfig       *mService;
572         LowpanContextInfo   *mLowpanContext;
573     };
574 
575     Error Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aConfig) const;
576 
577     static bool MatchService(const ServiceTlv  &aServiceTlv,
578                              uint32_t           aEnterpriseNumber,
579                              const ServiceData &aServiceData,
580                              ServiceMatchMode   aServiceMatchMode);
581 
582     const uint8_t *mTlvs;
583     uint8_t        mLength;
584 };
585 
586 /**
587  * This class represents mutable Network Data.
588  *
589  */
590 class MutableNetworkData : public NetworkData
591 {
592     friend class NetworkData;
593     friend class Service::Manager;
594     friend class Publisher;
595 
596 public:
597     /**
598      * This constructor initializes the `MutableNetworkData`
599      *
600      * @param[in] aInstance     A reference to the OpenThread instance.
601      * @param[in] aTlvs         A pointer to the buffer to store the TLVs.
602      * @param[in] aLength       The current length of the Network Data.
603      * @param[in] aSize         Size of the buffer @p aTlvs (maximum length).
604      *
605      */
MutableNetworkData(Instance & aInstance,uint8_t * aTlvs,uint8_t aLength,uint8_t aSize)606     MutableNetworkData(Instance &aInstance, uint8_t *aTlvs, uint8_t aLength, uint8_t aSize)
607         : NetworkData(aInstance, aTlvs, aLength)
608         , mSize(aSize)
609     {
610     }
611 
612     using NetworkData::GetBytes;
613     using NetworkData::GetLength;
614 
615     /**
616      * This method returns the size of the buffer to store the mutable Network Data.
617      *
618      * @returns The size of the buffer.
619      *
620      */
GetSize(void) const621     uint8_t GetSize(void) const { return mSize; }
622 
623     /**
624      * This method returns a pointer to start of the TLVs in `NetworkData`.
625      *
626      * @returns A pointer to start of the TLVs.
627      *
628      */
GetBytes(void)629     uint8_t *GetBytes(void) { return AsNonConst(AsConst(this)->GetBytes()); }
630 
631     /**
632      * This method clears the network data.
633      *
634      */
Clear(void)635     void Clear(void) { mLength = 0; }
636 
637 protected:
638     /**
639      * This method sets the Network Data length.
640      *
641      * @param[in] aLength   The length.
642      *
643      */
SetLength(uint8_t aLength)644     void SetLength(uint8_t aLength) { mLength = aLength; }
645 
646     using NetworkData::GetTlvsStart;
647 
648     /**
649      * This method returns a pointer to the start of Network Data TLV sequence.
650      *
651      * @returns A pointer to the start of Network Data TLV sequence.
652      *
653      */
GetTlvsStart(void)654     NetworkDataTlv *GetTlvsStart(void) { return AsNonConst(AsConst(this)->GetTlvsStart()); }
655 
656     using NetworkData::GetTlvsEnd;
657 
658     /**
659      * This method returns a pointer to the end of Network Data TLV sequence.
660      *
661      * @returns A pointer to the end of Network Data TLV sequence.
662      *
663      */
GetTlvsEnd(void)664     NetworkDataTlv *GetTlvsEnd(void) { return AsNonConst(AsConst(this)->GetTlvsEnd()); }
665 
666     using NetworkData::FindPrefix;
667 
668     /**
669      * This method returns a pointer to a Prefix TLV.
670      *
671      * @param[in]  aPrefix        A pointer to an IPv6 prefix.
672      * @param[in]  aPrefixLength  The prefix length pointed to by @p aPrefix (in bits).
673      *
674      * @returns A pointer to the Prefix TLV if one is found or `nullptr` if no matching Prefix TLV exists.
675      *
676      */
FindPrefix(const uint8_t * aPrefix,uint8_t aPrefixLength)677     PrefixTlv *FindPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength)
678     {
679         return AsNonConst(AsConst(this)->FindPrefix(aPrefix, aPrefixLength));
680     }
681 
682     /**
683      * This method returns a pointer to a Prefix TLV.
684      *
685      * @param[in]  aPrefix        An IPv6 prefix.
686      *
687      * @returns A pointer to the Prefix TLV if one is found or `nullptr` if no matching Prefix TLV exists.
688      *
689      */
FindPrefix(const Ip6::Prefix & aPrefix)690     PrefixTlv *FindPrefix(const Ip6::Prefix &aPrefix) { return FindPrefix(aPrefix.GetBytes(), aPrefix.GetLength()); }
691 
692     using NetworkData::FindService;
693 
694     /**
695      * This method returns a pointer to a matching Service TLV.
696      *
697      * @param[in]  aEnterpriseNumber  Enterprise Number.
698      * @param[in]  aServiceData       A Service Data.
699      * @param[in]  aServiceMatchMode  The Service Data match mode.
700      *
701      * @returns A pointer to the Service TLV if one is found or `nullptr` if no matching Service TLV exists.
702      *
703      */
FindService(uint32_t aEnterpriseNumber,const ServiceData & aServiceData,ServiceMatchMode aServiceMatchMode)704     ServiceTlv *FindService(uint32_t           aEnterpriseNumber,
705                             const ServiceData &aServiceData,
706                             ServiceMatchMode   aServiceMatchMode)
707     {
708         return AsNonConst(AsConst(this)->FindService(aEnterpriseNumber, aServiceData, aServiceMatchMode));
709     }
710 
711     /**
712      * This method indicates whether there is space in Network Data to insert/append new info and grow it by a given
713      * number of bytes.
714      *
715      * @param[in]  aSize  The number of bytes to grow the Network Data.
716      *
717      * @retval TRUE   There is space to grow Network Data by @p aSize bytes.
718      * @retval FALSE  There is no space left to grow Network Data by @p aSize bytes.
719      *
720      */
CanInsert(uint16_t aSize) const721     bool CanInsert(uint16_t aSize) const { return (mLength + aSize <= mSize); }
722 
723     /**
724      * This method grows the Network Data to append a TLV with a requested size.
725      *
726      * On success, the returned TLV is not initialized (i.e., the TLV Length field is not set) but the requested
727      * size for it (@p aTlvSize number of bytes) is reserved in the Network Data.
728      *
729      * @param[in]  aTlvSize  The size of TLV (total number of bytes including Type, Length, and Value fields)
730      *
731      * @returns A pointer to the TLV if there is space to grow Network Data, or `nullptr` if no space to grow the
732      *          Network Data with requested @p aTlvSize number of bytes.
733      *
734      */
735     NetworkDataTlv *AppendTlv(uint16_t aTlvSize);
736 
737     /**
738      * This method inserts bytes into the Network Data.
739      *
740      * @param[in]  aStart   A pointer to the beginning of the insertion.
741      * @param[in]  aLength  The number of bytes to insert.
742      *
743      */
744     void Insert(void *aStart, uint8_t aLength);
745 
746     /**
747      * This method removes bytes from the Network Data.
748      *
749      * @param[in]  aRemoveStart   A pointer to the beginning of the removal.
750      * @param[in]  aRemoveLength  The number of bytes to remove.
751      *
752      */
753     void Remove(void *aRemoveStart, uint8_t aRemoveLength);
754 
755     /**
756      * This method removes a TLV from the Network Data.
757      *
758      * @param[in]  aTlv   The TLV to remove.
759      *
760      */
761     void RemoveTlv(NetworkDataTlv *aTlv);
762 
763     /**
764      * This method strips non-stable data from the Thread Network Data.
765      *
766      */
767     void RemoveTemporaryData(void);
768 
769 private:
770     void RemoveTemporaryDataIn(PrefixTlv &aPrefix);
771     void RemoveTemporaryDataIn(ServiceTlv &aService);
772 
773     uint8_t mSize;
774 };
775 
776 } // namespace NetworkData
777 
778 /**
779  * @}
780  */
781 
782 } // namespace ot
783 
784 #endif // NETWORK_DATA_HPP_
785