1 /*
2 * Copyright (c) 2020, 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 includes implementations for ICMPv6 Router Advertisement.
32 *
33 */
34
35 #include "border_router/router_advertisement.hpp"
36
37 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
38
39 namespace ot {
40
41 namespace BorderRouter {
42
43 namespace RouterAdv {
44
GetNextOption(const Option * aCurOption,const uint8_t * aBuffer,uint16_t aBufferLength)45 const Option *Option::GetNextOption(const Option *aCurOption, const uint8_t *aBuffer, uint16_t aBufferLength)
46 {
47 const uint8_t *nextOption = nullptr;
48 const uint8_t *bufferEnd = aBuffer + aBufferLength;
49
50 VerifyOrExit(aBuffer != nullptr, nextOption = nullptr);
51
52 if (aCurOption == nullptr)
53 {
54 nextOption = aBuffer;
55 }
56 else
57 {
58 nextOption = reinterpret_cast<const uint8_t *>(aCurOption) + aCurOption->GetSize();
59 }
60
61 VerifyOrExit(nextOption + sizeof(Option) <= bufferEnd, nextOption = nullptr);
62 VerifyOrExit(reinterpret_cast<const Option *>(nextOption)->GetSize() > 0, nextOption = nullptr);
63 VerifyOrExit(nextOption + reinterpret_cast<const Option *>(nextOption)->GetSize() <= bufferEnd,
64 nextOption = nullptr);
65
66 exit:
67 return reinterpret_cast<const Option *>(nextOption);
68 }
69
PrefixInfoOption(void)70 PrefixInfoOption::PrefixInfoOption(void)
71 : Option(Type::kPrefixInfo, sizeof(*this) / kLengthUnit)
72 , mPrefixLength(0)
73 , mReserved1(0)
74 , mValidLifetime(0)
75 , mPreferredLifetime(0)
76 , mReserved2(0)
77 {
78 OT_UNUSED_VARIABLE(mReserved2);
79
80 mPrefix.Clear();
81 }
82
SetOnLink(bool aOnLink)83 void PrefixInfoOption::SetOnLink(bool aOnLink)
84 {
85 if (aOnLink)
86 {
87 mReserved1 |= kOnLinkFlagMask;
88 }
89 else
90 {
91 mReserved1 &= ~kOnLinkFlagMask;
92 }
93 }
94
SetAutoAddrConfig(bool aAutoAddrConfig)95 void PrefixInfoOption::SetAutoAddrConfig(bool aAutoAddrConfig)
96 {
97 if (aAutoAddrConfig)
98 {
99 mReserved1 |= kAutoConfigFlagMask;
100 }
101 else
102 {
103 mReserved1 &= ~kAutoConfigFlagMask;
104 }
105 }
106
SetPrefix(const Ip6::Prefix & aPrefix)107 void PrefixInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
108 {
109 mPrefixLength = aPrefix.mLength;
110 mPrefix = static_cast<const Ip6::Address &>(aPrefix.mPrefix);
111 }
112
GetPrefix(void) const113 Ip6::Prefix PrefixInfoOption::GetPrefix(void) const
114 {
115 Ip6::Prefix prefix;
116
117 prefix.Set(mPrefix.GetBytes(), mPrefixLength);
118 return prefix;
119 }
120
RouteInfoOption(void)121 RouteInfoOption::RouteInfoOption(void)
122 : Option(Type::kRouteInfo, 0)
123 , mPrefixLength(0)
124 , mReserved(0)
125 , mRouteLifetime(0)
126 {
127 OT_UNUSED_VARIABLE(mReserved);
128
129 mPrefix.Clear();
130 }
131
SetPreference(RoutePreference aPreference)132 void RouteInfoOption::SetPreference(RoutePreference aPreference)
133 {
134 mReserved &= ~kPreferenceMask;
135 mReserved |= (NetworkData::RoutePreferenceToValue(aPreference) << kPreferenceOffset) & kPreferenceMask;
136 }
137
GetPreference(void) const138 RouteInfoOption::RoutePreference RouteInfoOption::GetPreference(void) const
139 {
140 return NetworkData::RoutePreferenceFromValue((mReserved & kPreferenceMask) >> kPreferenceOffset);
141 }
142
SetPrefix(const Ip6::Prefix & aPrefix)143 void RouteInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
144 {
145 // The total length (in bytes) of a Router Information Option
146 // is: (8 bytes fixed option header) + (0, 8, or 16 bytes prefix).
147 // Because the length of the option must be padded with 8 bytes,
148 // the length of the prefix (in bits) must be padded with 64 bits.
149 SetLength((aPrefix.mLength + kLengthUnit * CHAR_BIT - 1) / (kLengthUnit * CHAR_BIT) + 1);
150
151 mPrefixLength = aPrefix.mLength;
152 mPrefix = static_cast<const Ip6::Address &>(aPrefix.mPrefix);
153 }
154
GetPrefix(void) const155 Ip6::Prefix RouteInfoOption::GetPrefix(void) const
156 {
157 Ip6::Prefix prefix;
158
159 prefix.Set(mPrefix.GetBytes(), mPrefixLength);
160 return prefix;
161 }
162
IsValid(void) const163 bool RouteInfoOption::IsValid(void) const
164 {
165 return (GetLength() == 1 || GetLength() == 2 || GetLength() == 3) &&
166 (mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) && NetworkData::IsRoutePreferenceValid(GetPreference());
167 }
168
SetToDefault(void)169 void RouterAdvMessage::SetToDefault(void)
170 {
171 mHeader.Clear();
172 mHeader.SetType(Ip6::Icmp::Header::kTypeRouterAdvert);
173 mReachableTime = 0;
174 mRetransTimer = 0;
175 }
176
operator =(const RouterAdvMessage & aOther)177 const RouterAdvMessage &RouterAdvMessage::operator=(const RouterAdvMessage &aOther)
178 {
179 mHeader = aOther.mHeader;
180
181 // Set zero value and let platform do the calculation.
182 mHeader.SetChecksum(0);
183
184 mReachableTime = aOther.mReachableTime;
185 mRetransTimer = aOther.mRetransTimer;
186
187 return *this;
188 }
189
operator ==(const RouterAdvMessage & aOther) const190 bool RouterAdvMessage::operator==(const RouterAdvMessage &aOther) const
191 {
192 return memcmp(&mHeader.mData, &aOther.mHeader.mData, sizeof(mHeader.mData)) == 0 &&
193 mReachableTime == aOther.mReachableTime && mRetransTimer == aOther.mRetransTimer;
194 }
195
RouterSolicitMessage(void)196 RouterSolicitMessage::RouterSolicitMessage(void)
197 {
198 mHeader.Clear();
199 mHeader.SetType(Ip6::Icmp::Header::kTypeRouterSolicit);
200 }
201
202 } // namespace RouterAdv
203
204 } // namespace BorderRouter
205
206 } // namespace ot
207
208 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
209