1 /*
2 * Copyright (c) 2022, 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 "test_platform.h"
30
31 #include <openthread/config.h>
32
33 #include "common/message.hpp"
34 #include "common/tlvs.hpp"
35 #include "instance/instance.hpp"
36
37 #include "test_util.h"
38
39 namespace ot {
40
TestTlv(void)41 void TestTlv(void)
42 {
43 Instance *instance = testInitInstance();
44 Message *message;
45 Tlv tlv;
46 ExtendedTlv extTlv;
47 uint16_t offset;
48 uint16_t valueOffset;
49 uint16_t length;
50 uint8_t buffer[4];
51
52 VerifyOrQuit(instance != nullptr);
53
54 VerifyOrQuit((message = instance->Get<MessagePool>().Allocate(Message::kTypeIp6)) != nullptr);
55 VerifyOrQuit(message != nullptr);
56
57 VerifyOrQuit(message->GetOffset() == 0);
58 VerifyOrQuit(message->GetLength() == 0);
59
60 VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 1, valueOffset, length) == kErrorNotFound);
61 VerifyOrQuit(Tlv::ReadTlvValue(*message, 0, buffer, 1) == kErrorParse);
62
63 // Add an empty TLV with type 1 and check that we can find it
64
65 offset = message->GetLength();
66
67 tlv.SetType(1);
68 tlv.SetLength(0);
69 SuccessOrQuit(message->Append(tlv));
70
71 SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 1, valueOffset, length));
72 VerifyOrQuit(valueOffset == sizeof(Tlv));
73 VerifyOrQuit(length == 0);
74 SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 0));
75 VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
76
77 // Add an empty extended TLV (type 2), and check that we can find it.
78
79 offset = message->GetLength();
80
81 extTlv.SetType(2);
82 extTlv.SetLength(0);
83 SuccessOrQuit(message->Append(extTlv));
84
85 SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 2, valueOffset, length));
86 VerifyOrQuit(valueOffset == offset + sizeof(ExtendedTlv));
87 VerifyOrQuit(length == 0);
88 SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 0));
89 VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
90
91 // Add a TLV with type 3 with one byte value and check if we can find it.
92
93 offset = message->GetLength();
94
95 tlv.SetType(3);
96 tlv.SetLength(1);
97 SuccessOrQuit(message->Append(tlv));
98 SuccessOrQuit(message->Append<uint8_t>(0xff));
99
100 SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 3, valueOffset, length));
101 VerifyOrQuit(valueOffset == offset + sizeof(Tlv));
102 VerifyOrQuit(length == 1);
103 SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1));
104 VerifyOrQuit(buffer[0] == 0x0ff);
105 VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2) == kErrorParse);
106
107 // Add an extended TLV with type 4 with two byte value and check if we can find it.
108
109 offset = message->GetLength();
110
111 extTlv.SetType(4);
112 extTlv.SetLength(2);
113 SuccessOrQuit(message->Append(extTlv));
114 SuccessOrQuit(message->Append<uint8_t>(0x12));
115 SuccessOrQuit(message->Append<uint8_t>(0x34));
116
117 SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 4, valueOffset, length));
118 VerifyOrQuit(valueOffset == offset + sizeof(ExtendedTlv));
119 VerifyOrQuit(length == 2);
120 SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1));
121 VerifyOrQuit(buffer[0] == 0x12);
122 SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2));
123 VerifyOrQuit(buffer[0] == 0x12);
124 VerifyOrQuit(buffer[1] == 0x34);
125 VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 3) == kErrorParse);
126
127 // Add a TLV with missing value.
128
129 offset = message->GetLength();
130
131 tlv.SetType(5);
132 tlv.SetLength(1);
133 SuccessOrQuit(message->Append(tlv));
134
135 VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 5, valueOffset, length) != kErrorNone);
136 VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 0) == kErrorParse);
137
138 // Add the missing value.
139 SuccessOrQuit(message->Append<uint8_t>(0xaa));
140
141 SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 5, valueOffset, length));
142 VerifyOrQuit(valueOffset == offset + sizeof(Tlv));
143 VerifyOrQuit(length == 1);
144 SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1));
145 VerifyOrQuit(buffer[0] == 0xaa);
146 VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2) == kErrorParse);
147
148 // Add an extended TLV with missing value.
149
150 offset = message->GetLength();
151
152 extTlv.SetType(6);
153 extTlv.SetLength(2);
154 SuccessOrQuit(message->Append(extTlv));
155 SuccessOrQuit(message->Append<uint8_t>(0xbb));
156
157 VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 6, valueOffset, length) != kErrorNone);
158 VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
159
160 SuccessOrQuit(message->Append<uint8_t>(0xcc));
161
162 SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 6, valueOffset, length) != kErrorNone);
163 VerifyOrQuit(valueOffset == offset + sizeof(ExtendedTlv));
164 VerifyOrQuit(length == 2);
165 SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2));
166 VerifyOrQuit(buffer[0] == 0xbb);
167 VerifyOrQuit(buffer[1] == 0xcc);
168 VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 3) == kErrorParse);
169
170 // Add an extended TLV with overflow length.
171
172 offset = message->GetLength();
173
174 extTlv.SetType(7);
175 extTlv.SetLength(0xffff);
176 SuccessOrQuit(message->Append(extTlv));
177 SuccessOrQuit(message->Append<uint8_t>(0x11));
178
179 VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 7, valueOffset, length) != kErrorNone);
180 VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
181
182 message->Free();
183
184 testFreeInstance(instance);
185 }
186
187 } // namespace ot
188
main(void)189 int main(void)
190 {
191 ot::TestTlv();
192 printf("All tests passed\n");
193 return 0;
194 }
195