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 IPv6 packet processing.
32  */
33 
34 #ifndef IP6_HPP_
35 #define IP6_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <stddef.h>
40 
41 #include <openthread/ip6.h>
42 #include <openthread/nat64.h>
43 #include <openthread/udp.h>
44 
45 #include "common/callback.hpp"
46 #include "common/encoding.hpp"
47 #include "common/frame_data.hpp"
48 #include "common/locator.hpp"
49 #include "common/log.hpp"
50 #include "common/message.hpp"
51 #include "common/non_copyable.hpp"
52 #include "common/owned_ptr.hpp"
53 #include "common/time_ticker.hpp"
54 #include "common/timer.hpp"
55 #include "net/icmp6.hpp"
56 #include "net/ip6_address.hpp"
57 #include "net/ip6_headers.hpp"
58 #include "net/ip6_mpl.hpp"
59 #include "net/ip6_types.hpp"
60 #include "net/netif.hpp"
61 #include "net/socket.hpp"
62 #include "net/tcp6.hpp"
63 #include "net/udp6.hpp"
64 
65 namespace ot {
66 
67 /**
68  * @namespace ot::Ip6
69  *
70  * @brief
71  *   This namespace includes definitions for IPv6 networking.
72  *
73  */
74 namespace Ip6 {
75 
76 /**
77  * @addtogroup core-ipv6
78  *
79  * @brief
80  *   This module includes definitions for the IPv6 network layer.
81  *
82  * @{
83  *
84  * @defgroup core-ip6-icmp6 ICMPv6
85  * @defgroup core-ip6-ip6 IPv6
86  * @defgroup core-ip6-mpl MPL
87  * @defgroup core-ip6-netif Network Interfaces
88  *
89  * @}
90  *
91  */
92 
93 /**
94  * @addtogroup core-ip6-ip6
95  *
96  * @brief
97  *   This module includes definitions for core IPv6 networking.
98  *
99  * @{
100  *
101  */
102 
103 /**
104  * Implements the core IPv6 message processing.
105  *
106  */
107 class Ip6 : public InstanceLocator, private NonCopyable
108 {
109     friend class ot::Instance;
110     friend class ot::TimeTicker;
111     friend class Mpl;
112 
113 public:
114     /**
115      * Initializes the object.
116      *
117      * @param[in]  aInstance   A reference to the otInstance object.
118      *
119      */
120     explicit Ip6(Instance &aInstance);
121 
122     /**
123      * Allocates a new message buffer from the buffer pool with default settings (link security
124      * enabled and `kPriorityMedium`).
125      *
126      * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
127      *
128      */
129     Message *NewMessage(void);
130 
131     /**
132      * Allocates a new message buffer from the buffer pool with default settings (link security
133      * enabled and `kPriorityMedium`).
134      *
135      * @param[in]  aReserved  The number of header bytes to reserve following the IPv6 header.
136      *
137      * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
138      *
139      */
140     Message *NewMessage(uint16_t aReserved);
141 
142     /**
143      * Allocates a new message buffer from the buffer pool.
144      *
145      * @param[in]  aReserved  The number of header bytes to reserve following the IPv6 header.
146      * @param[in]  aSettings  The message settings.
147      *
148      * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
149      *
150      */
151     Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings);
152 
153     /**
154      * Allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message.
155      *
156      * The message priority is always determined from IPv6 message itself (@p aData) and the priority included in
157      * @p aSetting is ignored.
158      *
159      * @param[in]  aData        A pointer to the IPv6 datagram buffer.
160      * @param[in]  aDataLength  The size of the IPV6 datagram buffer pointed by @p aData.
161      * @param[in]  aSettings    The message settings.
162      *
163      * @returns A pointer to the message or `nullptr` if malformed IPv6 header or insufficient message buffers are
164      *          available.
165      *
166      */
167     Message *NewMessageFromData(const uint8_t *aData, uint16_t aDataLength, const Message::Settings &aSettings);
168 
169     /**
170      * Converts the IPv6 DSCP value to message priority level.
171      *
172      * @param[in]  aDscp  The IPv6 DSCP value.
173      *
174      * @returns The message priority level.
175      *
176      */
177     static Message::Priority DscpToPriority(uint8_t aDscp);
178 
179     /**
180      * Sends an IPv6 datagram.
181      *
182      * @param[in]  aMessage      A reference to the message.
183      * @param[in]  aMessageInfo  A reference to the message info associated with @p aMessage.
184      * @param[in]  aIpProto      The Internet Protocol value.
185      *
186      * @retval kErrorNone     Successfully enqueued the message into an output interface.
187      * @retval kErrorNoBufs   Insufficient available buffer to add the IPv6 headers.
188      *
189      */
190     Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto);
191 
192     /**
193      * Sends a raw IPv6 datagram with a fully formed IPv6 header.
194      *
195      * @param[in]  aMessage   An owned pointer to a message (ownership is transferred to the method).
196      *
197      * @retval kErrorNone     Successfully processed the message.
198      * @retval kErrorDrop     Message was well-formed but not fully processed due to packet processing rules.
199      * @retval kErrorNoBufs   Could not allocate necessary message buffers when processing the datagram.
200      * @retval kErrorNoRoute  No route to host.
201      * @retval kErrorParse    Encountered a malformed header when processing the message.
202      *
203      */
204     Error SendRaw(OwnedPtr<Message> aMessage);
205 
206     /**
207      * Processes a received IPv6 datagram.
208      *
209      * @param[in]  aMessage          An owned pointer to a message.
210      *
211      * @retval kErrorNone     Successfully processed the message.
212      * @retval kErrorDrop     Message was well-formed but not fully processed due to packet processing rules.
213      * @retval kErrorNoBufs   Could not allocate necessary message buffers when processing the datagram.
214      * @retval kErrorNoRoute  No route to host.
215      * @retval kErrorParse    Encountered a malformed header when processing the message.
216      *
217      */
218     Error HandleDatagram(OwnedPtr<Message> aMessagePtr, bool aIsReassembled = false);
219 
220     /**
221      * Registers a callback to provide received raw IPv6 datagrams.
222      *
223      * By default, this callback does not pass Thread control traffic.  See SetReceiveIp6FilterEnabled() to change
224      * the Thread control traffic filter setting.
225      *
226      * @param[in]  aCallback         A pointer to a function that is called when an IPv6 datagram is received
227      *                               or `nullptr` to disable the callback.
228      * @param[in]  aCallbackContext  A pointer to application-specific context.
229      *
230      * @sa IsReceiveIp6FilterEnabled
231      * @sa SetReceiveIp6FilterEnabled
232      *
233      */
SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback,void * aCallbackContext)234     void SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback, void *aCallbackContext)
235     {
236         mReceiveIp6DatagramCallback.Set(aCallback, aCallbackContext);
237     }
238 
239 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
240     /**
241      * Registers a callback to provide received translated IPv4 datagrams.
242      *
243      * @param[in]  aCallback         A pointer to a function that is called when a translated IPv4 datagram is received
244      *                               or `nullptr` to disable the callback.
245      * @param[in]  aCallbackContext  A pointer to application-specific context.
246      *
247      * @sa SetReceiveDatagramCallback
248      *
249      */
SetNat64ReceiveIp4DatagramCallback(otNat64ReceiveIp4Callback aCallback,void * aCallbackContext)250     void SetNat64ReceiveIp4DatagramCallback(otNat64ReceiveIp4Callback aCallback, void *aCallbackContext)
251     {
252         mReceiveIp4DatagramCallback.Set(aCallback, aCallbackContext);
253     }
254 #endif
255 
256     /**
257      * Indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
258      * via the callback specified in SetReceiveIp6DatagramCallback().
259      *
260      * @returns  TRUE if Thread control traffic is filtered out, FALSE otherwise.
261      *
262      * @sa SetReceiveDatagramCallback
263      * @sa SetReceiveIp6FilterEnabled
264      *
265      */
IsReceiveIp6FilterEnabled(void) const266     bool IsReceiveIp6FilterEnabled(void) const { return mIsReceiveIp6FilterEnabled; }
267 
268     /**
269      * Sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
270      * via the callback specified in SetReceiveIp6DatagramCallback().
271      *
272      * @param[in]  aEnabled  TRUE if Thread control traffic is filtered out, FALSE otherwise.
273      *
274      * @sa SetReceiveDatagramCallback
275      * @sa IsReceiveIp6FilterEnabled
276      *
277      */
SetReceiveIp6FilterEnabled(bool aEnabled)278     void SetReceiveIp6FilterEnabled(bool aEnabled) { mIsReceiveIp6FilterEnabled = aEnabled; }
279 
280     /**
281      * Performs default source address selection.
282      *
283      * @param[in,out]  aMessageInfo  A reference to the message information.
284      *
285      * @retval  kErrorNone      Found a source address and updated SockAddr of @p aMessageInfo.
286      * @retval  kErrorNotFound  No source address was found and @p aMessageInfo is unchanged.
287      *
288      */
289     Error SelectSourceAddress(MessageInfo &aMessageInfo) const;
290 
291     /**
292      * Performs default source address selection.
293      *
294      * @param[in]  aDestination  The destination address.
295      *
296      * @returns A pointer to the selected IPv6 source address or `nullptr` if no source address was found.
297      *
298      */
299     const Address *SelectSourceAddress(const Address &aDestination) const;
300 
301     /**
302      * Returns a reference to the send queue.
303      *
304      * @returns A reference to the send queue.
305      *
306      */
GetSendQueue(void) const307     const PriorityQueue &GetSendQueue(void) const { return mSendQueue; }
308 
309     /**
310      * Converts an IP protocol number to a string.
311      *
312      * @param[in] aIpProto  An IP protocol number.
313      *
314      * @returns The string representation of @p aIpProto.
315      *
316      */
317     static const char *IpProtoToString(uint8_t aIpProto);
318 
319     /**
320      * Converts an IP header ECN value to a string.
321      *
322      * @param[in] aEcn   The 2-bit ECN value.
323      *
324      * @returns The string representation of @p aEcn.
325      *
326      */
327     static const char *EcnToString(Ecn aEcn);
328 
329 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
330     /**
331      * Returns a reference to the Border Routing counters.
332      *
333      * @returns A reference to the Border Routing counters.
334      *
335      */
GetBorderRoutingCounters(void) const336     const otBorderRoutingCounters &GetBorderRoutingCounters(void) const { return mBorderRoutingCounters; }
337 
338     /**
339      * Returns a reference to the Border Routing counters.
340      *
341      * @returns A reference to the Border Routing counters.
342      *
343      */
GetBorderRoutingCounters(void)344     otBorderRoutingCounters &GetBorderRoutingCounters(void) { return mBorderRoutingCounters; }
345 
346     /**
347      * Resets the Border Routing counters.
348      *
349      */
ResetBorderRoutingCounters(void)350     void ResetBorderRoutingCounters(void) { ClearAllBytes(mBorderRoutingCounters); }
351 #endif
352 
353 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
354 
355     /**
356      * Enables or disables the filter that drops TMF UDP messages from untrusted origin.
357      *
358      * @param[in]  aEnabled  TRUE to enable filter, FALSE otherwise.
359      *
360      */
SetTmfOriginFilterEnabled(bool aEnabled)361     void SetTmfOriginFilterEnabled(bool aEnabled) { mTmfOriginFilterEnabled = aEnabled; }
362 
363     /**
364      * Indicates whether the filter that drops TMF UDP messages from untrusted origin is enabled or not.
365      *
366      * @returns TRUE if the filter is enabled, FALSE otherwise.
367      *
368      */
IsTmfOriginFilterEnabled(void)369     bool IsTmfOriginFilterEnabled(void) { return mTmfOriginFilterEnabled; }
370 
371 #endif
372 
373 private:
374     static constexpr uint8_t kDefaultHopLimit      = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT;
375     static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT;
376 
377     static constexpr uint16_t kMinimalMtu = 1280;
378 
379     static uint8_t PriorityToDscp(Message::Priority aPriority);
380     static Error   TakeOrCopyMessagePtr(OwnedPtr<Message> &aTargetPtr,
381                                         OwnedPtr<Message> &aMessagePtr,
382                                         Message::Ownership aMessageOwnership);
383 
384     void  EnqueueDatagram(Message &aMessage);
385     void  HandleSendQueue(void);
386     Error PassToHost(OwnedPtr<Message> &aMessagePtr,
387                      const MessageInfo &aMessageInfo,
388                      uint8_t            aIpProto,
389                      bool               aApplyFilter,
390                      bool               aReceive,
391                      Message::Ownership aMessageOwnership);
392     Error HandleExtensionHeaders(OwnedPtr<Message> &aMessagePtr,
393                                  MessageInfo       &aMessageInfo,
394                                  Header            &aHeader,
395                                  uint8_t           &aNextHeader,
396                                  bool              &aReceive);
397     Error FragmentDatagram(Message &aMessage, uint8_t aIpProto);
398     Error HandleFragment(Message &aMessage);
399 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
400     void CleanupFragmentationBuffer(void);
401     void HandleTimeTick(void);
402     void UpdateReassemblyList(void);
403     void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode);
404 #endif
405     Error AddMplOption(Message &aMessage, Header &aHeader);
406     Error PrepareMulticastToLargerThanRealmLocal(Message &aMessage, const Header &aHeader);
407     Error InsertMplOption(Message &aMessage, Header &aHeader);
408     Error RemoveMplOption(Message &aMessage);
409     Error HandleOptions(Message &aMessage, Header &aHeader, bool &aReceive);
410     Error HandlePayload(Header            &aIp6Header,
411                         OwnedPtr<Message> &aMessagePtr,
412                         MessageInfo       &aMessageInfo,
413                         uint8_t            aIpProto,
414                         Message::Ownership aMessageOwnership);
415     bool  IsOnLink(const Address &aAddress) const;
416     Error RouteLookup(const Address &aSource, const Address &aDestination) const;
417 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
418     void UpdateBorderRoutingCounters(const Header &aHeader, uint16_t aMessageLength, bool aIsInbound);
419 #endif
420 
421     using SendQueueTask = TaskletIn<Ip6, &Ip6::HandleSendQueue>;
422 
423     bool mIsReceiveIp6FilterEnabled;
424 
425 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
426     bool mTmfOriginFilterEnabled : 1;
427 #endif
428 
429     Callback<otIp6ReceiveCallback> mReceiveIp6DatagramCallback;
430 
431 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
432     Callback<otNat64ReceiveIp4Callback> mReceiveIp4DatagramCallback;
433 #endif
434 
435     PriorityQueue mSendQueue;
436     SendQueueTask mSendQueueTask;
437 
438     Icmp mIcmp;
439     Udp  mUdp;
440     Mpl  mMpl;
441 
442 #if OPENTHREAD_CONFIG_TCP_ENABLE
443     Tcp mTcp;
444 #endif
445 
446 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
447     MessageQueue mReassemblyList;
448 #endif
449 
450 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
451     otBorderRoutingCounters mBorderRoutingCounters;
452 #endif
453 };
454 
455 /**
456  * Represents parsed IPv6 header along with UDP/TCP/ICMP6 headers from a received message/frame.
457  *
458  */
459 class Headers : private Clearable<Headers>
460 {
461     friend class Clearable<Headers>;
462 
463 public:
464     /**
465      * Parses the IPv6 and UDP/TCP/ICMP6 headers from a given message.
466      *
467      * @param[in] aMessage   The message to parse the headers from.
468      *
469      * @retval kErrorNone    The headers are parsed successfully.
470      * @retval kErrorParse   Failed to parse the headers.
471      *
472      */
473     Error ParseFrom(const Message &aMessage);
474 
475     /**
476      * Decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
477      *
478      * @param[in]  aMessage         The message from which to read the lowpan frame.
479      * @param[in]  aOffset          The offset in @p aMessage to start reading the frame.
480      * @param[in]  aMacAddrs        The MAC source and destination addresses.
481      *
482      * @retval kErrorNone           Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers.
483      * @retval kErrorNotFound       Lowpan frame is a next fragment and does not contain IPv6 headers.
484      * @retval kErrorParse          Failed to parse the headers.
485      *
486      */
487     Error DecompressFrom(const Message &aMessage, uint16_t aOffset, const Mac::Addresses &aMacAddrs);
488 
489     /**
490      * Decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
491      *
492      * @param[in]  aFrameData       The lowpan frame data.
493      * @param[in]  aMacAddrs        The MAC source and destination addresses.
494      * @param[in]  aInstance        The OpenThread instance.
495      *
496      * @retval kErrorNone           Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers.
497      * @retval kErrorNotFound       Lowpan frame is a next fragment and does not contain IPv6 headers.
498      * @retval kErrorParse          Failed to parse the headers.
499      *
500      */
501     Error DecompressFrom(const FrameData &aFrameData, const Mac::Addresses &aMacAddrs, Instance &aInstance);
502 
503     /**
504      * Returns the IPv6 header.
505      *
506      * @returns The IPv6 header.
507      *
508      */
GetIp6Header(void) const509     const Header &GetIp6Header(void) const { return mIp6Header; }
510 
511     /**
512      * Returns the IP protocol number from IPv6 Next Header field.
513      *
514      * @returns The IP protocol number.
515      *
516      */
GetIpProto(void) const517     uint8_t GetIpProto(void) const { return mIp6Header.GetNextHeader(); }
518 
519     /**
520      * Returns the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field from IPv6 header.
521      *
522      * @returns The ECN value.
523      *
524      */
GetEcn(void) const525     Ecn GetEcn(void) const { return mIp6Header.GetEcn(); }
526 
527     /**
528      * Indicates if the protocol number from IPv6 header is UDP.
529      *
530      * @retval TRUE   If the protocol number in IPv6 header is UDP.
531      * @retval FALSE  If the protocol number in IPv6 header is not UDP.
532      *
533      */
IsUdp(void) const534     bool IsUdp(void) const { return GetIpProto() == kProtoUdp; }
535 
536     /**
537      * Indicates if the protocol number from IPv6 header is TCP.
538      *
539      * @retval TRUE   If the protocol number in IPv6 header is TCP.
540      * @retval FALSE  If the protocol number in IPv6 header is not TCP.
541      *
542      */
IsTcp(void) const543     bool IsTcp(void) const { return GetIpProto() == kProtoTcp; }
544 
545     /**
546      * Indicates if the protocol number from IPv6 header is ICMPv6.
547      *
548      * @retval TRUE   If the protocol number in IPv6 header is ICMPv6.
549      * @retval FALSE  If the protocol number in IPv6 header is not ICMPv6.
550      *
551      */
IsIcmp6(void) const552     bool IsIcmp6(void) const { return GetIpProto() == kProtoIcmp6; }
553 
554     /**
555      * Returns the source IPv6 address from IPv6 header.
556      *
557      * @returns The source IPv6 address.
558      *
559      */
GetSourceAddress(void) const560     const Address &GetSourceAddress(void) const { return mIp6Header.GetSource(); }
561 
562     /**
563      * Returns the destination IPv6 address from IPv6 header.
564      *
565      * @returns The destination IPv6 address.
566      *
567      */
GetDestinationAddress(void) const568     const Address &GetDestinationAddress(void) const { return mIp6Header.GetDestination(); }
569 
570     /**
571      * Returns the UDP header.
572      *
573      * MUST be used when `IsUdp() == true`. Otherwise its behavior is undefined
574      *
575      * @returns The UDP header.
576      *
577      */
GetUdpHeader(void) const578     const Udp::Header &GetUdpHeader(void) const { return mHeader.mUdp; }
579 
580     /**
581      * Returns the TCP header.
582      *
583      * MUST be used when `IsTcp() == true`. Otherwise its behavior is undefined
584      *
585      * @returns The TCP header.
586      *
587      */
GetTcpHeader(void) const588     const Tcp::Header &GetTcpHeader(void) const { return mHeader.mTcp; }
589 
590     /**
591      * Returns the ICMPv6 header.
592      *
593      * MUST be used when `IsIcmp6() == true`. Otherwise its behavior is undefined
594      *
595      * @returns The ICMPv6 header.
596      *
597      */
GetIcmpHeader(void) const598     const Icmp::Header &GetIcmpHeader(void) const { return mHeader.mIcmp; }
599 
600     /**
601      * Returns the source port number if header is UDP or TCP, or zero otherwise
602      *
603      * @returns The source port number under UDP / TCP or zero.
604      *
605      */
606     uint16_t GetSourcePort(void) const;
607 
608     /**
609      * Returns the destination port number if header is UDP or TCP, or zero otherwise.
610      *
611      * @returns The destination port number under UDP / TCP or zero.
612      *
613      */
614     uint16_t GetDestinationPort(void) const;
615 
616     /**
617      * Returns the checksum values from corresponding UDP, TCP, or ICMPv6 header.
618      *
619      * @returns The checksum value.
620      *
621      */
622     uint16_t GetChecksum(void) const;
623 
624 private:
625     Header mIp6Header;
626     union
627     {
628         Udp::Header  mUdp;
629         Tcp::Header  mTcp;
630         Icmp::Header mIcmp;
631     } mHeader;
632 };
633 
634 /**
635  * @}
636  *
637  */
638 
639 } // namespace Ip6
640 } // namespace ot
641 
642 #endif // IP6_HPP_
643