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      * @param[in]  aLinkMessageInfo  A pointer to link-specific message information.
211      *
212      * @retval kErrorNone     Successfully processed the message.
213      * @retval kErrorDrop     Message was well-formed but not fully processed due to packet processing rules.
214      * @retval kErrorNoBufs   Could not allocate necessary message buffers when processing the datagram.
215      * @retval kErrorNoRoute  No route to host.
216      * @retval kErrorParse    Encountered a malformed header when processing the message.
217      *
218      */
219     Error HandleDatagram(OwnedPtr<Message> aMessagePtr,
220                          const void       *aLinkMessageInfo = nullptr,
221                          bool              aIsReassembled   = false);
222 
223     /**
224      * Registers a callback to provide received raw IPv6 datagrams.
225      *
226      * By default, this callback does not pass Thread control traffic.  See SetReceiveIp6FilterEnabled() to change
227      * the Thread control traffic filter setting.
228      *
229      * @param[in]  aCallback         A pointer to a function that is called when an IPv6 datagram is received
230      *                               or `nullptr` to disable the callback.
231      * @param[in]  aCallbackContext  A pointer to application-specific context.
232      *
233      * @sa IsReceiveIp6FilterEnabled
234      * @sa SetReceiveIp6FilterEnabled
235      *
236      */
SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback,void * aCallbackContext)237     void SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback, void *aCallbackContext)
238     {
239         mReceiveIp6DatagramCallback.Set(aCallback, aCallbackContext);
240     }
241 
242 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
243     /**
244      * Registers a callback to provide received translated IPv4 datagrams.
245      *
246      * @param[in]  aCallback         A pointer to a function that is called when a translated IPv4 datagram is received
247      *                               or `nullptr` to disable the callback.
248      * @param[in]  aCallbackContext  A pointer to application-specific context.
249      *
250      * @sa SetReceiveDatagramCallback
251      *
252      */
SetNat64ReceiveIp4DatagramCallback(otNat64ReceiveIp4Callback aCallback,void * aCallbackContext)253     void SetNat64ReceiveIp4DatagramCallback(otNat64ReceiveIp4Callback aCallback, void *aCallbackContext)
254     {
255         mReceiveIp4DatagramCallback.Set(aCallback, aCallbackContext);
256     }
257 #endif
258 
259     /**
260      * Indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
261      * via the callback specified in SetReceiveIp6DatagramCallback().
262      *
263      * @returns  TRUE if Thread control traffic is filtered out, FALSE otherwise.
264      *
265      * @sa SetReceiveDatagramCallback
266      * @sa SetReceiveIp6FilterEnabled
267      *
268      */
IsReceiveIp6FilterEnabled(void) const269     bool IsReceiveIp6FilterEnabled(void) const { return mIsReceiveIp6FilterEnabled; }
270 
271     /**
272      * Sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
273      * via the callback specified in SetReceiveIp6DatagramCallback().
274      *
275      * @param[in]  aEnabled  TRUE if Thread control traffic is filtered out, FALSE otherwise.
276      *
277      * @sa SetReceiveDatagramCallback
278      * @sa IsReceiveIp6FilterEnabled
279      *
280      */
SetReceiveIp6FilterEnabled(bool aEnabled)281     void SetReceiveIp6FilterEnabled(bool aEnabled) { mIsReceiveIp6FilterEnabled = aEnabled; }
282 
283     /**
284      * Performs default source address selection.
285      *
286      * @param[in,out]  aMessageInfo  A reference to the message information.
287      *
288      * @retval  kErrorNone      Found a source address and updated SockAddr of @p aMessageInfo.
289      * @retval  kErrorNotFound  No source address was found and @p aMessageInfo is unchanged.
290      *
291      */
292     Error SelectSourceAddress(MessageInfo &aMessageInfo) const;
293 
294     /**
295      * Performs default source address selection.
296      *
297      * @param[in]  aDestination  The destination address.
298      *
299      * @returns A pointer to the selected IPv6 source address or `nullptr` if no source address was found.
300      *
301      */
302     const Address *SelectSourceAddress(const Address &aDestination) const;
303 
304     /**
305      * Returns a reference to the send queue.
306      *
307      * @returns A reference to the send queue.
308      *
309      */
GetSendQueue(void) const310     const PriorityQueue &GetSendQueue(void) const { return mSendQueue; }
311 
312     /**
313      * Converts an IP protocol number to a string.
314      *
315      * @param[in] aIpProto  An IP protocol number.
316      *
317      * @returns The string representation of @p aIpProto.
318      *
319      */
320     static const char *IpProtoToString(uint8_t aIpProto);
321 
322     /**
323      * Converts an IP header ECN value to a string.
324      *
325      * @param[in] aEcn   The 2-bit ECN value.
326      *
327      * @returns The string representation of @p aEcn.
328      *
329      */
330     static const char *EcnToString(Ecn aEcn);
331 
332 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
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 otBorderRoutingCounters &GetBorderRoutingCounters(void) const { return mBorderRoutingCounters; }
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     otBorderRoutingCounters &GetBorderRoutingCounters(void) { return mBorderRoutingCounters; }
348 
349     /**
350      * Resets the Border Routing counters.
351      *
352      */
ResetBorderRoutingCounters(void)353     void ResetBorderRoutingCounters(void) { memset(&mBorderRoutingCounters, 0, sizeof(mBorderRoutingCounters)); }
354 #endif
355 
356 private:
357     static constexpr uint8_t kDefaultHopLimit      = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT;
358     static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT;
359 
360     static constexpr uint16_t kMinimalMtu = 1280;
361 
362     static uint8_t PriorityToDscp(Message::Priority aPriority);
363     static Error   TakeOrCopyMessagePtr(OwnedPtr<Message> &aTargetPtr,
364                                         OwnedPtr<Message> &aMessagePtr,
365                                         Message::Ownership aMessageOwnership);
366 
367     void  EnqueueDatagram(Message &aMessage);
368     void  HandleSendQueue(void);
369     Error PassToHost(OwnedPtr<Message> &aMessagePtr,
370                      const MessageInfo &aMessageInfo,
371                      uint8_t            aIpProto,
372                      bool               aApplyFilter,
373                      bool               aReceive,
374                      Message::Ownership aMessageOwnership);
375     Error HandleExtensionHeaders(OwnedPtr<Message> &aMessagePtr,
376                                  MessageInfo       &aMessageInfo,
377                                  Header            &aHeader,
378                                  uint8_t           &aNextHeader,
379                                  bool              &aReceive);
380     Error FragmentDatagram(Message &aMessage, uint8_t aIpProto);
381     Error HandleFragment(Message &aMessage, MessageInfo &aMessageInfo);
382 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
383     void CleanupFragmentationBuffer(void);
384     void HandleTimeTick(void);
385     void UpdateReassemblyList(void);
386     void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode);
387 #endif
388     Error AddMplOption(Message &aMessage, Header &aHeader);
389     Error PrepareMulticastToLargerThanRealmLocal(Message &aMessage, const Header &aHeader);
390     Error InsertMplOption(Message &aMessage, Header &aHeader);
391     Error RemoveMplOption(Message &aMessage);
392     Error HandleOptions(Message &aMessage, Header &aHeader, bool &aReceive);
393     Error HandlePayload(Header            &aIp6Header,
394                         OwnedPtr<Message> &aMessagePtr,
395                         MessageInfo       &aMessageInfo,
396                         uint8_t            aIpProto,
397                         Message::Ownership aMessageOwnership);
398     bool  IsOnLink(const Address &aAddress) const;
399     Error RouteLookup(const Address &aSource, const Address &aDestination) const;
400 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
401     void UpdateBorderRoutingCounters(const Header &aHeader, uint16_t aMessageLength, bool aIsInbound);
402 #endif
403 
404     using SendQueueTask = TaskletIn<Ip6, &Ip6::HandleSendQueue>;
405 
406     bool mIsReceiveIp6FilterEnabled;
407 
408     Callback<otIp6ReceiveCallback> mReceiveIp6DatagramCallback;
409 
410 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
411     Callback<otNat64ReceiveIp4Callback> mReceiveIp4DatagramCallback;
412 #endif
413 
414     PriorityQueue mSendQueue;
415     SendQueueTask mSendQueueTask;
416 
417     Icmp mIcmp;
418     Udp  mUdp;
419     Mpl  mMpl;
420 
421 #if OPENTHREAD_CONFIG_TCP_ENABLE
422     Tcp mTcp;
423 #endif
424 
425 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
426     MessageQueue mReassemblyList;
427 #endif
428 
429 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
430     otBorderRoutingCounters mBorderRoutingCounters;
431 #endif
432 };
433 
434 /**
435  * Represents parsed IPv6 header along with UDP/TCP/ICMP6 headers from a received message/frame.
436  *
437  */
438 class Headers : private Clearable<Headers>
439 {
440     friend class Clearable<Headers>;
441 
442 public:
443     /**
444      * Parses the IPv6 and UDP/TCP/ICMP6 headers from a given message.
445      *
446      * @param[in] aMessage   The message to parse the headers from.
447      *
448      * @retval kErrorNone    The headers are parsed successfully.
449      * @retval kErrorParse   Failed to parse the headers.
450      *
451      */
452     Error ParseFrom(const Message &aMessage);
453 
454     /**
455      * Decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
456      *
457      * @param[in]  aMessage         The message from which to read the lowpan frame.
458      * @param[in]  aOffset          The offset in @p aMessage to start reading the frame.
459      * @param[in]  aMacAddrs        The MAC source and destination addresses.
460      *
461      * @retval kErrorNone           Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers.
462      * @retval kErrorNotFound       Lowpan frame is a next fragment and does not contain IPv6 headers.
463      * @retval kErrorParse          Failed to parse the headers.
464      *
465      */
466     Error DecompressFrom(const Message &aMessage, uint16_t aOffset, const Mac::Addresses &aMacAddrs);
467 
468     /**
469      * Decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
470      *
471      * @param[in]  aFrameData       The lowpan frame data.
472      * @param[in]  aMacAddrs        The MAC source and destination addresses.
473      * @param[in]  aInstance        The OpenThread instance.
474      *
475      * @retval kErrorNone           Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers.
476      * @retval kErrorNotFound       Lowpan frame is a next fragment and does not contain IPv6 headers.
477      * @retval kErrorParse          Failed to parse the headers.
478      *
479      */
480     Error DecompressFrom(const FrameData &aFrameData, const Mac::Addresses &aMacAddrs, Instance &aInstance);
481 
482     /**
483      * Returns the IPv6 header.
484      *
485      * @returns The IPv6 header.
486      *
487      */
GetIp6Header(void) const488     const Header &GetIp6Header(void) const { return mIp6Header; }
489 
490     /**
491      * Returns the IP protocol number from IPv6 Next Header field.
492      *
493      * @returns The IP protocol number.
494      *
495      */
GetIpProto(void) const496     uint8_t GetIpProto(void) const { return mIp6Header.GetNextHeader(); }
497 
498     /**
499      * Returns the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field from IPv6 header.
500      *
501      * @returns The ECN value.
502      *
503      */
GetEcn(void) const504     Ecn GetEcn(void) const { return mIp6Header.GetEcn(); }
505 
506     /**
507      * Indicates if the protocol number from IPv6 header is UDP.
508      *
509      * @retval TRUE   If the protocol number in IPv6 header is UDP.
510      * @retval FALSE  If the protocol number in IPv6 header is not UDP.
511      *
512      */
IsUdp(void) const513     bool IsUdp(void) const { return GetIpProto() == kProtoUdp; }
514 
515     /**
516      * Indicates if the protocol number from IPv6 header is TCP.
517      *
518      * @retval TRUE   If the protocol number in IPv6 header is TCP.
519      * @retval FALSE  If the protocol number in IPv6 header is not TCP.
520      *
521      */
IsTcp(void) const522     bool IsTcp(void) const { return GetIpProto() == kProtoTcp; }
523 
524     /**
525      * Indicates if the protocol number from IPv6 header is ICMPv6.
526      *
527      * @retval TRUE   If the protocol number in IPv6 header is ICMPv6.
528      * @retval FALSE  If the protocol number in IPv6 header is not ICMPv6.
529      *
530      */
IsIcmp6(void) const531     bool IsIcmp6(void) const { return GetIpProto() == kProtoIcmp6; }
532 
533     /**
534      * Returns the source IPv6 address from IPv6 header.
535      *
536      * @returns The source IPv6 address.
537      *
538      */
GetSourceAddress(void) const539     const Address &GetSourceAddress(void) const { return mIp6Header.GetSource(); }
540 
541     /**
542      * Returns the destination IPv6 address from IPv6 header.
543      *
544      * @returns The destination IPv6 address.
545      *
546      */
GetDestinationAddress(void) const547     const Address &GetDestinationAddress(void) const { return mIp6Header.GetDestination(); }
548 
549     /**
550      * Returns the UDP header.
551      *
552      * MUST be used when `IsUdp() == true`. Otherwise its behavior is undefined
553      *
554      * @returns The UDP header.
555      *
556      */
GetUdpHeader(void) const557     const Udp::Header &GetUdpHeader(void) const { return mHeader.mUdp; }
558 
559     /**
560      * Returns the TCP header.
561      *
562      * MUST be used when `IsTcp() == true`. Otherwise its behavior is undefined
563      *
564      * @returns The TCP header.
565      *
566      */
GetTcpHeader(void) const567     const Tcp::Header &GetTcpHeader(void) const { return mHeader.mTcp; }
568 
569     /**
570      * Returns the ICMPv6 header.
571      *
572      * MUST be used when `IsIcmp6() == true`. Otherwise its behavior is undefined
573      *
574      * @returns The ICMPv6 header.
575      *
576      */
GetIcmpHeader(void) const577     const Icmp::Header &GetIcmpHeader(void) const { return mHeader.mIcmp; }
578 
579     /**
580      * Returns the source port number if header is UDP or TCP, or zero otherwise
581      *
582      * @returns The source port number under UDP / TCP or zero.
583      *
584      */
585     uint16_t GetSourcePort(void) const;
586 
587     /**
588      * Returns the destination port number if header is UDP or TCP, or zero otherwise.
589      *
590      * @returns The destination port number under UDP / TCP or zero.
591      *
592      */
593     uint16_t GetDestinationPort(void) const;
594 
595     /**
596      * Returns the checksum values from corresponding UDP, TCP, or ICMPv6 header.
597      *
598      * @returns The checksum value.
599      *
600      */
601     uint16_t GetChecksum(void) const;
602 
603 private:
604     Header mIp6Header;
605     union
606     {
607         Udp::Header  mUdp;
608         Tcp::Header  mTcp;
609         Icmp::Header mIcmp;
610     } mHeader;
611 };
612 
613 /**
614  * @}
615  *
616  */
617 
618 } // namespace Ip6
619 } // namespace ot
620 
621 #endif // IP6_HPP_
622