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/time_ticker.hpp"
53 #include "common/timer.hpp"
54 #include "net/icmp6.hpp"
55 #include "net/ip6_address.hpp"
56 #include "net/ip6_headers.hpp"
57 #include "net/ip6_mpl.hpp"
58 #include "net/ip6_types.hpp"
59 #include "net/netif.hpp"
60 #include "net/socket.hpp"
61 #include "net/tcp6.hpp"
62 #include "net/udp6.hpp"
63 
64 namespace ot {
65 
66 /**
67  * @namespace ot::Ip6
68  *
69  * @brief
70  *   This namespace includes definitions for IPv6 networking.
71  *
72  */
73 namespace Ip6 {
74 
75 using ot::Encoding::BigEndian::HostSwap16;
76 using ot::Encoding::BigEndian::HostSwap32;
77 
78 /**
79  * @addtogroup core-ipv6
80  *
81  * @brief
82  *   This module includes definitions for the IPv6 network layer.
83  *
84  * @{
85  *
86  * @defgroup core-ip6-icmp6 ICMPv6
87  * @defgroup core-ip6-ip6 IPv6
88  * @defgroup core-ip6-mpl MPL
89  * @defgroup core-ip6-netif Network Interfaces
90  *
91  * @}
92  *
93  */
94 
95 /**
96  * @addtogroup core-ip6-ip6
97  *
98  * @brief
99  *   This module includes definitions for core IPv6 networking.
100  *
101  * @{
102  *
103  */
104 
105 /**
106  * Implements the core IPv6 message processing.
107  *
108  */
109 class Ip6 : public InstanceLocator, private NonCopyable
110 {
111     friend class ot::Instance;
112     friend class ot::TimeTicker;
113     friend class Mpl;
114 
115 public:
116     /**
117      * Represents an IPv6 message origin.
118      *
119      * In case the message is originating from host, it also indicates whether or not it is allowed to passed back the
120      * message to the host.
121      *
122      */
123     enum MessageOrigin : uint8_t
124     {
125         kFromThreadNetif,          ///< Message originates from Thread Netif.
126         kFromHostDisallowLoopBack, ///< Message originates from host and should not be passed back to host.
127         kFromHostAllowLoopBack,    ///< Message originates from host and can be passed back to host.
128     };
129 
130     /**
131      * Initializes the object.
132      *
133      * @param[in]  aInstance   A reference to the otInstance object.
134      *
135      */
136     explicit Ip6(Instance &aInstance);
137 
138     /**
139      * Allocates a new message buffer from the buffer pool with default settings (link security
140      * enabled and `kPriorityMedium`).
141      *
142      * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
143      *
144      */
145     Message *NewMessage(void);
146 
147     /**
148      * Allocates a new message buffer from the buffer pool with default settings (link security
149      * enabled and `kPriorityMedium`).
150      *
151      * @param[in]  aReserved  The number of header bytes to reserve following the IPv6 header.
152      *
153      * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
154      *
155      */
156     Message *NewMessage(uint16_t aReserved);
157 
158     /**
159      * Allocates a new message buffer from the buffer pool.
160      *
161      * @param[in]  aReserved  The number of header bytes to reserve following the IPv6 header.
162      * @param[in]  aSettings  The message settings.
163      *
164      * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
165      *
166      */
167     Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings);
168 
169     /**
170      * Allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message.
171      *
172      * The message priority is always determined from IPv6 message itself (@p aData) and the priority included in
173      * @p aSetting is ignored.
174      *
175      * @param[in]  aData        A pointer to the IPv6 datagram buffer.
176      * @param[in]  aDataLength  The size of the IPV6 datagram buffer pointed by @p aData.
177      * @param[in]  aSettings    The message settings.
178      *
179      * @returns A pointer to the message or `nullptr` if malformed IPv6 header or insufficient message buffers are
180      *          available.
181      *
182      */
183     Message *NewMessageFromData(const uint8_t *aData, uint16_t aDataLength, const Message::Settings &aSettings);
184 
185     /**
186      * Converts the IPv6 DSCP value to message priority level.
187      *
188      * @param[in]  aDscp  The IPv6 DSCP value.
189      *
190      * @returns The message priority level.
191      *
192      */
193     static Message::Priority DscpToPriority(uint8_t aDscp);
194 
195     /**
196      * Sends an IPv6 datagram.
197      *
198      * @param[in]  aMessage      A reference to the message.
199      * @param[in]  aMessageInfo  A reference to the message info associated with @p aMessage.
200      * @param[in]  aIpProto      The Internet Protocol value.
201      *
202      * @retval kErrorNone     Successfully enqueued the message into an output interface.
203      * @retval kErrorNoBufs   Insufficient available buffer to add the IPv6 headers.
204      *
205      */
206     Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto);
207 
208     /**
209      * Sends a raw IPv6 datagram with a fully formed IPv6 header.
210      *
211      * The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when
212      * processing is complete, including when a value other than `kErrorNone` is returned.
213      *
214      * @param[in]  aMessage               A reference to the message.
215      * @param[in]  aAllowLoopBackToHost   Indicate whether or not the message is allowed to be passed back to host.
216      *
217      * @retval kErrorNone     Successfully processed the message.
218      * @retval kErrorDrop     Message was well-formed but not fully processed due to packet processing rules.
219      * @retval kErrorNoBufs   Could not allocate necessary message buffers when processing the datagram.
220      * @retval kErrorNoRoute  No route to host.
221      * @retval kErrorParse    Encountered a malformed header when processing the message.
222      *
223      */
224     Error SendRaw(Message &aMessage, bool aAllowLoopBackToHost);
225 
226     /**
227      * Processes a received IPv6 datagram.
228      *
229      * @param[in]  aMessage          A reference to the message.
230      * @param[in]  aOrigin           The message oirgin.
231      * @param[in]  aLinkMessageInfo  A pointer to link-specific message information.
232      *
233      * @retval kErrorNone     Successfully processed the message.
234      * @retval kErrorDrop     Message was well-formed but not fully processed due to packet processing rules.
235      * @retval kErrorNoBufs   Could not allocate necessary message buffers when processing the datagram.
236      * @retval kErrorNoRoute  No route to host.
237      * @retval kErrorParse    Encountered a malformed header when processing the message.
238      *
239      */
240     Error HandleDatagram(Message      &aMessage,
241                          MessageOrigin aOrigin,
242                          const void   *aLinkMessageInfo = nullptr,
243                          bool          aIsReassembled   = false);
244 
245     /**
246      * Registers a callback to provide received raw IPv6 datagrams.
247      *
248      * By default, this callback does not pass Thread control traffic.  See SetReceiveIp6FilterEnabled() to change
249      * the Thread control traffic filter setting.
250      *
251      * @param[in]  aCallback         A pointer to a function that is called when an IPv6 datagram is received
252      *                               or `nullptr` to disable the callback.
253      * @param[in]  aCallbackContext  A pointer to application-specific context.
254      *
255      * @sa IsReceiveIp6FilterEnabled
256      * @sa SetReceiveIp6FilterEnabled
257      *
258      */
SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback,void * aCallbackContext)259     void SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback, void *aCallbackContext)
260     {
261         mReceiveIp6DatagramCallback.Set(aCallback, aCallbackContext);
262     }
263 
264 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
265     /**
266      * Registers a callback to provide received translated IPv4 datagrams.
267      *
268      * @param[in]  aCallback         A pointer to a function that is called when a translated IPv4 datagram is received
269      *                               or `nullptr` to disable the callback.
270      * @param[in]  aCallbackContext  A pointer to application-specific context.
271      *
272      * @sa SetReceiveDatagramCallback
273      *
274      */
SetNat64ReceiveIp4DatagramCallback(otNat64ReceiveIp4Callback aCallback,void * aCallbackContext)275     void SetNat64ReceiveIp4DatagramCallback(otNat64ReceiveIp4Callback aCallback, void *aCallbackContext)
276     {
277         mReceiveIp4DatagramCallback.Set(aCallback, aCallbackContext);
278     }
279 #endif
280 
281     /**
282      * Indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
283      * via the callback specified in SetReceiveIp6DatagramCallback().
284      *
285      * @returns  TRUE if Thread control traffic is filtered out, FALSE otherwise.
286      *
287      * @sa SetReceiveDatagramCallback
288      * @sa SetReceiveIp6FilterEnabled
289      *
290      */
IsReceiveIp6FilterEnabled(void) const291     bool IsReceiveIp6FilterEnabled(void) const { return mIsReceiveIp6FilterEnabled; }
292 
293     /**
294      * Sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
295      * via the callback specified in SetReceiveIp6DatagramCallback().
296      *
297      * @param[in]  aEnabled  TRUE if Thread control traffic is filtered out, FALSE otherwise.
298      *
299      * @sa SetReceiveDatagramCallback
300      * @sa IsReceiveIp6FilterEnabled
301      *
302      */
SetReceiveIp6FilterEnabled(bool aEnabled)303     void SetReceiveIp6FilterEnabled(bool aEnabled) { mIsReceiveIp6FilterEnabled = aEnabled; }
304 
305     /**
306      * Performs default source address selection.
307      *
308      * @param[in,out]  aMessageInfo  A reference to the message information.
309      *
310      * @retval  kErrorNone      Found a source address and updated SockAddr of @p aMessageInfo.
311      * @retval  kErrorNotFound  No source address was found and @p aMessageInfo is unchanged.
312      *
313      */
314     Error SelectSourceAddress(MessageInfo &aMessageInfo) const;
315 
316     /**
317      * Performs default source address selection.
318      *
319      * @param[in]  aDestination  The destination address.
320      *
321      * @returns A pointer to the selected IPv6 source address or `nullptr` if no source address was found.
322      *
323      */
324     const Address *SelectSourceAddress(const Address &aDestination) const;
325 
326     /**
327      * Returns a reference to the send queue.
328      *
329      * @returns A reference to the send queue.
330      *
331      */
GetSendQueue(void) const332     const PriorityQueue &GetSendQueue(void) const { return mSendQueue; }
333 
334     /**
335      * Converts an IP protocol number to a string.
336      *
337      * @param[in] aIpProto  An IP protocol number.
338      *
339      * @returns The string representation of @p aIpProto.
340      *
341      */
342     static const char *IpProtoToString(uint8_t aIpProto);
343 
344     /**
345      * Converts an IP header ECN value to a string.
346      *
347      * @param[in] aEcn   The 2-bit ECN value.
348      *
349      * @returns The string representation of @p aEcn.
350      *
351      */
352     static const char *EcnToString(Ecn aEcn);
353 
354 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
355     /**
356      * Returns a reference to the Border Routing counters.
357      *
358      * @returns A reference to the Border Routing counters.
359      *
360      */
GetBorderRoutingCounters(void) const361     const otBorderRoutingCounters &GetBorderRoutingCounters(void) const { return mBorderRoutingCounters; }
362 
363     /**
364      * Returns a reference to the Border Routing counters.
365      *
366      * @returns A reference to the Border Routing counters.
367      *
368      */
GetBorderRoutingCounters(void)369     otBorderRoutingCounters &GetBorderRoutingCounters(void) { return mBorderRoutingCounters; }
370 
371     /**
372      * Resets the Border Routing counters.
373      *
374      */
ResetBorderRoutingCounters(void)375     void ResetBorderRoutingCounters(void) { memset(&mBorderRoutingCounters, 0, sizeof(mBorderRoutingCounters)); }
376 #endif
377 
378 private:
379     static constexpr uint8_t kDefaultHopLimit      = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT;
380     static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT;
381 
382     static constexpr uint16_t kMinimalMtu = 1280;
383 
384     void HandleSendQueue(void);
385 
386     static uint8_t PriorityToDscp(Message::Priority aPriority);
387 
388     void  EnqueueDatagram(Message &aMessage);
389     Error PassToHost(Message           &aMessage,
390                      MessageOrigin      aOrigin,
391                      const MessageInfo &aMessageInfo,
392                      uint8_t            aIpProto,
393                      bool               aApplyFilter,
394                      Message::Ownership aMessageOwnership);
395     Error HandleExtensionHeaders(Message      &aMessage,
396                                  MessageOrigin aOrigin,
397                                  MessageInfo  &aMessageInfo,
398                                  Header       &aHeader,
399                                  uint8_t      &aNextHeader,
400                                  bool         &aReceive);
401     Error FragmentDatagram(Message &aMessage, uint8_t aIpProto);
402     Error HandleFragment(Message &aMessage, MessageOrigin aOrigin, MessageInfo &aMessageInfo);
403 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
404     void CleanupFragmentationBuffer(void);
405     void HandleTimeTick(void);
406     void UpdateReassemblyList(void);
407     void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode);
408 #endif
409     Error AddMplOption(Message &aMessage, Header &aHeader);
410     Error AddTunneledMplOption(Message &aMessage, Header &aHeader);
411     Error InsertMplOption(Message &aMessage, Header &aHeader);
412     Error RemoveMplOption(Message &aMessage);
413     Error HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive);
414     Error HandlePayload(Header            &aIp6Header,
415                         Message           &aMessage,
416                         MessageInfo       &aMessageInfo,
417                         uint8_t            aIpProto,
418                         Message::Ownership aMessageOwnership);
419     bool  IsOnLink(const Address &aAddress) const;
420     Error RouteLookup(const Address &aSource, const Address &aDestination) const;
421 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
422     void UpdateBorderRoutingCounters(const Header &aHeader, uint16_t aMessageLength, bool aIsInbound);
423 #endif
424 
425     using SendQueueTask = TaskletIn<Ip6, &Ip6::HandleSendQueue>;
426 
427     bool mIsReceiveIp6FilterEnabled;
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