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/instance.hpp"
34 #include "common/message.hpp"
35 #include "common/tlvs.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