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  * 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  * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * Finds and returns Domain ID associated with a given prefix in the Thread Network data.
329      *
330      * @param[in]  aPrefix     The prefix to search for.
331      * @param[out] aDomainId   A reference to return the Domain ID.
332      *
333      * @retval kErrorNone      Successfully found @p aPrefix in the Network Data and updated @p aDomainId.
334      * @retval kErrorNotFound  Could not find @p aPrefix in the Network Data.
335      *
336      */
337     Error FindDomainIdFor(const Ip6::Prefix &aPrefix, uint8_t &aDomainId) const;
338 
339     /**
340      * Finds border routers and servers in the Network Data matching specified filters, returning their RLOC16s.
341      *
342      * @p aBrFilter can be used to filter the type of BRs. It can be set to `kAnyBrOrServer` to include all BRs and
343      * servers. `kBrProvidingExternalIpConn` restricts it to BRs providing external IP connectivity where at least one
344      * the below conditions hold:
345      *
346      * - It has added at least one external route entry.
347      * - It has added at least one prefix entry with default-route and on-mesh flags set.
348      * - It has added at least one domain prefix (domain and on-mesh flags set).
349      *
350      * Should be used when the RLOC16s are present in the Network Data (when the Network Data contains the
351      * full set and not the stable subset).
352      *
353      * @param[in]  aBrFilter    Indicates BR filter.
354      * @param[in]  aRoleFilter  Indicates role filter (any role, router role only, or child only).
355      * @param[out] aRlocs       Array to output the list of RLOC16s.
356      *
357      */
358     void FindRlocs(BorderRouterFilter aBrFilter, RoleFilter aRoleFilter, Rlocs &aRlocs) const;
359 
360     /**
361      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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      * Returns the next pointer to a matching Service TLV.
467      *
468      * 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      * Returns the next pointer to a matching Thread Service TLV (with Thread Enterprise number).
487      *
488      * 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     static void AddRloc16ToRlocs(uint16_t aRloc16, Rlocs &aRlocs, RoleFilter aRoleFilter);
583 
584     const uint8_t *mTlvs;
585     uint8_t        mLength;
586 };
587 
588 /**
589  * Represents mutable Network Data.
590  *
591  */
592 class MutableNetworkData : public NetworkData
593 {
594     friend class NetworkData;
595     friend class Service::Manager;
596     friend class Publisher;
597 
598 public:
599     /**
600      * Initializes the `MutableNetworkData`
601      *
602      * @param[in] aInstance     A reference to the OpenThread instance.
603      * @param[in] aTlvs         A pointer to the buffer to store the TLVs.
604      * @param[in] aLength       The current length of the Network Data.
605      * @param[in] aSize         Size of the buffer @p aTlvs (maximum length).
606      *
607      */
MutableNetworkData(Instance & aInstance,uint8_t * aTlvs,uint8_t aLength,uint8_t aSize)608     MutableNetworkData(Instance &aInstance, uint8_t *aTlvs, uint8_t aLength, uint8_t aSize)
609         : NetworkData(aInstance, aTlvs, aLength)
610         , mSize(aSize)
611     {
612     }
613 
614     using NetworkData::GetBytes;
615     using NetworkData::GetLength;
616 
617     /**
618      * Returns the size of the buffer to store the mutable Network Data.
619      *
620      * @returns The size of the buffer.
621      *
622      */
GetSize(void) const623     uint8_t GetSize(void) const { return mSize; }
624 
625     /**
626      * Returns a pointer to start of the TLVs in `NetworkData`.
627      *
628      * @returns A pointer to start of the TLVs.
629      *
630      */
GetBytes(void)631     uint8_t *GetBytes(void) { return AsNonConst(AsConst(this)->GetBytes()); }
632 
633     /**
634      * Clears the network data.
635      *
636      */
Clear(void)637     void Clear(void) { mLength = 0; }
638 
639 protected:
640     /**
641      * Sets the Network Data length.
642      *
643      * @param[in] aLength   The length.
644      *
645      */
SetLength(uint8_t aLength)646     void SetLength(uint8_t aLength) { mLength = aLength; }
647 
648     using NetworkData::GetTlvsStart;
649 
650     /**
651      * Returns a pointer to the start of Network Data TLV sequence.
652      *
653      * @returns A pointer to the start of Network Data TLV sequence.
654      *
655      */
GetTlvsStart(void)656     NetworkDataTlv *GetTlvsStart(void) { return AsNonConst(AsConst(this)->GetTlvsStart()); }
657 
658     using NetworkData::GetTlvsEnd;
659 
660     /**
661      * Returns a pointer to the end of Network Data TLV sequence.
662      *
663      * @returns A pointer to the end of Network Data TLV sequence.
664      *
665      */
GetTlvsEnd(void)666     NetworkDataTlv *GetTlvsEnd(void) { return AsNonConst(AsConst(this)->GetTlvsEnd()); }
667 
668     using NetworkData::FindPrefix;
669 
670     /**
671      * Returns a pointer to a Prefix TLV.
672      *
673      * @param[in]  aPrefix        A pointer to an IPv6 prefix.
674      * @param[in]  aPrefixLength  The prefix length pointed to by @p aPrefix (in bits).
675      *
676      * @returns A pointer to the Prefix TLV if one is found or `nullptr` if no matching Prefix TLV exists.
677      *
678      */
FindPrefix(const uint8_t * aPrefix,uint8_t aPrefixLength)679     PrefixTlv *FindPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength)
680     {
681         return AsNonConst(AsConst(this)->FindPrefix(aPrefix, aPrefixLength));
682     }
683 
684     /**
685      * Returns a pointer to a Prefix TLV.
686      *
687      * @param[in]  aPrefix        An IPv6 prefix.
688      *
689      * @returns A pointer to the Prefix TLV if one is found or `nullptr` if no matching Prefix TLV exists.
690      *
691      */
FindPrefix(const Ip6::Prefix & aPrefix)692     PrefixTlv *FindPrefix(const Ip6::Prefix &aPrefix) { return FindPrefix(aPrefix.GetBytes(), aPrefix.GetLength()); }
693 
694     using NetworkData::FindService;
695 
696     /**
697      * Returns a pointer to a matching Service TLV.
698      *
699      * @param[in]  aEnterpriseNumber  Enterprise Number.
700      * @param[in]  aServiceData       A Service Data.
701      * @param[in]  aServiceMatchMode  The Service Data match mode.
702      *
703      * @returns A pointer to the Service TLV if one is found or `nullptr` if no matching Service TLV exists.
704      *
705      */
FindService(uint32_t aEnterpriseNumber,const ServiceData & aServiceData,ServiceMatchMode aServiceMatchMode)706     ServiceTlv *FindService(uint32_t           aEnterpriseNumber,
707                             const ServiceData &aServiceData,
708                             ServiceMatchMode   aServiceMatchMode)
709     {
710         return AsNonConst(AsConst(this)->FindService(aEnterpriseNumber, aServiceData, aServiceMatchMode));
711     }
712 
713     /**
714      * Indicates whether there is space in Network Data to insert/append new info and grow it by a given
715      * number of bytes.
716      *
717      * @param[in]  aSize  The number of bytes to grow the Network Data.
718      *
719      * @retval TRUE   There is space to grow Network Data by @p aSize bytes.
720      * @retval FALSE  There is no space left to grow Network Data by @p aSize bytes.
721      *
722      */
CanInsert(uint16_t aSize) const723     bool CanInsert(uint16_t aSize) const { return (mLength + aSize <= mSize); }
724 
725     /**
726      * Grows the Network Data to append a TLV with a requested size.
727      *
728      * On success, the returned TLV is not initialized (i.e., the TLV Length field is not set) but the requested
729      * size for it (@p aTlvSize number of bytes) is reserved in the Network Data.
730      *
731      * @param[in]  aTlvSize  The size of TLV (total number of bytes including Type, Length, and Value fields)
732      *
733      * @returns A pointer to the TLV if there is space to grow Network Data, or `nullptr` if no space to grow the
734      *          Network Data with requested @p aTlvSize number of bytes.
735      *
736      */
737     NetworkDataTlv *AppendTlv(uint16_t aTlvSize);
738 
739     /**
740      * Inserts bytes into the Network Data.
741      *
742      * @param[in]  aStart   A pointer to the beginning of the insertion.
743      * @param[in]  aLength  The number of bytes to insert.
744      *
745      */
746     void Insert(void *aStart, uint8_t aLength);
747 
748     /**
749      * Removes bytes from the Network Data.
750      *
751      * @param[in]  aRemoveStart   A pointer to the beginning of the removal.
752      * @param[in]  aRemoveLength  The number of bytes to remove.
753      *
754      */
755     void Remove(void *aRemoveStart, uint8_t aRemoveLength);
756 
757     /**
758      * Removes a TLV from the Network Data.
759      *
760      * @param[in]  aTlv   The TLV to remove.
761      *
762      */
763     void RemoveTlv(NetworkDataTlv *aTlv);
764 
765     /**
766      * Strips non-stable data from the Thread Network Data.
767      *
768      */
769     void RemoveTemporaryData(void);
770 
771 private:
772     bool RemoveTemporaryDataIn(PrefixTlv &aPrefix);
773     bool RemoveTemporaryDataIn(ServiceTlv &aService);
774 
775     uint8_t mSize;
776 };
777 
778 } // namespace NetworkData
779 
780 /**
781  * @}
782  */
783 
784 } // namespace ot
785 
786 #endif // NETWORK_DATA_HPP_
787