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     typedef otBorderRoutingCounters BrCounters; ///< Border Routing counters.
332 
333     /**
334      * Returns a reference to the Border Routing counters.
335      *
336      * @returns A reference to the Border Routing counters.
337      *
338      */
GetBorderRoutingCounters(void) const339     const BrCounters &GetBorderRoutingCounters(void) const { return mBrCounters; }
340 
341     /**
342      * Returns a reference to the Border Routing counters.
343      *
344      * @returns A reference to the Border Routing counters.
345      *
346      */
GetBorderRoutingCounters(void)347     BrCounters &GetBorderRoutingCounters(void) { return mBrCounters; }
348 
349     /**
350      * Resets the Border Routing counters.
351      *
352      */
ResetBorderRoutingCounters(void)353     void ResetBorderRoutingCounters(void) { ClearAllBytes(mBrCounters); }
354 
355 #endif // OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
356 
357 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
358 
359     /**
360      * Enables or disables the filter that drops TMF UDP messages from untrusted origin.
361      *
362      * @param[in]  aEnabled  TRUE to enable filter, FALSE otherwise.
363      *
364      */
SetTmfOriginFilterEnabled(bool aEnabled)365     void SetTmfOriginFilterEnabled(bool aEnabled) { mTmfOriginFilterEnabled = aEnabled; }
366 
367     /**
368      * Indicates whether the filter that drops TMF UDP messages from untrusted origin is enabled or not.
369      *
370      * @returns TRUE if the filter is enabled, FALSE otherwise.
371      *
372      */
IsTmfOriginFilterEnabled(void)373     bool IsTmfOriginFilterEnabled(void) { return mTmfOriginFilterEnabled; }
374 
375 #endif
376 
377 private:
378     static constexpr uint8_t kDefaultHopLimit      = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT;
379     static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT;
380 
381     static constexpr uint16_t kMinimalMtu = 1280;
382 
383     static uint8_t PriorityToDscp(Message::Priority aPriority);
384     static Error   TakeOrCopyMessagePtr(OwnedPtr<Message> &aTargetPtr,
385                                         OwnedPtr<Message> &aMessagePtr,
386                                         Message::Ownership aMessageOwnership);
387 
388     void  EnqueueDatagram(Message &aMessage);
389     void  HandleSendQueue(void);
390     Error PassToHost(OwnedPtr<Message> &aMessagePtr,
391                      const Header      &aHeader,
392                      uint8_t            aIpProto,
393                      bool               aReceive,
394                      Message::Ownership aMessageOwnership);
395     Error HandleExtensionHeaders(OwnedPtr<Message> &aMessagePtr,
396                                  const Header      &aHeader,
397                                  uint8_t           &aNextHeader,
398                                  bool              &aReceive);
399     Error FragmentDatagram(Message &aMessage, uint8_t aIpProto);
400     Error HandleFragment(Message &aMessage);
401 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
402     void CleanupFragmentationBuffer(void);
403     void HandleTimeTick(void);
404     void UpdateReassemblyList(void);
405     void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode);
406 #endif
407     Error ReadHopByHopHeader(const Message &aMessage, OffsetRange &aOffsetRange, HopByHopHeader &aHbhHeader) const;
408     Error AddMplOption(Message &aMessage, Header &aHeader);
409     Error PrepareMulticastToLargerThanRealmLocal(Message &aMessage, const Header &aHeader);
410     Error InsertMplOption(Message &aMessage, Header &aHeader);
411     Error RemoveMplOption(Message &aMessage);
412     Error HandleOptions(Message &aMessage, const Header &aHeader, bool &aReceive);
413     Error Receive(Header            &aIp6Header,
414                   OwnedPtr<Message> &aMessagePtr,
415                   uint8_t            aIpProto,
416                   Message::Ownership aMessageOwnership);
417     bool  IsOnLink(const Address &aAddress) const;
418     Error RouteLookup(const Address &aSource, const Address &aDestination) const;
419 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
420     void UpdateBorderRoutingCounters(const Header &aHeader, uint16_t aMessageLength, bool aIsInbound);
421 #endif
422 
423     using SendQueueTask = TaskletIn<Ip6, &Ip6::HandleSendQueue>;
424 
425     bool mIsReceiveIp6FilterEnabled;
426 
427 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
428     bool mTmfOriginFilterEnabled : 1;
429 #endif
430 
431     Callback<otIp6ReceiveCallback> mReceiveIp6DatagramCallback;
432 
433 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
434     Callback<otNat64ReceiveIp4Callback> mReceiveIp4DatagramCallback;
435 #endif
436 
437     PriorityQueue mSendQueue;
438     SendQueueTask mSendQueueTask;
439 
440     Icmp mIcmp;
441     Udp  mUdp;
442     Mpl  mMpl;
443 
444 #if OPENTHREAD_CONFIG_TCP_ENABLE
445     Tcp mTcp;
446 #endif
447 
448 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
449     MessageQueue mReassemblyList;
450 #endif
451 
452 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
453     BrCounters mBrCounters;
454 #endif
455 };
456 
457 /**
458  * Represents parsed IPv6 header along with UDP/TCP/ICMP6 headers from a received message/frame.
459  *
460  */
461 class Headers : private Clearable<Headers>
462 {
463     friend class Clearable<Headers>;
464 
465 public:
466     /**
467      * Parses the IPv6 and UDP/TCP/ICMP6 headers from a given message.
468      *
469      * @param[in] aMessage   The message to parse the headers from.
470      *
471      * @retval kErrorNone    The headers are parsed successfully.
472      * @retval kErrorParse   Failed to parse the headers.
473      *
474      */
475     Error ParseFrom(const Message &aMessage);
476 
477     /**
478      * Decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
479      *
480      * @param[in]  aMessage         The message from which to read the lowpan frame.
481      * @param[in]  aOffset          The offset in @p aMessage to start reading the frame.
482      * @param[in]  aMacAddrs        The MAC source and destination addresses.
483      *
484      * @retval kErrorNone           Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers.
485      * @retval kErrorNotFound       Lowpan frame is a next fragment and does not contain IPv6 headers.
486      * @retval kErrorParse          Failed to parse the headers.
487      *
488      */
489     Error DecompressFrom(const Message &aMessage, uint16_t aOffset, const Mac::Addresses &aMacAddrs);
490 
491     /**
492      * Decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
493      *
494      * @param[in]  aFrameData       The lowpan frame data.
495      * @param[in]  aMacAddrs        The MAC source and destination addresses.
496      * @param[in]  aInstance        The OpenThread instance.
497      *
498      * @retval kErrorNone           Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers.
499      * @retval kErrorNotFound       Lowpan frame is a next fragment and does not contain IPv6 headers.
500      * @retval kErrorParse          Failed to parse the headers.
501      *
502      */
503     Error DecompressFrom(const FrameData &aFrameData, const Mac::Addresses &aMacAddrs, Instance &aInstance);
504 
505     /**
506      * Returns the IPv6 header.
507      *
508      * @returns The IPv6 header.
509      *
510      */
GetIp6Header(void) const511     const Header &GetIp6Header(void) const { return mIp6Header; }
512 
513     /**
514      * Returns the IP protocol number from IPv6 Next Header field.
515      *
516      * @returns The IP protocol number.
517      *
518      */
GetIpProto(void) const519     uint8_t GetIpProto(void) const { return mIp6Header.GetNextHeader(); }
520 
521     /**
522      * Returns the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field from IPv6 header.
523      *
524      * @returns The ECN value.
525      *
526      */
GetEcn(void) const527     Ecn GetEcn(void) const { return mIp6Header.GetEcn(); }
528 
529     /**
530      * Indicates if the protocol number from IPv6 header is UDP.
531      *
532      * @retval TRUE   If the protocol number in IPv6 header is UDP.
533      * @retval FALSE  If the protocol number in IPv6 header is not UDP.
534      *
535      */
IsUdp(void) const536     bool IsUdp(void) const { return GetIpProto() == kProtoUdp; }
537 
538     /**
539      * Indicates if the protocol number from IPv6 header is TCP.
540      *
541      * @retval TRUE   If the protocol number in IPv6 header is TCP.
542      * @retval FALSE  If the protocol number in IPv6 header is not TCP.
543      *
544      */
IsTcp(void) const545     bool IsTcp(void) const { return GetIpProto() == kProtoTcp; }
546 
547     /**
548      * Indicates if the protocol number from IPv6 header is ICMPv6.
549      *
550      * @retval TRUE   If the protocol number in IPv6 header is ICMPv6.
551      * @retval FALSE  If the protocol number in IPv6 header is not ICMPv6.
552      *
553      */
IsIcmp6(void) const554     bool IsIcmp6(void) const { return GetIpProto() == kProtoIcmp6; }
555 
556     /**
557      * Returns the source IPv6 address from IPv6 header.
558      *
559      * @returns The source IPv6 address.
560      *
561      */
GetSourceAddress(void) const562     const Address &GetSourceAddress(void) const { return mIp6Header.GetSource(); }
563 
564     /**
565      * Returns the destination IPv6 address from IPv6 header.
566      *
567      * @returns The destination IPv6 address.
568      *
569      */
GetDestinationAddress(void) const570     const Address &GetDestinationAddress(void) const { return mIp6Header.GetDestination(); }
571 
572     /**
573      * Returns the UDP header.
574      *
575      * MUST be used when `IsUdp() == true`. Otherwise its behavior is undefined
576      *
577      * @returns The UDP header.
578      *
579      */
GetUdpHeader(void) const580     const Udp::Header &GetUdpHeader(void) const { return mHeader.mUdp; }
581 
582     /**
583      * Returns the TCP header.
584      *
585      * MUST be used when `IsTcp() == true`. Otherwise its behavior is undefined
586      *
587      * @returns The TCP header.
588      *
589      */
GetTcpHeader(void) const590     const Tcp::Header &GetTcpHeader(void) const { return mHeader.mTcp; }
591 
592     /**
593      * Returns the ICMPv6 header.
594      *
595      * MUST be used when `IsIcmp6() == true`. Otherwise its behavior is undefined
596      *
597      * @returns The ICMPv6 header.
598      *
599      */
GetIcmpHeader(void) const600     const Icmp::Header &GetIcmpHeader(void) const { return mHeader.mIcmp; }
601 
602     /**
603      * Returns the source port number if header is UDP or TCP, or zero otherwise
604      *
605      * @returns The source port number under UDP / TCP or zero.
606      *
607      */
608     uint16_t GetSourcePort(void) const;
609 
610     /**
611      * Returns the destination port number if header is UDP or TCP, or zero otherwise.
612      *
613      * @returns The destination port number under UDP / TCP or zero.
614      *
615      */
616     uint16_t GetDestinationPort(void) const;
617 
618     /**
619      * Returns the checksum values from corresponding UDP, TCP, or ICMPv6 header.
620      *
621      * @returns The checksum value.
622      *
623      */
624     uint16_t GetChecksum(void) const;
625 
626 private:
627     Header mIp6Header;
628     union
629     {
630         Udp::Header  mUdp;
631         Tcp::Header  mTcp;
632         Icmp::Header mIcmp;
633     } mHeader;
634 };
635 
636 /**
637  * @}
638  *
639  */
640 
641 } // namespace Ip6
642 } // namespace ot
643 
644 #endif // IP6_HPP_
645