1 /*
2 * Copyright (c) 2024, 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 #include <openthread/config.h>
30
31 #include "test_platform.h"
32 #include "test_util.hpp"
33
34 #include "meshcop/dataset.hpp"
35
36 namespace ot {
37 namespace MeshCoP {
38
TestDataset(void)39 void TestDataset(void)
40 {
41 static const uint8_t kTlvBytes[] = {
42 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x35, 0x06, 0x00,
43 0x04, 0x00, 0x1f, 0xff, 0xe0, 0x02, 0x08, 0x1d, 0xe5, 0xbf, 0xec, 0xd5, 0x16, 0x5b, 0x8f, 0x07, 0x08, 0xfd,
44 0xe2, 0x1f, 0x0c, 0x8a, 0x13, 0xe8, 0xe7, 0x05, 0x10, 0xea, 0xf9, 0x14, 0x9f, 0xdc, 0x73, 0x78, 0x77, 0x06,
45 0x98, 0xd5, 0x91, 0x80, 0x22, 0x19, 0x58, 0x03, 0x0f, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61,
46 0x64, 0x2d, 0x61, 0x61, 0x63, 0x33, 0x01, 0x02, 0xfa, 0xce, 0x04, 0x10, 0x2e, 0xaa, 0xe2, 0x94, 0x84, 0x38,
47 0x8e, 0x31, 0x19, 0x58, 0x1a, 0x7b, 0x5a, 0x94, 0x8c, 0x07, 0x0c, 0x04, 0x02, 0xa0, 0xf7, 0xf8,
48 };
49
50 static const otNetworkKey kNetworkKey = {
51 {0xea, 0xf9, 0x14, 0x9f, 0xdc, 0x73, 0x78, 0x77, 0x06, 0x98, 0xd5, 0x91, 0x80, 0x22, 0x19, 0x58}};
52
53 static const otNetworkKey kNewNetworkKey = {
54 {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}};
55
56 static const uint8_t kDuplicateChannels[] = {
57 0x00, 0x03, 0x00, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x00, 0x1a,
58 };
59
60 static const Tlv::Type kDatasetTlvTypes[] = {
61 Tlv::kChannel, Tlv::kPanId, Tlv::kExtendedPanId, Tlv::kNetworkName, Tlv::kPskc,
62 Tlv::kNetworkKey, Tlv::kMeshLocalPrefix, Tlv::kSecurityPolicy, Tlv::kActiveTimestamp,
63 };
64
65 Dataset dataset;
66 Dataset dataset2;
67 Dataset::Tlvs datasetTlvs;
68 Dataset::Info datasetInfo;
69 uint16_t panId;
70 NetworkKey networkKey;
71
72 SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes)));
73
74 VerifyOrQuit(dataset.GetLength() == sizeof(kTlvBytes));
75
76 SuccessOrQuit(dataset.ValidateTlvs());
77
78 for (Tlv::Type tlvType : kDatasetTlvTypes)
79 {
80 VerifyOrQuit(dataset.ContainsTlv(tlvType));
81 }
82
83 // Converting to `Dataset::Tlvs`
84
85 dataset.ConvertTo(datasetTlvs);
86 VerifyOrQuit(datasetTlvs.mLength == sizeof(kTlvBytes));
87 VerifyOrQuit(memcmp(datasetTlvs.mTlvs, kTlvBytes, sizeof(kTlvBytes)) == 0);
88
89 // Converting to `Dataset::Info`
90
91 dataset.ConvertTo(datasetInfo);
92
93 VerifyOrQuit(datasetInfo.mComponents.mIsActiveTimestampPresent);
94 VerifyOrQuit(datasetInfo.mComponents.mIsNetworkKeyPresent);
95 VerifyOrQuit(datasetInfo.mComponents.mIsNetworkNamePresent);
96 VerifyOrQuit(datasetInfo.mComponents.mIsExtendedPanIdPresent);
97 VerifyOrQuit(datasetInfo.mComponents.mIsMeshLocalPrefixPresent);
98 VerifyOrQuit(datasetInfo.mComponents.mIsPanIdPresent);
99 VerifyOrQuit(datasetInfo.mComponents.mIsChannelPresent);
100 VerifyOrQuit(datasetInfo.mComponents.mIsPskcPresent);
101 VerifyOrQuit(datasetInfo.mComponents.mIsSecurityPolicyPresent);
102 VerifyOrQuit(datasetInfo.mComponents.mIsChannelMaskPresent);
103 VerifyOrQuit(!datasetInfo.mComponents.mIsPendingTimestampPresent);
104 VerifyOrQuit(!datasetInfo.mComponents.mIsDelayPresent);
105
106 VerifyOrQuit(datasetInfo.mPanId == 0xface);
107 VerifyOrQuit(AsCoreType(&datasetInfo.mNetworkKey) == AsCoreType(&kNetworkKey));
108
109 // Finding, reading TLVs
110
111 VerifyOrQuit(dataset.Contains<PanIdTlv>());
112 VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr);
113 SuccessOrQuit(dataset.Read<PanIdTlv>(panId));
114 VerifyOrQuit(panId == 0xface);
115
116 VerifyOrQuit(dataset.Contains<NetworkKeyTlv>());
117 VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr);
118 SuccessOrQuit(dataset.Read<NetworkKeyTlv>(networkKey));
119 VerifyOrQuit(networkKey == AsCoreType(&kNetworkKey));
120
121 // Change PAN ID TLV
122
123 SuccessOrQuit(dataset.Write<PanIdTlv>(0xcafe));
124
125 SuccessOrQuit(dataset.ValidateTlvs());
126
127 VerifyOrQuit(dataset.Contains<PanIdTlv>());
128 VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr);
129 SuccessOrQuit(dataset.Read<PanIdTlv>(panId));
130 VerifyOrQuit(panId == 0xcafe);
131
132 for (Tlv::Type tlvType : kDatasetTlvTypes)
133 {
134 VerifyOrQuit(dataset.ContainsTlv(tlvType));
135 }
136
137 // Change Network Key TLV
138
139 SuccessOrQuit(dataset.Write<NetworkKeyTlv>(AsCoreType(&kNewNetworkKey)));
140 VerifyOrQuit(dataset.Contains<NetworkKeyTlv>());
141 VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr);
142 SuccessOrQuit(dataset.Read<NetworkKeyTlv>(networkKey));
143 VerifyOrQuit(networkKey == AsCoreType(&kNewNetworkKey));
144
145 for (Tlv::Type tlvType : kDatasetTlvTypes)
146 {
147 VerifyOrQuit(dataset.ContainsTlv(tlvType));
148 }
149
150 // Remove PAN ID TLV
151
152 dataset.RemoveTlv(Tlv::kPanId);
153 VerifyOrQuit(!dataset.Contains<PanIdTlv>());
154 VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) == nullptr);
155 VerifyOrQuit(dataset.Read<PanIdTlv>(panId) == kErrorNotFound);
156
157 SuccessOrQuit(dataset.ValidateTlvs());
158
159 // Invalid datasets
160
161 SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes) - 1));
162 VerifyOrQuit(dataset.ValidateTlvs() == kErrorParse);
163
164 SuccessOrQuit(dataset.SetFrom(kDuplicateChannels, sizeof(kDuplicateChannels)));
165 VerifyOrQuit(dataset.ValidateTlvs() == kErrorParse);
166
167 SuccessOrQuit(dataset.SetFrom(kDuplicateChannels, sizeof(kDuplicateChannels) / 2));
168 SuccessOrQuit(dataset.ValidateTlvs());
169
170 // Combining/Merging TLVs from two Datasets.
171
172 SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes)));
173
174 datasetInfo.Clear();
175 datasetInfo.mComponents.mIsPanIdPresent = true;
176 datasetInfo.mComponents.mIsNetworkKeyPresent = true;
177 datasetInfo.mPanId = 0xcafe;
178 datasetInfo.mNetworkKey = kNewNetworkKey;
179
180 dataset2.SetFrom(datasetInfo);
181 SuccessOrQuit(dataset2.ValidateTlvs());
182
183 SuccessOrQuit(dataset.WriteTlvsFrom(dataset2));
184
185 SuccessOrQuit(dataset.ValidateTlvs());
186
187 VerifyOrQuit(dataset.Contains<PanIdTlv>());
188 VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr);
189 SuccessOrQuit(dataset.Read<PanIdTlv>(panId));
190 VerifyOrQuit(panId == 0xcafe);
191
192 VerifyOrQuit(dataset.Contains<NetworkKeyTlv>());
193 VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr);
194 SuccessOrQuit(dataset.Read<NetworkKeyTlv>(networkKey));
195 VerifyOrQuit(networkKey == AsCoreType(&kNewNetworkKey));
196
197 // Combining/Merging TLVs from two Datasets (using `Dataset::Info`).
198
199 SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes)));
200
201 SuccessOrQuit(dataset.WriteTlvsFrom(datasetInfo));
202
203 SuccessOrQuit(dataset.ValidateTlvs());
204
205 VerifyOrQuit(dataset.Contains<PanIdTlv>());
206 VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr);
207 SuccessOrQuit(dataset.Read<PanIdTlv>(panId));
208 VerifyOrQuit(panId == 0xcafe);
209
210 VerifyOrQuit(dataset.Contains<NetworkKeyTlv>());
211 VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr);
212 SuccessOrQuit(dataset.Read<NetworkKeyTlv>(networkKey));
213 VerifyOrQuit(networkKey == AsCoreType(&kNewNetworkKey));
214
215 // Append TLVs
216
217 SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes)));
218 VerifyOrQuit(dataset.GetLength() == sizeof(kTlvBytes));
219 VerifyOrQuit(memcmp(dataset.GetBytes(), kTlvBytes, sizeof(kTlvBytes)) == 0);
220
221 SuccessOrQuit(dataset.AppendTlvsFrom(kTlvBytes, sizeof(kTlvBytes)));
222 VerifyOrQuit(dataset.GetLength() == 2 * sizeof(kTlvBytes));
223 VerifyOrQuit(memcmp(dataset.GetBytes(), kTlvBytes, sizeof(kTlvBytes)) == 0);
224 VerifyOrQuit(memcmp(dataset.GetBytes() + sizeof(kTlvBytes), kTlvBytes, sizeof(kTlvBytes)) == 0);
225
226 VerifyOrQuit(dataset.ValidateTlvs() == kErrorParse);
227
228 // Validate `IsSubsetOf()`
229
230 SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes)));
231
232 datasetInfo.Clear();
233 datasetInfo.mComponents.mIsPanIdPresent = true;
234 datasetInfo.mComponents.mIsNetworkKeyPresent = true;
235 datasetInfo.mPanId = 0xface;
236 datasetInfo.mNetworkKey = kNetworkKey;
237
238 dataset2.SetFrom(datasetInfo);
239
240 SuccessOrQuit(dataset2.ValidateTlvs());
241 SuccessOrQuit(dataset.ValidateTlvs());
242
243 VerifyOrQuit(dataset2.IsSubsetOf(dataset));
244 VerifyOrQuit(!dataset.IsSubsetOf(dataset2));
245
246 datasetInfo.mComponents.mIsActiveTimestampPresent = true;
247 datasetInfo.mComponents.mIsPendingTimestampPresent = true;
248 datasetInfo.mComponents.mIsDelayPresent = true;
249 datasetInfo.mActiveTimestamp.mSeconds = 0xffff;
250 datasetInfo.mPendingTimestamp.mSeconds = 0x1000;
251 datasetInfo.mDelay = 5000;
252 dataset2.SetFrom(datasetInfo);
253
254 VerifyOrQuit(dataset2.IsSubsetOf(dataset));
255 VerifyOrQuit(!dataset.IsSubsetOf(dataset2));
256
257 datasetInfo.mPanId = 0xcafe;
258 dataset2.SetFrom(datasetInfo);
259
260 VerifyOrQuit(!dataset2.IsSubsetOf(dataset));
261 VerifyOrQuit(!dataset.IsSubsetOf(dataset2));
262 }
263
264 } // namespace MeshCoP
265 } // namespace ot
266
main(void)267 int main(void)
268 {
269 ot::MeshCoP::TestDataset();
270
271 printf("All tests passed\n");
272 return 0;
273 }
274