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"
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 /**
30 * @file
31 * This file implements IP6 header processing.
32 */
33
34 #include "ip6_headers.hpp"
35
36 #include "net/ip6.hpp"
37
38 namespace ot {
39 namespace Ip6 {
40
41 //---------------------------------------------------------------------------------------------------------------------
42 // Header
43
ParseFrom(const Message & aMessage)44 Error Header::ParseFrom(const Message &aMessage)
45 {
46 Error error = kErrorParse;
47
48 SuccessOrExit(aMessage.Read(0, *this));
49 VerifyOrExit(IsValid());
50 VerifyOrExit(sizeof(Header) + GetPayloadLength() == aMessage.GetLength());
51
52 error = kErrorNone;
53
54 exit:
55 return error;
56 }
57
IsValid(void) const58 bool Header::IsValid(void) const
59 {
60 #if !OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
61 static constexpr uint32_t kMaxLength = kMaxDatagramLength;
62 #else
63 static constexpr uint32_t kMaxLength = kMaxAssembledDatagramLength;
64 #endif
65
66 return IsVersion6() && ((sizeof(Header) + GetPayloadLength()) <= kMaxLength);
67 }
68
69 //---------------------------------------------------------------------------------------------------------------------
70 // Option
71
ParseFrom(const Message & aMessage,uint16_t aOffset,uint16_t aEndOffset)72 Error Option::ParseFrom(const Message &aMessage, uint16_t aOffset, uint16_t aEndOffset)
73 {
74 Error error;
75
76 // Read the Type first to check for the Pad1 Option.
77 // If it is not, then we read the full `Option` header.
78
79 SuccessOrExit(error = aMessage.Read(aOffset, this, sizeof(mType)));
80
81 if (mType == kTypePad1)
82 {
83 SetLength(0);
84 ExitNow();
85 }
86
87 SuccessOrExit(error = aMessage.Read(aOffset, *this));
88
89 VerifyOrExit(aOffset + GetSize() <= aEndOffset, error = kErrorParse);
90
91 exit:
92 return error;
93 }
94
GetSize(void) const95 uint16_t Option::GetSize(void) const
96 {
97 return (mType == kTypePad1) ? sizeof(mType) : static_cast<uint16_t>(mLength) + sizeof(Option);
98 }
99
100 //---------------------------------------------------------------------------------------------------------------------
101 // PadOption
102
InitForPadSize(uint8_t aPadSize)103 void PadOption::InitForPadSize(uint8_t aPadSize)
104 {
105 OT_UNUSED_VARIABLE(mPads);
106
107 Clear();
108
109 if (aPadSize == 1)
110 {
111 SetType(kTypePad1);
112 }
113 else
114 {
115 SetType(kTypePadN);
116 SetLength(aPadSize - sizeof(Option));
117 }
118 }
119
InitToPadHeaderWithSize(uint16_t aHeaderSize)120 Error PadOption::InitToPadHeaderWithSize(uint16_t aHeaderSize)
121 {
122 Error error = kErrorNone;
123 uint8_t size = static_cast<uint8_t>(aHeaderSize % ExtensionHeader::kLengthUnitSize);
124
125 VerifyOrExit(size != 0, error = kErrorAlready);
126 InitForPadSize(ExtensionHeader::kLengthUnitSize - size);
127
128 exit:
129 return error;
130 }
131
132 } // namespace Ip6
133 } // namespace ot
134