• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, 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 definitions for ICMPv6.
32  */
33 
34 #ifndef ICMP6_HPP_
35 #define ICMP6_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/icmp6.h>
40 
41 #include "common/as_core_type.hpp"
42 #include "common/clearable.hpp"
43 #include "common/encoding.hpp"
44 #include "common/linked_list.hpp"
45 #include "common/locator.hpp"
46 #include "common/non_copyable.hpp"
47 #include "net/ip6_headers.hpp"
48 
49 namespace ot {
50 namespace Ip6 {
51 
52 using ot::Encoding::BigEndian::HostSwap16;
53 
54 /**
55  * @addtogroup core-ip6-icmp6
56  *
57  * @brief
58  *   This module includes definitions for ICMPv6.
59  *
60  * @{
61  *
62  */
63 
64 class Headers;
65 
66 /**
67  * This class implements ICMPv6.
68  *
69  */
70 class Icmp : public InstanceLocator, private NonCopyable
71 {
72 public:
73     /*
74      * This class implements ICMPv6 header generation and parsing.
75      *
76      */
77     OT_TOOL_PACKED_BEGIN
78     class Header : public otIcmp6Header, public Clearable<Header>
79     {
80     public:
81         /**
82          * ICMPv6 Message Types
83          *
84          */
85         enum Type : uint8_t
86         {
87             kTypeDstUnreach       = OT_ICMP6_TYPE_DST_UNREACH,       ///< Destination Unreachable
88             kTypePacketToBig      = OT_ICMP6_TYPE_PACKET_TO_BIG,     ///< Packet To Big
89             kTypeTimeExceeded     = OT_ICMP6_TYPE_TIME_EXCEEDED,     ///< Time Exceeded
90             kTypeParameterProblem = OT_ICMP6_TYPE_PARAMETER_PROBLEM, ///< Parameter Problem
91             kTypeEchoRequest      = OT_ICMP6_TYPE_ECHO_REQUEST,      ///< Echo Request
92             kTypeEchoReply        = OT_ICMP6_TYPE_ECHO_REPLY,        ///< Echo Reply
93             kTypeRouterSolicit    = OT_ICMP6_TYPE_ROUTER_SOLICIT,    ///< Router Solicitation
94             kTypeRouterAdvert     = OT_ICMP6_TYPE_ROUTER_ADVERT,     ///< Router Advertisement
95         };
96 
97         /**
98          * ICMPv6 Message Codes
99          *
100          */
101         enum Code : uint8_t
102         {
103             kCodeDstUnreachNoRoute = OT_ICMP6_CODE_DST_UNREACH_NO_ROUTE, ///< Destination Unreachable No Route
104             kCodeFragmReasTimeEx   = OT_ICMP6_CODE_FRAGM_REAS_TIME_EX,   ///< Fragment Reassembly Time Exceeded
105         };
106 
107         static constexpr uint8_t kTypeFieldOffset     = 0; ///< The byte offset of Type field in ICMP6 header.
108         static constexpr uint8_t kCodeFieldOffset     = 1; ///< The byte offset of Code field in ICMP6 header.
109         static constexpr uint8_t kChecksumFieldOffset = 2; ///< The byte offset of Checksum field in ICMP6 header.
110         static constexpr uint8_t kDataFieldOffset     = 4; ///< The byte offset of Data field in ICMP6 header.
111 
112         /**
113          * This method indicates whether the ICMPv6 message is an error message.
114          *
115          * @retval TRUE if the ICMPv6 message is an error message.
116          * @retval FALSE if the ICMPv6 message is an informational message.
117          *
118          */
IsError(void) const119         bool IsError(void) const { return mType < OT_ICMP6_TYPE_ECHO_REQUEST; }
120 
121         /**
122          * This method returns the ICMPv6 message type.
123          *
124          * @returns The ICMPv6 message type.
125          *
126          */
GetType(void) const127         Type GetType(void) const { return static_cast<Type>(mType); }
128 
129         /**
130          * This method sets the ICMPv6 message type.
131          *
132          * @param[in]  aType  The ICMPv6 message type.
133          *
134          */
SetType(Type aType)135         void SetType(Type aType) { mType = static_cast<uint8_t>(aType); }
136 
137         /**
138          * This method returns the ICMPv6 message code.
139          *
140          * @returns The ICMPv6 message code.
141          *
142          */
GetCode(void) const143         Code GetCode(void) const { return static_cast<Code>(mCode); }
144 
145         /**
146          * This method sets the ICMPv6 message code.
147          *
148          * @param[in]  aCode  The ICMPv6 message code.
149          *
150          */
SetCode(Code aCode)151         void SetCode(Code aCode) { mCode = static_cast<uint8_t>(aCode); }
152 
153         /**
154          * This method returns the ICMPv6 message checksum.
155          *
156          * @returns The ICMPv6 message checksum.
157          *
158          */
GetChecksum(void) const159         uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
160 
161         /**
162          * This method sets the ICMPv6 message checksum.
163          *
164          * @param[in]  aChecksum  The ICMPv6 message checksum.
165          *
166          */
SetChecksum(uint16_t aChecksum)167         void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
168 
169         /**
170          * This method returns the ICMPv6 message ID for Echo Requests and Replies.
171          *
172          * @returns The ICMPv6 message ID.
173          *
174          */
GetId(void) const175         uint16_t GetId(void) const { return HostSwap16(mData.m16[0]); }
176 
177         /**
178          * This method sets the ICMPv6 message ID for Echo Requests and Replies.
179          *
180          * @param[in]  aId  The ICMPv6 message ID.
181          *
182          */
SetId(uint16_t aId)183         void SetId(uint16_t aId) { mData.m16[0] = HostSwap16(aId); }
184 
185         /**
186          * This method returns the ICMPv6 message sequence for Echo Requests and Replies.
187          *
188          * @returns The ICMPv6 message sequence.
189          *
190          */
GetSequence(void) const191         uint16_t GetSequence(void) const { return HostSwap16(mData.m16[1]); }
192 
193         /**
194          * This method sets the ICMPv6 message sequence for Echo Requests and Replies.
195          *
196          * @param[in]  aSequence  The ICMPv6 message sequence.
197          *
198          */
SetSequence(uint16_t aSequence)199         void SetSequence(uint16_t aSequence) { mData.m16[1] = HostSwap16(aSequence); }
200     } OT_TOOL_PACKED_END;
201 
202     /**
203      * This class implements ICMPv6 message handlers.
204      *
205      */
206     class Handler : public otIcmp6Handler, public LinkedListEntry<Handler>
207     {
208         friend class Icmp;
209 
210     public:
211         /**
212          * This constructor creates an ICMPv6 message handler.
213          *
214          * @param[in]  aCallback  A pointer to the function that is called when receiving an ICMPv6 message.
215          * @param[in]  aContext   A pointer to arbitrary context information.
216          *
217          */
Handler(otIcmp6ReceiveCallback aCallback,void * aContext)218         Handler(otIcmp6ReceiveCallback aCallback, void *aContext)
219         {
220             mReceiveCallback = aCallback;
221             mContext         = aContext;
222             mNext            = nullptr;
223         }
224 
225     private:
HandleReceiveMessage(Message & aMessage,const MessageInfo & aMessageInfo,const Header & aIcmp6Header)226         void HandleReceiveMessage(Message &aMessage, const MessageInfo &aMessageInfo, const Header &aIcmp6Header)
227         {
228             mReceiveCallback(mContext, &aMessage, &aMessageInfo, &aIcmp6Header);
229         }
230     };
231 
232     /**
233      * This constructor initializes the object.
234      *
235      * @param[in]  aInstance A reference to the OpenThread instance.
236      *
237      */
238     explicit Icmp(Instance &aInstance);
239 
240     /**
241      * This method returns a new ICMP message with sufficient header space reserved.
242      *
243      * @param[in]  aReserved  The number of header bytes to reserve after the ICMP header.
244      *
245      * @returns A pointer to the message or `nullptr` if no buffers are available.
246      *
247      */
248     Message *NewMessage(uint16_t aReserved);
249 
250     /**
251      * This method registers ICMPv6 handler.
252      *
253      * @param[in]  aHandler  A reference to the ICMPv6 handler.
254      *
255      * @retval kErrorNone     Successfully registered the ICMPv6 handler.
256      * @retval kErrorAlready  The ICMPv6 handler is already registered.
257      *
258      */
259     Error RegisterHandler(Handler &aHandler);
260 
261     /**
262      * This method sends an ICMPv6 Echo Request message.
263      *
264      * @param[in]  aMessage      A reference to the Echo Request payload.
265      * @param[in]  aMessageInfo  A reference to the message info associated with @p aMessage.
266      * @param[in]  aIdentifier   An identifier to aid in matching Echo Replies to this Echo Request.
267      *                           May be zero.
268      *
269      * @retval kErrorNone     Successfully enqueued the ICMPv6 Echo Request message.
270      * @retval kErrorNoBufs   Insufficient buffers available to generate an ICMPv6 Echo Request message.
271      *
272      */
273     Error SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo, uint16_t aIdentifier);
274 
275     /**
276      * This method sends an ICMPv6 error message.
277      *
278      * @param[in]  aType         The ICMPv6 message type.
279      * @param[in]  aCode         The ICMPv6 message code.
280      * @param[in]  aMessageInfo  A reference to the message info.
281      * @param[in]  aMessage      The error-causing IPv6 message.
282      *
283      * @retval kErrorNone     Successfully enqueued the ICMPv6 error message.
284      * @retval kErrorNoBufs   Insufficient buffers available.
285      *
286      */
287     Error SendError(Header::Type aType, Header::Code aCode, const MessageInfo &aMessageInfo, const Message &aMessage);
288 
289     /**
290      * This method sends an ICMPv6 error message.
291      *
292      * @param[in]  aType         The ICMPv6 message type.
293      * @param[in]  aCode         The ICMPv6 message code.
294      * @param[in]  aMessageInfo  A reference to the message info.
295      * @param[in]  aHeaders      The parsed headers from the error-causing IPv6 message.
296      *
297      * @retval kErrorNone     Successfully enqueued the ICMPv6 error message.
298      * @retval kErrorNoBufs   Insufficient buffers available.
299      *
300      */
301     Error SendError(Header::Type aType, Header::Code aCode, const MessageInfo &aMessageInfo, const Headers &aHeaders);
302 
303     /**
304      * This method handles an ICMPv6 message.
305      *
306      * @param[in]  aMessage      A reference to the ICMPv6 message.
307      * @param[in]  aMessageInfo  A reference to the message info associated with @p aMessage.
308      *
309      * @retval kErrorNone     Successfully processed the ICMPv6 message.
310      * @retval kErrorNoBufs   Insufficient buffers available to generate the reply.
311      * @retval kErrorDrop     The ICMPv6 message was invalid and dropped.
312      *
313      */
314     Error HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
315 
316     /**
317      * This method indicates whether or not ICMPv6 Echo processing is enabled.
318      *
319      * @retval TRUE   ICMPv6 Echo processing is enabled.
320      * @retval FALSE  ICMPv6 Echo processing is disabled.
321      *
322      */
GetEchoMode(void) const323     otIcmp6EchoMode GetEchoMode(void) const { return mEchoMode; }
324 
325     /**
326      * Sets the ICMPv6 echo mode.
327      *
328      * @param[in]  aMode  The ICMPv6 echo mode.
329      *
330      */
SetEchoMode(otIcmp6EchoMode aMode)331     void SetEchoMode(otIcmp6EchoMode aMode) { mEchoMode = aMode; }
332 
333     /**
334      * This method indicates whether or not the ICMPv6 Echo Request should be handled.
335      *
336      * @retval TRUE if OpenThread should respond with an ICMPv6 Echo Reply.
337      * @retval FALSE if OpenThread should not respond with an ICMPv6 Echo Reply.
338      *
339      */
340     bool ShouldHandleEchoRequest(const MessageInfo &aMessageInfo);
341 
342     /**
343      * This method returns the ICMPv6 Echo sequence number.
344      *
345      * @returns The sequence number of the next ICMPv6 Echo request.
346      *
347      */
GetEchoSequence(void) const348     uint16_t GetEchoSequence(void) const { return mEchoSequence; }
349 
350 private:
351     Error HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo);
352 
353     LinkedList<Handler> mHandlers;
354 
355     uint16_t        mEchoSequence;
356     otIcmp6EchoMode mEchoMode;
357 };
358 
359 /**
360  * @}
361  *
362  */
363 
364 } // namespace Ip6
365 
366 DefineCoreType(otIcmp6Header, Ip6::Icmp::Header);
367 DefineCoreType(otIcmp6Handler, Ip6::Icmp::Handler);
368 
369 } // namespace ot
370 
371 #endif // ICMP6_HPP_
372