• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for 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/udp.h>
43 
44 #include "common/encoding.hpp"
45 #include "common/frame_data.hpp"
46 #include "common/locator.hpp"
47 #include "common/log.hpp"
48 #include "common/message.hpp"
49 #include "common/non_copyable.hpp"
50 #include "common/time_ticker.hpp"
51 #include "common/timer.hpp"
52 #include "net/icmp6.hpp"
53 #include "net/ip6_address.hpp"
54 #include "net/ip6_headers.hpp"
55 #include "net/ip6_mpl.hpp"
56 #include "net/ip6_types.hpp"
57 #include "net/netif.hpp"
58 #include "net/socket.hpp"
59 #include "net/tcp6.hpp"
60 #include "net/udp6.hpp"
61 
62 namespace ot {
63 
64 /**
65  * @namespace ot::Ip6
66  *
67  * @brief
68  *   This namespace includes definitions for IPv6 networking.
69  *
70  */
71 namespace Ip6 {
72 
73 using ot::Encoding::BigEndian::HostSwap16;
74 using ot::Encoding::BigEndian::HostSwap32;
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  * This class 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      * This constructor initializes the object.
116      *
117      * @param[in]  aInstance   A reference to the otInstance object.
118      *
119      */
120     explicit Ip6(Instance &aInstance);
121 
122     /**
123      * This method allocates a new message buffer from the buffer pool.
124      *
125      * @param[in]  aReserved  The number of header bytes to reserve following the IPv6 header.
126      * @param[in]  aSettings  The message settings.
127      *
128      * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
129      *
130      */
131     Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
132 
133     /**
134      * This method allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message.
135      *
136      * @param[in]  aData        A pointer to the IPv6 datagram buffer.
137      * @param[in]  aDataLength  The size of the IPV6 datagram buffer pointed by @p aData.
138      * @param[in]  aSettings    The message settings.
139      *
140      * @returns A pointer to the message or `nullptr` if malformed IPv6 header or insufficient message buffers are
141      * available.
142      *
143      */
144     Message *NewMessage(const uint8_t *aData, uint16_t aDataLength, const Message::Settings &aSettings);
145 
146     /**
147      * This method allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message.
148      *
149      * @note The link layer security is enabled and the message priority is obtained from IPv6 message itself.
150      *
151      * @param[in]  aData        A pointer to the IPv6 datagram buffer.
152      * @param[in]  aDataLength  The size of the IPV6 datagram buffer pointed by @p aData.
153      *
154      * @returns A pointer to the message or `nullptr` if malformed IPv6 header or insufficient message buffers are
155      * available.
156      *
157      */
158     Message *NewMessage(const uint8_t *aData, uint16_t aDataLength);
159 
160     /**
161      * This method converts the IPv6 DSCP value to message priority level.
162      *
163      * @param[in]  aDscp  The IPv6 DSCP value.
164      *
165      * @returns The message priority level.
166      *
167      */
168     static Message::Priority DscpToPriority(uint8_t aDscp);
169 
170     /**
171      * This method sends an IPv6 datagram.
172      *
173      * @param[in]  aMessage      A reference to the message.
174      * @param[in]  aMessageInfo  A reference to the message info associated with @p aMessage.
175      * @param[in]  aIpProto      The Internet Protocol value.
176      *
177      * @retval kErrorNone     Successfully enqueued the message into an output interface.
178      * @retval kErrorNoBufs   Insufficient available buffer to add the IPv6 headers.
179      *
180      */
181     Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto);
182 
183     /**
184      * This method sends a raw IPv6 datagram with a fully formed IPv6 header.
185      *
186      * The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when
187      * processing is complete, including when a value other than `kErrorNone` is returned.
188      *
189      * @param[in]  aMessage          A reference to the message.
190      * @param[in]  aFromHost         TRUE if the message is originated from the host, FALSE otherwise.
191      *
192      * @retval kErrorNone     Successfully processed the message.
193      * @retval kErrorDrop     Message was well-formed but not fully processed due to packet processing rules.
194      * @retval kErrorNoBufs   Could not allocate necessary message buffers when processing the datagram.
195      * @retval kErrorNoRoute  No route to host.
196      * @retval kErrorParse    Encountered a malformed header when processing the message.
197      *
198      */
199     Error SendRaw(Message &aMessage, bool aFromHost);
200 
201     /**
202      * This method processes a received IPv6 datagram.
203      *
204      * @param[in]  aMessage          A reference to the message.
205      * @param[in]  aNetif            A pointer to the network interface that received the message.
206      * @param[in]  aLinkMessageInfo  A pointer to link-specific message information.
207      * @param[in]  aFromHost         TRUE if the message is originated from the host, FALSE otherwise.
208      *
209      * @retval kErrorNone     Successfully processed the message.
210      * @retval kErrorDrop     Message was well-formed but not fully processed due to packet processing rules.
211      * @retval kErrorNoBufs   Could not allocate necessary message buffers when processing the datagram.
212      * @retval kErrorNoRoute  No route to host.
213      * @retval kErrorParse    Encountered a malformed header when processing the message.
214      *
215      */
216     Error HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromHost);
217 
218     /**
219      * This method registers a callback to provide received raw IPv6 datagrams.
220      *
221      * By default, this callback does not pass Thread control traffic.  See SetReceiveIp6FilterEnabled() to change
222      * the Thread control traffic filter setting.
223      *
224      * @param[in]  aCallback         A pointer to a function that is called when an IPv6 datagram is received
225      *                               or `nullptr` to disable the callback.
226      * @param[in]  aCallbackContext  A pointer to application-specific context.
227      *
228      * @sa IsReceiveIp6FilterEnabled
229      * @sa SetReceiveIp6FilterEnabled
230      *
231      */
232     void SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback, void *aCallbackContext);
233 
234     /**
235      * This method indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
236      * via the callback specified in SetReceiveIp6DatagramCallback().
237      *
238      * @returns  TRUE if Thread control traffic is filtered out, FALSE otherwise.
239      *
240      * @sa SetReceiveDatagramCallback
241      * @sa SetReceiveIp6FilterEnabled
242      *
243      */
IsReceiveIp6FilterEnabled(void) const244     bool IsReceiveIp6FilterEnabled(void) const { return mIsReceiveIp6FilterEnabled; }
245 
246     /**
247      * This method sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
248      * via the callback specified in SetReceiveIp6DatagramCallback().
249      *
250      * @param[in]  aEnabled  TRUE if Thread control traffic is filtered out, FALSE otherwise.
251      *
252      * @sa SetReceiveDatagramCallback
253      * @sa IsReceiveIp6FilterEnabled
254      *
255      */
SetReceiveIp6FilterEnabled(bool aEnabled)256     void SetReceiveIp6FilterEnabled(bool aEnabled) { mIsReceiveIp6FilterEnabled = aEnabled; }
257 
258     /**
259      * This method indicates whether or not IPv6 forwarding is enabled.
260      *
261      * @returns TRUE if IPv6 forwarding is enabled, FALSE otherwise.
262      *
263      */
IsForwardingEnabled(void) const264     bool IsForwardingEnabled(void) const { return mForwardingEnabled; }
265 
266     /**
267      * This method enables/disables IPv6 forwarding.
268      *
269      * @param[in]  aEnable  TRUE to enable IPv6 forwarding, FALSE otherwise.
270      *
271      */
SetForwardingEnabled(bool aEnable)272     void SetForwardingEnabled(bool aEnable) { mForwardingEnabled = aEnable; }
273 
274     /**
275      * This method perform default source address selection.
276      *
277      * @param[in]  aMessageInfo  A reference to the message information.
278      *
279      * @returns A pointer to the selected IPv6 source address or `nullptr` if no source address was found.
280      *
281      */
282     const Netif::UnicastAddress *SelectSourceAddress(MessageInfo &aMessageInfo);
283 
284     /**
285      * This method returns a reference to the send queue.
286      *
287      * @returns A reference to the send queue.
288      *
289      */
GetSendQueue(void) const290     const PriorityQueue &GetSendQueue(void) const { return mSendQueue; }
291 
292     /**
293      * This static method converts an IP protocol number to a string.
294      *
295      * @param[in] aIpProto  An IP protocol number.
296      *
297      * @returns The string representation of @p aIpProto.
298      *
299      */
300     static const char *IpProtoToString(uint8_t aIpProto);
301 
302     /**
303      * This static method converts an IP header ECN value to a string.
304      *
305      * @param[in] aEcn   The 2-bit ECN value.
306      *
307      * @returns The string representation of @p aEcn.
308      *
309      */
310     static const char *EcnToString(Ecn aEcn);
311 
312 private:
313     static constexpr uint8_t kDefaultHopLimit      = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT;
314     static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT;
315 
316     static constexpr uint16_t kMinimalMtu = 1280;
317 
318     static void HandleSendQueue(Tasklet &aTasklet);
319     void        HandleSendQueue(void);
320 
321     static uint8_t PriorityToDscp(Message::Priority aPriority);
322     static Error   GetDatagramPriority(const uint8_t *aData, uint16_t aDataLen, Message::Priority &aPriority);
323 
324     void  EnqueueDatagram(Message &aMessage);
325     Error ProcessReceiveCallback(Message &          aMessage,
326                                  const MessageInfo &aMessageInfo,
327                                  uint8_t            aIpProto,
328                                  bool               aFromHost,
329                                  bool               aAllowReceiveFilter,
330                                  Message::Ownership aMessageOwnership);
331     Error HandleExtensionHeaders(Message &    aMessage,
332                                  Netif *      aNetif,
333                                  MessageInfo &aMessageInfo,
334                                  Header &     aHeader,
335                                  uint8_t &    aNextHeader,
336                                  bool         aIsOutbound,
337                                  bool         aFromHost,
338                                  bool &       aReceive);
339     Error FragmentDatagram(Message &aMessage, uint8_t aIpProto);
340     Error HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromHost);
341 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
342     void CleanupFragmentationBuffer(void);
343     void HandleTimeTick(void);
344     void UpdateReassemblyList(void);
345     void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode);
346 #endif
347     Error AddMplOption(Message &aMessage, Header &aHeader);
348     Error AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo);
349     Error InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo);
350     Error RemoveMplOption(Message &aMessage);
351     Error HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive);
352     Error HandlePayload(Header &           aIp6Header,
353                         Message &          aMessage,
354                         MessageInfo &      aMessageInfo,
355                         uint8_t            aIpProto,
356                         Message::Ownership aMessageOwnership);
357     bool  ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromHost) const;
358     bool  IsOnLink(const Address &aAddress) const;
359 
360     bool                 mForwardingEnabled;
361     bool                 mIsReceiveIp6FilterEnabled;
362     otIp6ReceiveCallback mReceiveIp6DatagramCallback;
363     void *               mReceiveIp6DatagramCallbackContext;
364 
365     PriorityQueue mSendQueue;
366     Tasklet       mSendQueueTask;
367 
368     Icmp mIcmp;
369     Udp  mUdp;
370     Mpl  mMpl;
371 
372 #if OPENTHREAD_CONFIG_TCP_ENABLE
373     Tcp mTcp;
374 #endif
375 
376 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
377     MessageQueue mReassemblyList;
378 #endif
379 };
380 
381 /**
382  * This class represents parsed IPv6 header along with UDP/TCP/ICMP6 headers from a received message/frame.
383  *
384  */
385 class Headers : private Clearable<Headers>
386 {
387 public:
388     /**
389      * This method parses the IPv6 and UDP/TCP/ICMP6 headers from a given message.
390      *
391      * @param[in] aMessage   The message to parse the headers from.
392      *
393      * @retval kErrorNone    The headers are parsed successfully.
394      * @retval kErrorParse   Failed to parse the headers.
395      *
396      */
397     Error ParseFrom(const Message &aMessage);
398 
399     /**
400      * This method decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
401      *
402      * @param[in]  aMessage         The message from which to read the lowpan frame.
403      * @param[in]  aOffset          The offset in @p aMessage to start reading the frame.
404      * @param[in]  aMacSource       The MAC source address.
405      * @param[in]  aMacDest         The MAC destination address.
406      *
407      * @retval kErrorNone           Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers.
408      * @retval kErrorNotFound       Lowpan frame is a next fragment and does not contain IPv6 headers.
409      * @retval kErrorParse          Failed to parse the headers.
410      *
411      */
412     Error DecompressFrom(const Message &     aMessage,
413                          uint16_t            aOffset,
414                          const Mac::Address &aMacSource,
415                          const Mac::Address &aMacDest);
416 
417     /**
418      * This method decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
419      *
420      * @param[in]  aFrameData       The lowpan frame data.
421      * @param[in]  aMacSource       The MAC source address.
422      * @param[in]  aMacDest         The MAC destination address.
423      * @param[in]  aInstance        The OpenThread instance.
424      *
425      * @retval kErrorNone           Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers.
426      * @retval kErrorNotFound       Lowpan frame is a next fragment and does not contain IPv6 headers.
427      * @retval kErrorParse          Failed to parse the headers.
428      *
429      */
430     Error DecompressFrom(const FrameData &   aFrameData,
431                          const Mac::Address &aMacSource,
432                          const Mac::Address &aMacDest,
433                          Instance &          aInstance);
434 
435     /**
436      * This method returns the IPv6 header.
437      *
438      * @returns The IPv6 header.
439      *
440      */
GetIp6Header(void) const441     const Header &GetIp6Header(void) const { return mIp6Header; }
442 
443     /**
444      * This method returns the IP protocol number from IPv6 Next Header field.
445      *
446      * @returns The IP protocol number.
447      *
448      */
GetIpProto(void) const449     uint8_t GetIpProto(void) const { return mIp6Header.GetNextHeader(); }
450 
451     /**
452      * This method returns the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field from IPv6 header.
453      *
454      * @returns The ECN value.
455      *
456      */
GetEcn(void) const457     Ecn GetEcn(void) const { return mIp6Header.GetEcn(); }
458 
459     /**
460      * This method indicates if the protocol number from IPv6 header is UDP.
461      *
462      * @retval TRUE   If the protocol number in IPv6 header is UDP.
463      * @retval FALSE  If the protocol number in IPv6 header is not UDP.
464      *
465      */
IsUdp(void) const466     bool IsUdp(void) const { return GetIpProto() == kProtoUdp; }
467 
468     /**
469      * This method indicates if the protocol number from IPv6 header is TCP.
470      *
471      * @retval TRUE   If the protocol number in IPv6 header is TCP.
472      * @retval FALSE  If the protocol number in IPv6 header is not TCP.
473      *
474      */
IsTcp(void) const475     bool IsTcp(void) const { return GetIpProto() == kProtoTcp; }
476 
477     /**
478      * This method indicates if the protocol number from IPv6 header is ICMPv6.
479      *
480      * @retval TRUE   If the protocol number in IPv6 header is ICMPv6.
481      * @retval FALSE  If the protocol number in IPv6 header is not ICMPv6.
482      *
483      */
IsIcmp6(void) const484     bool IsIcmp6(void) const { return GetIpProto() == kProtoIcmp6; }
485 
486     /**
487      * This method returns the source IPv6 address from IPv6 header.
488      *
489      * @returns The source IPv6 address.
490      *
491      */
GetSourceAddress(void) const492     const Address &GetSourceAddress(void) const { return mIp6Header.GetSource(); }
493 
494     /**
495      * This method returns the destination IPv6 address from IPv6 header.
496      *
497      * @returns The destination IPv6 address.
498      *
499      */
GetDestinationAddress(void) const500     const Address &GetDestinationAddress(void) const { return mIp6Header.GetDestination(); }
501 
502     /**
503      * This method returns the UDP header.
504      *
505      * This method MUST be used when `IsUdp() == true`. Otherwise its behavior is undefined
506      *
507      * @returns The UDP header.
508      *
509      */
GetUdpHeader(void) const510     const Udp::Header &GetUdpHeader(void) const { return mHeader.mUdp; }
511 
512     /**
513      * This method returns the TCP header.
514      *
515      * This method MUST be used when `IsTcp() == true`. Otherwise its behavior is undefined
516      *
517      * @returns The TCP header.
518      *
519      */
GetTcpHeader(void) const520     const Tcp::Header &GetTcpHeader(void) const { return mHeader.mTcp; }
521 
522     /**
523      * This method returns the ICMPv6 header.
524      *
525      * This method MUST be used when `IsIcmp6() == true`. Otherwise its behavior is undefined
526      *
527      * @returns The ICMPv6 header.
528      *
529      */
GetIcmpHeader(void) const530     const Icmp::Header &GetIcmpHeader(void) const { return mHeader.mIcmp; }
531 
532     /**
533      * This method returns the source port number if header is UDP or TCP, or zero otherwise
534      *
535      * @returns The source port number under UDP / TCP or zero.
536      *
537      */
538     uint16_t GetSourcePort(void) const;
539 
540     /**
541      * This method returns the destination port number if header is UDP or TCP, or zero otherwise.
542      *
543      * @returns The destination port number under UDP / TCP or zero.
544      *
545      */
546     uint16_t GetDestinationPort(void) const;
547 
548     /**
549      * This method returns the checksum values from corresponding UDP, TCP, or ICMPv6 header.
550      *
551      * @returns The checksum value.
552      *
553      */
554     uint16_t GetChecksum(void) const;
555 
556 private:
557     Header mIp6Header;
558     union
559     {
560         Udp::Header  mUdp;
561         Tcp::Header  mTcp;
562         Icmp::Header mIcmp;
563     } mHeader;
564 };
565 
566 /**
567  * @}
568  *
569  */
570 
571 } // namespace Ip6
572 } // namespace ot
573 
574 #endif // IP6_HPP_
575