• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *    Copyright (c) 2017, 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" AND
17  *    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  *    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20  *    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  *    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /**
29  * @file
30  *   This file implements a spinel decoder.
31  */
32 
33 #include "spinel_decoder.hpp"
34 
35 #include "common/code_utils.hpp"
36 #include "common/string.hpp"
37 
38 namespace ot {
39 namespace Spinel {
40 
Decoder(void)41 Decoder::Decoder(void)
42     : mFrame(nullptr)
43     , mLength(0)
44     , mIndex(0)
45     , mEnd(0)
46     , mNumOpenStructs(0)
47     , mSavedNumOpenStructs(0)
48     , mSavedIndex(0)
49     , mSavedEnd(0)
50 {
51 }
52 
Init(const uint8_t * aFrame,uint16_t aLength)53 void Decoder::Init(const uint8_t *aFrame, uint16_t aLength)
54 {
55     mFrame  = aFrame;
56     mLength = (mFrame != nullptr) ? aLength : 0;
57 
58     Reset();
59     ClearSavedPosition();
60 }
61 
Reset(void)62 void Decoder::Reset(void)
63 {
64     mIndex          = 0;
65     mEnd            = mLength;
66     mNumOpenStructs = 0;
67     ClearSavedPosition();
68 }
69 
ReadBool(bool & aBool)70 otError Decoder::ReadBool(bool &aBool)
71 {
72     otError error = OT_ERROR_NONE;
73     uint8_t byte;
74 
75     SuccessOrExit(error = ReadUint8(byte));
76 
77     // Boolean value are encoded in 8-bits as either 0x00 or 0x01. All other values are illegal.
78     if (byte == 0x00)
79     {
80         aBool = false;
81     }
82     else if (byte == 0x01)
83     {
84         aBool = true;
85     }
86     else
87     {
88         error = OT_ERROR_PARSE;
89     }
90 
91 exit:
92     return error;
93 }
94 
ReadUint8(uint8_t & aUint8)95 otError Decoder::ReadUint8(uint8_t &aUint8)
96 {
97     otError error = OT_ERROR_NONE;
98 
99     VerifyOrExit(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);
100     aUint8 = mFrame[mIndex];
101     mIndex += sizeof(uint8_t);
102 
103 exit:
104     return error;
105 }
106 
ReadInt8(int8_t & aInt8)107 otError Decoder::ReadInt8(int8_t &aInt8)
108 {
109     otError error = OT_ERROR_NONE;
110     uint8_t byte;
111 
112     SuccessOrExit(error = ReadUint8(byte));
113     aInt8 = static_cast<int8_t>(byte);
114 
115 exit:
116     return error;
117 }
118 
ReadUint16(uint16_t & aUint16)119 otError Decoder::ReadUint16(uint16_t &aUint16)
120 {
121     otError error = OT_ERROR_NONE;
122 
123     VerifyOrExit(mIndex + sizeof(uint16_t) <= mEnd, error = OT_ERROR_PARSE);
124 
125     aUint16 = static_cast<uint16_t>(mFrame[mIndex] | (mFrame[mIndex + 1] << 8));
126 
127     mIndex += sizeof(uint16_t);
128 
129 exit:
130     return error;
131 }
132 
ReadInt16(int16_t & aInt16)133 otError Decoder::ReadInt16(int16_t &aInt16)
134 {
135     otError  error = OT_ERROR_NONE;
136     uint16_t u16;
137 
138     SuccessOrExit(error = ReadUint16(u16));
139     aInt16 = static_cast<int16_t>(u16);
140 
141 exit:
142     return error;
143 }
144 
ReadUint32(uint32_t & aUint32)145 otError Decoder::ReadUint32(uint32_t &aUint32)
146 {
147     otError error = OT_ERROR_NONE;
148 
149     VerifyOrExit(mIndex + sizeof(uint32_t) <= mEnd, error = OT_ERROR_PARSE);
150 
151     aUint32 = ((static_cast<uint32_t>(mFrame[mIndex + 0]) << 0) | (static_cast<uint32_t>(mFrame[mIndex + 1]) << 8) |
152                (static_cast<uint32_t>(mFrame[mIndex + 2]) << 16) | (static_cast<uint32_t>(mFrame[mIndex + 3]) << 24));
153 
154     mIndex += sizeof(uint32_t);
155 
156 exit:
157     return error;
158 }
159 
ReadInt32(int32_t & aInt32)160 otError Decoder::ReadInt32(int32_t &aInt32)
161 {
162     otError  error = OT_ERROR_NONE;
163     uint32_t u32;
164 
165     SuccessOrExit(error = ReadUint32(u32));
166     aInt32 = static_cast<int32_t>(u32);
167 
168 exit:
169     return error;
170 }
171 
ReadUint64(uint64_t & aUint64)172 otError Decoder::ReadUint64(uint64_t &aUint64)
173 {
174     otError error = OT_ERROR_NONE;
175 
176     VerifyOrExit(mIndex + sizeof(uint64_t) <= mEnd, error = OT_ERROR_PARSE);
177 
178     aUint64 = ((static_cast<uint64_t>(mFrame[mIndex + 0]) << 0) | (static_cast<uint64_t>(mFrame[mIndex + 1]) << 8) |
179                (static_cast<uint64_t>(mFrame[mIndex + 2]) << 16) | (static_cast<uint64_t>(mFrame[mIndex + 3]) << 24) |
180                (static_cast<uint64_t>(mFrame[mIndex + 4]) << 32) | (static_cast<uint64_t>(mFrame[mIndex + 5]) << 40) |
181                (static_cast<uint64_t>(mFrame[mIndex + 6]) << 48) | (static_cast<uint64_t>(mFrame[mIndex + 7]) << 56));
182 
183     mIndex += sizeof(uint64_t);
184 
185 exit:
186     return error;
187 }
188 
ReadInt64(int64_t & aInt64)189 otError Decoder::ReadInt64(int64_t &aInt64)
190 {
191     otError  error = OT_ERROR_NONE;
192     uint64_t u64;
193 
194     SuccessOrExit(error = ReadUint64(u64));
195     aInt64 = static_cast<int64_t>(u64);
196 
197 exit:
198     return error;
199 }
200 
ReadUintPacked(unsigned int & aUint)201 otError Decoder::ReadUintPacked(unsigned int &aUint)
202 {
203     otError        error = OT_ERROR_NONE;
204     spinel_ssize_t parsedLen;
205     unsigned int   uint;
206 
207     parsedLen = spinel_packed_uint_decode(&mFrame[mIndex], mEnd - mIndex, &uint);
208     VerifyOrExit(parsedLen > 0, error = OT_ERROR_PARSE);
209 
210     mIndex += parsedLen;
211     aUint = uint;
212 
213 exit:
214     return error;
215 }
216 
217 // Reads an item of given size and updates the pointer `aPtr`.
ReadItem(const uint8_t ** aPtr,uint16_t aSize)218 otError Decoder::ReadItem(const uint8_t **aPtr, uint16_t aSize)
219 {
220     otError error = OT_ERROR_NONE;
221 
222     VerifyOrExit(mIndex + aSize <= mEnd, error = OT_ERROR_PARSE);
223 
224     *aPtr = &mFrame[mIndex];
225 
226     mIndex += aSize;
227 
228 exit:
229     return error;
230 }
231 
ReadIp6Address(spinel_ipv6addr_t & aIp6Addr)232 otError Decoder::ReadIp6Address(spinel_ipv6addr_t &aIp6Addr)
233 {
234     otError                  error       = OT_ERROR_NONE;
235     const spinel_ipv6addr_t *ipv6AddrPtr = nullptr;
236 
237     SuccessOrExit(error = ReadIp6Address(ipv6AddrPtr));
238     VerifyOrExit(ipv6AddrPtr != nullptr, error = OT_ERROR_PARSE);
239     aIp6Addr = *ipv6AddrPtr;
240 
241 exit:
242     return error;
243 }
244 
ReadIp6Address(otIp6Address & aIp6Addr)245 otError Decoder::ReadIp6Address(otIp6Address &aIp6Addr)
246 {
247     otError             error       = OT_ERROR_NONE;
248     const otIp6Address *ipv6AddrPtr = nullptr;
249 
250     SuccessOrExit(error = ReadIp6Address(ipv6AddrPtr));
251     VerifyOrExit(ipv6AddrPtr != nullptr, error = OT_ERROR_PARSE);
252     aIp6Addr = *ipv6AddrPtr;
253 
254 exit:
255     return error;
256 }
257 
ReadEui64(spinel_eui64_t & aEui64)258 otError Decoder::ReadEui64(spinel_eui64_t &aEui64)
259 {
260     otError               error    = OT_ERROR_NONE;
261     const spinel_eui64_t *eui64Ptr = nullptr;
262 
263     SuccessOrExit(error = ReadEui64(eui64Ptr));
264     VerifyOrExit(eui64Ptr != nullptr, error = OT_ERROR_PARSE);
265     aEui64 = *eui64Ptr;
266 
267 exit:
268     return error;
269 }
270 
ReadEui64(otExtAddress & aEui64)271 otError Decoder::ReadEui64(otExtAddress &aEui64)
272 {
273     otError             error    = OT_ERROR_NONE;
274     const otExtAddress *eui64Ptr = nullptr;
275 
276     SuccessOrExit(error = ReadEui64(eui64Ptr));
277     VerifyOrExit(eui64Ptr != nullptr, error = OT_ERROR_PARSE);
278     aEui64 = *eui64Ptr;
279 
280 exit:
281     return error;
282 }
283 
ReadEui48(spinel_eui48_t & aEui48)284 otError Decoder::ReadEui48(spinel_eui48_t &aEui48)
285 {
286     otError               error    = OT_ERROR_NONE;
287     const spinel_eui48_t *eui48Ptr = nullptr;
288 
289     SuccessOrExit(error = ReadEui48(eui48Ptr));
290     VerifyOrExit(eui48Ptr != nullptr, error = OT_ERROR_PARSE);
291     aEui48 = *eui48Ptr;
292 
293 exit:
294     return error;
295 }
296 
ReadUtf8(const char * & aUtf8)297 otError Decoder::ReadUtf8(const char *&aUtf8)
298 {
299     otError error = OT_ERROR_NONE;
300     size_t  len;
301 
302     // Ensure there is at least one byte (for null character).
303     VerifyOrExit(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);
304 
305     len = StringLength(reinterpret_cast<const char *>(&mFrame[mIndex]), mEnd - mIndex);
306     VerifyOrExit(len < static_cast<uint16_t>(mEnd - mIndex), error = OT_ERROR_PARSE);
307 
308     aUtf8 = reinterpret_cast<const char *>(&mFrame[mIndex]);
309 
310     // `sizeof(uint8_t)` is added for the terminating null character.
311     mIndex += static_cast<uint16_t>(len + sizeof(uint8_t));
312 
313 exit:
314     return error;
315 }
316 
ReadData(const uint8_t * & aData,uint16_t & aDataLen)317 otError Decoder::ReadData(const uint8_t *&aData, uint16_t &aDataLen)
318 {
319     aDataLen = mEnd - mIndex;
320 
321     return ReadItem(&aData, aDataLen);
322 }
323 
ReadDataWithLen(const uint8_t * & aData,uint16_t & aDataLen)324 otError Decoder::ReadDataWithLen(const uint8_t *&aData, uint16_t &aDataLen)
325 {
326     otError  error = OT_ERROR_NONE;
327     uint16_t len;
328 
329     SuccessOrExit(error = ReadUint16(len));
330     SuccessOrExit(error = ReadItem(&aData, len));
331     aDataLen = len;
332 
333 exit:
334     return error;
335 }
336 
OpenStruct(void)337 otError Decoder::OpenStruct(void)
338 {
339     otError  error = OT_ERROR_NONE;
340     uint16_t structLen;
341 
342     VerifyOrExit(mNumOpenStructs < kMaxNestedStructs, error = OT_ERROR_INVALID_STATE);
343 
344     SuccessOrExit(error = ReadUint16(structLen));
345     VerifyOrExit(structLen <= mEnd - mIndex, error = OT_ERROR_PARSE);
346 
347     mPrevEnd[mNumOpenStructs] = mEnd;
348     mEnd                      = (mIndex + structLen);
349     mNumOpenStructs++;
350 
351 exit:
352     return error;
353 }
354 
CloseStruct(void)355 otError Decoder::CloseStruct(void)
356 {
357     otError error = OT_ERROR_NONE;
358 
359     VerifyOrExit(mNumOpenStructs > 0, error = OT_ERROR_INVALID_STATE);
360 
361     // If there is a saved position and it is contained
362     // within the current struct being closed, the saved
363     // position is cleared to ensure user cannot go back
364     // to middle of an already closed struct.
365 
366     if (IsSavedPositionValid() && (mNumOpenStructs == mSavedNumOpenStructs))
367     {
368         ClearSavedPosition();
369     }
370 
371     mNumOpenStructs--;
372     mIndex = mEnd;
373     mEnd   = mPrevEnd[mNumOpenStructs];
374 
375 exit:
376     return error;
377 }
378 
SavePosition(void)379 void Decoder::SavePosition(void)
380 {
381     mSavedIndex          = mIndex;
382     mSavedEnd            = mEnd;
383     mSavedNumOpenStructs = mNumOpenStructs;
384 }
385 
ResetToSaved(void)386 otError Decoder::ResetToSaved(void)
387 {
388     otError error = OT_ERROR_NONE;
389 
390     VerifyOrExit(IsSavedPositionValid(), error = OT_ERROR_INVALID_STATE);
391 
392     mIndex          = mSavedIndex;
393     mEnd            = mSavedEnd;
394     mNumOpenStructs = mSavedNumOpenStructs;
395 
396 exit:
397     return error;
398 }
399 
400 } // namespace Spinel
401 } // namespace ot
402