Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #pragma once
19 :
20 : #include <stdint.h>
21 : #include <stdio.h>
22 : #include <stdlib.h>
23 :
24 : #include <lib/core/CHIPCore.h>
25 : #include <lib/support/Span.h>
26 :
27 : namespace chip {
28 : namespace Thread {
29 :
30 : class ThreadTLV;
31 :
32 : inline constexpr size_t kChannel_NotSpecified = UINT8_MAX;
33 : inline constexpr size_t kPANId_NotSpecified = UINT16_MAX;
34 :
35 : inline constexpr size_t kSizeOperationalDataset = 254;
36 :
37 : inline constexpr size_t kSizeNetworkName = 16;
38 : inline constexpr size_t kSizeExtendedPanId = 8;
39 : inline constexpr size_t kSizeMasterKey = 16;
40 : inline constexpr size_t kSizeMeshLocalPrefix = 8;
41 : inline constexpr size_t kSizePSKc = 16;
42 :
43 : /**
44 : * This class provides methods to manipulate Thread operational dataset.
45 : *
46 : */
47 : class OperationalDataset
48 : {
49 : public:
50 : /**
51 : * This method initializes the dataset with the given dataset.
52 : *
53 : * @param[in] aData Thread Operational dataset in octects.
54 : *
55 : * @retval CHIP_NO_ERROR Successfully initialized the dataset.
56 : * @retval CHIP_ERROR_INVALID_ARGUMENT The dataset length @p aLength is too long or @p data is corrupted.
57 : */
58 : CHIP_ERROR Init(ByteSpan aData);
59 :
60 : /**
61 : * This method retrieves Thread active timestamp from the dataset.
62 : *
63 : * @param[out] aActiveTimestamp A reference to receive the active timestamp.
64 : *
65 : * @retval CHIP_NO_ERROR Successfully retrieved the active timestamp.
66 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread active timestamp is not present in the dataset.
67 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
68 : */
69 : CHIP_ERROR GetActiveTimestamp(uint64_t & aActiveTimestamp) const;
70 :
71 : /**
72 : * This method sets Thread active timestamp to the dataset.
73 : *
74 : * @param[in] aActiveTimestamp The Thread active timestamp.
75 : *
76 : * @retval CHIP_NO_ERROR Successfully set the active timestamp.
77 : * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread active timestamp.
78 : */
79 : CHIP_ERROR SetActiveTimestamp(uint64_t aActiveTimestamp);
80 :
81 : /**
82 : * This method retrieves Thread channel from the dataset.
83 : *
84 : * @param[out] aChannel A reference to receive the channel.
85 : *
86 : * @retval CHIP_NO_ERROR Successfully retrieved the channel.
87 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread channel is not present in the dataset.
88 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
89 : */
90 : CHIP_ERROR GetChannel(uint16_t & aChannel) const;
91 :
92 : /**
93 : * This method sets Thread channel to the dataset.
94 : *
95 : * @param[in] aChannel The Thread channel.
96 : *
97 : * @retval CHIP_NO_ERROR Successfully set the channel.
98 : * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread channel.
99 : */
100 : CHIP_ERROR SetChannel(uint16_t aChannel);
101 :
102 : /**
103 : * This method retrieves Thread extended PAN ID from the dataset.
104 : *
105 : * @param[out] aExtendedPanId A reference to receive the extended PAN ID.
106 : *
107 : * @retval CHIP_NO_ERROR Successfully retrieved the extended PAN ID.
108 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread extended PAN ID is not present in the dataset.
109 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
110 : */
111 : CHIP_ERROR GetExtendedPanId(uint8_t (&aExtendedPanId)[kSizeExtendedPanId]) const;
112 :
113 : /**
114 : * This method retrieves the Thread extended PAN ID from the dataset, interpreted as a big endian number.
115 : * @retval CHIP_NO_ERROR Successfully retrieved the extended PAN ID.
116 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread extended PAN ID is not present in the dataset.
117 : */
118 : CHIP_ERROR GetExtendedPanId(uint64_t & extendedPanId) const;
119 :
120 : /**
121 : * This method returns a const ByteSpan to the extended PAN ID in the dataset.
122 : * This can be used to pass the extended PAN ID to a cluster command without the use of external memory.
123 : *
124 : * Note: The returned span points into storage managed by this class,
125 : * and must not be dereferenced beyond the lifetime of this object.
126 : *
127 : * @param[out] span A reference to receive the location of the extended PAN ID.
128 : *
129 : * @retval CHIP_NO_ERROR Successfully retrieved the extended PAN ID.
130 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread extended PAN ID is not present in the dataset.
131 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
132 : */
133 : CHIP_ERROR GetExtendedPanIdAsByteSpan(ByteSpan & span) const;
134 :
135 : /**
136 : * This method sets Thread extended PAN ID to the dataset.
137 : *
138 : * @param[in] aExtendedPanId The Thread extended PAN ID.
139 : *
140 : * @retval CHIP_NO_ERROR Successfully set the extended PAN ID.
141 : * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread extended PAN ID.
142 : */
143 : CHIP_ERROR SetExtendedPanId(const uint8_t (&aExtendedPanId)[kSizeExtendedPanId]);
144 :
145 : /**
146 : * This method retrieves Thread master key from the dataset.
147 : *
148 : * @param[out] aMasterKey A reference to receive the master key.
149 : *
150 : * @retval CHIP_NO_ERROR Successfully retrieved the master key.
151 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread master key is not present in the dataset.
152 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
153 : */
154 : CHIP_ERROR GetMasterKey(uint8_t (&aMasterKey)[kSizeMasterKey]) const;
155 :
156 : /**
157 : * This method sets Thread master key to the dataset.
158 : *
159 : * @param[in] aMasterKey The Thread master key.
160 : *
161 : * @retval CHIP_NO_ERROR Successfully set the master key.
162 : * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread master key.
163 : */
164 : CHIP_ERROR SetMasterKey(const uint8_t (&aMasterKey)[kSizeMasterKey]);
165 :
166 : /**
167 : * This method unsets Thread master key to the dataset.
168 : */
169 : void UnsetMasterKey(void);
170 :
171 : /**
172 : * This method retrieves Thread mesh local prefix from the dataset.
173 : *
174 : * @param[out] aMeshLocalPrefix A reference to receive the mesh local prefix.
175 : *
176 : * @retval CHIP_NO_ERROR Successfully retrieved the mesh local prefix.
177 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread mesh local prefix is not present in the dataset.
178 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
179 : */
180 : CHIP_ERROR GetMeshLocalPrefix(uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]) const;
181 :
182 : /**
183 : * This method sets Thread mesh local prefix to the dataset.
184 : *
185 : * @param[in] aMeshLocalPrefix The Thread mesh local prefix.
186 : *
187 : * @retval CHIP_NO_ERROR Successfully set the Thread mesh local prefix.
188 : * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread mesh local prefix.
189 : */
190 : CHIP_ERROR SetMeshLocalPrefix(const uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]);
191 :
192 : /**
193 : * This method retrieves Thread network name from the dataset.
194 : *
195 : * @param[out] aNetworkName A reference to receive the Thread network name.
196 : *
197 : * @retval CHIP_NO_ERROR Successfully retrieved the network name.
198 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread network name is not present in the dataset.
199 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
200 : */
201 : CHIP_ERROR GetNetworkName(char (&aNetworkName)[kSizeNetworkName + 1]) const;
202 :
203 : /**
204 : * This method sets Thread network name to the dataset.
205 : *
206 : * @param[in] aNetworkName The Thread network name.
207 : *
208 : * @retval CHIP_NO_ERROR Successfully set the network name.
209 : * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread network name.
210 : */
211 : CHIP_ERROR SetNetworkName(const char * aNetworkName);
212 :
213 : /**
214 : * This method retrieves Thread PAN ID from the dataset.
215 : *
216 : * @param[out] aPanId A reference to receive the PAN ID.
217 : *
218 : * @retval CHIP_NO_ERROR Successfully retrieved the PAN ID.
219 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread PAN ID is not present in the dataset.
220 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
221 : */
222 : CHIP_ERROR GetPanId(uint16_t & aPanId) const;
223 :
224 : /**
225 : * This method sets Thread PAN ID to the dataset.
226 : *
227 : * @param[in] aPanId The Thread PAN ID.
228 : *
229 : * @retval CHIP_NO_ERROR Successfully set the PAN ID.
230 : * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread PAN ID.
231 : */
232 : CHIP_ERROR SetPanId(uint16_t aPanId);
233 :
234 : /**
235 : * This method retrieves Thread PSKc from the dataset.
236 : *
237 : * @param[out] aPSKc A reference to receive the PSKc.
238 : *
239 : * @retval CHIP_NO_ERROR Successfully retrieved the PSKc.
240 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread PSKc is not present in the dataset.
241 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
242 : */
243 : CHIP_ERROR GetPSKc(uint8_t (&aPSKc)[kSizePSKc]) const;
244 :
245 : /**
246 : * This method sets Thread PSKc to the dataset.
247 : *
248 : * @param[in] aPSKc The Thread PSKc.
249 : *
250 : * @retval CHIP_NO_ERROR Successfully set the PSKc.
251 : * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread PSKc.
252 : */
253 : CHIP_ERROR SetPSKc(const uint8_t (&aPSKc)[kSizePSKc]);
254 :
255 : /**
256 : * This method unsets Thread PSKc to the dataset.
257 : */
258 : void UnsetPSKc(void);
259 :
260 : /**
261 : * Returns ByteSpan pointing to the channel mask within the dataset.
262 : *
263 : * Note: The returned span points into storage managed by this class,
264 : * and must not be dereferenced beyond the lifetime of this object.
265 : *
266 : * @retval CHIP_NO_ERROR on success.
267 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND if the channel mask is not present in the dataset.
268 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT if the TLV element is invalid.
269 : */
270 : CHIP_ERROR GetChannelMask(ByteSpan & aChannelMask) const;
271 :
272 : /**
273 : * This method sets the channel mask within the dataset.
274 : *
275 : * @retval CHIP_NO_ERROR on success.
276 : * @retval CHIP_ERROR_NO_MEMORY if there is insufficient space within the dataset.
277 : */
278 : CHIP_ERROR SetChannelMask(ByteSpan aChannelMask);
279 :
280 : /**
281 : * Retrieves the security policy from the dataset.
282 : *
283 : * @retval CHIP_NO_ERROR on success.
284 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND if no security policy is present in the dataset.
285 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT if the TLV element is invalid.
286 : */
287 : CHIP_ERROR GetSecurityPolicy(uint32_t & aSecurityPolicy) const;
288 :
289 : /**
290 : * This method sets the security policy within the dataset.
291 : *
292 : * @retval CHIP_NO_ERROR on success.
293 : * @retval CHIP_ERROR_NO_MEMORY if there is insufficient space within the dataset.
294 : */
295 : CHIP_ERROR SetSecurityPolicy(uint32_t aSecurityPolicy);
296 :
297 : /**
298 : * Retrieves the delay timer from the dataset.
299 : *
300 : * @retval CHIP_NO_ERROR on success.
301 : * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND if no security policy is present in the dataset.
302 : * @retval CHIP_ERROR_INVALID_TLV_ELEMENT if the TLV element is invalid.
303 : */
304 : CHIP_ERROR GetDelayTimer(uint32_t & aDelayMillis) const;
305 :
306 : /**
307 : * This method sets the delay timer within the dataset.
308 : *
309 : * @retval CHIP_NO_ERROR on success.
310 : * @retval CHIP_ERROR_NO_MEMORY if there is insufficient space within the dataset.
311 : */
312 : CHIP_ERROR SetDelayTimer(uint32_t aDelayMillis);
313 :
314 : /**
315 : * This method clears all data stored in the dataset.
316 : */
317 : void Clear(void) { mLength = 0; }
318 :
319 : /**
320 : * This method checks if the dataset is ready for creating Thread network.
321 : */
322 : bool IsCommissioned(void) const;
323 :
324 : /**
325 : * This method checks if the dataset is empty.
326 : */
327 : bool IsEmpty() const { return mLength == 0; }
328 :
329 : /**
330 : * This method checks whether @p aData is formatted as ThreadTLVs.
331 : *
332 : * @note This method doesn't verify ThreadTLV values are valid.
333 : */
334 : static bool IsValid(ByteSpan aData);
335 :
336 : ByteSpan AsByteSpan(void) const { return ByteSpan(mData, mLength); }
337 :
338 : private:
339 21 : ThreadTLV * Locate(uint8_t aType)
340 : {
341 21 : return const_cast<ThreadTLV *>(const_cast<const OperationalDataset *>(this)->Locate(aType));
342 : }
343 : const ThreadTLV * Locate(uint8_t aType) const;
344 60 : const ThreadTLV & Begin(void) const { return *reinterpret_cast<const ThreadTLV *>(&mData[0]); };
345 : ThreadTLV & Begin(void) { return const_cast<ThreadTLV &>(const_cast<const OperationalDataset *>(this)->Begin()); }
346 98 : const ThreadTLV & End(void) const { return *reinterpret_cast<const ThreadTLV *>(&mData[mLength]); };
347 38 : ThreadTLV & End(void) { return const_cast<ThreadTLV &>(const_cast<const OperationalDataset *>(this)->End()); }
348 : void Remove(uint8_t aType);
349 : void Remove(ThreadTLV & aTlv);
350 : ThreadTLV * MakeRoom(uint8_t aType, size_t aSize);
351 0 : bool Has(uint8_t aType) const { return Locate(aType) != nullptr; }
352 :
353 : uint8_t mData[kSizeOperationalDataset];
354 : uint8_t mLength = 0;
355 : };
356 :
357 : } // namespace Thread
358 : } // namespace chip
|