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/locator.hpp"
46 #include "common/message.hpp"
47 #include "common/non_copyable.hpp"
48 #include "common/time_ticker.hpp"
49 #include "common/timer.hpp"
50 #include "net/icmp6.hpp"
51 #include "net/ip6_address.hpp"
52 #include "net/ip6_headers.hpp"
53 #include "net/ip6_mpl.hpp"
54 #include "net/netif.hpp"
55 #include "net/socket.hpp"
56 #include "net/tcp6.hpp"
57 #include "net/udp6.hpp"
58 
59 namespace ot {
60 
61 /**
62  * @namespace ot::Ip6
63  *
64  * @brief
65  *   This namespace includes definitions for IPv6 networking.
66  *
67  */
68 namespace Ip6 {
69 
70 using ot::Encoding::BigEndian::HostSwap16;
71 using ot::Encoding::BigEndian::HostSwap32;
72 
73 /**
74  * @addtogroup core-ipv6
75  *
76  * @brief
77  *   This module includes definitions for the IPv6 network layer.
78  *
79  * @{
80  *
81  * @defgroup core-ip6-icmp6 ICMPv6
82  * @defgroup core-ip6-ip6 IPv6
83  * @defgroup core-ip6-mpl MPL
84  * @defgroup core-ip6-netif Network Interfaces
85  *
86  * @}
87  *
88  */
89 
90 /**
91  * @addtogroup core-ip6-ip6
92  *
93  * @brief
94  *   This module includes definitions for core IPv6 networking.
95  *
96  * @{
97  *
98  */
99 
100 /**
101  * This class implements the core IPv6 message processing.
102  *
103  */
104 class Ip6 : public InstanceLocator, private NonCopyable
105 {
106     friend class ot::Instance;
107     friend class ot::TimeTicker;
108     friend class Mpl;
109 
110 public:
111     /**
112      * The max datagram length (in bytes) of an IPv6 message.
113      *
114      */
115     static constexpr uint16_t kMaxDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_DATAGRAM_LENGTH;
116 
117     /**
118      * The max datagram length (in bytes) of an unfragmented IPv6 message.
119      *
120      */
121     static constexpr uint16_t kMaxAssembledDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_ASSEMBLED_DATAGRAM;
122 
123     /**
124      * This constructor initializes the object.
125      *
126      * @param[in]  aInstance   A reference to the otInstance object.
127      *
128      */
129     explicit Ip6(Instance &aInstance);
130 
131     /**
132      * This method allocates a new message buffer from the buffer pool.
133      *
134      * @param[in]  aReserved  The number of header bytes to reserve following the IPv6 header.
135      * @param[in]  aSettings  The message settings.
136      *
137      * @returns A pointer to the message or nullptr if insufficient message buffers are available.
138      *
139      */
140     Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
141 
142     /**
143      * This method allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message.
144      *
145      * @param[in]  aData        A pointer to the IPv6 datagram buffer.
146      * @param[in]  aDataLength  The size of the IPV6 datagram buffer pointed by @p aData.
147      * @param[in]  aSettings    The message settings.
148      *
149      * @returns A pointer to the message or nullptr if malformed IPv6 header or insufficient message buffers are
150      * available.
151      *
152      */
153     Message *NewMessage(const uint8_t *aData, uint16_t aDataLength, const Message::Settings &aSettings);
154 
155     /**
156      * This method allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message.
157      *
158      * @note The link layer security is enabled and the message priority is obtained from IPv6 message itself.
159      *
160      * @param[in]  aData        A pointer to the IPv6 datagram buffer.
161      * @param[in]  aDataLength  The size of the IPV6 datagram buffer pointed by @p aData.
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 *NewMessage(const uint8_t *aData, uint16_t aDataLength);
168 
169     /**
170      * This method 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      * This method 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      * This method sends a raw IPv6 datagram with a fully formed IPv6 header.
194      *
195      * The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when
196      * processing is complete, including when a value other than `kErrorNone` is returned.
197      *
198      * @param[in]  aMessage          A reference to the message.
199      *
200      * @retval kErrorNone     Successfully processed the message.
201      * @retval kErrorDrop     Message was well-formed but not fully processed due to packet processing rules.
202      * @retval kErrorNoBufs   Could not allocate necessary message buffers when processing the datagram.
203      * @retval kErrorNoRoute  No route to host.
204      * @retval kErrorParse    Encountered a malformed header when processing the message.
205      *
206      */
207     Error SendRaw(Message &aMessage);
208 
209     /**
210      * This method processes a received IPv6 datagram.
211      *
212      * @param[in]  aMessage          A reference to the message.
213      * @param[in]  aNetif            A pointer to the network interface that received the message.
214      * @param[in]  aLinkMessageInfo  A pointer to link-specific message information.
215      * @param[in]  aFromNcpHost      TRUE if the message was submitted by the NCP host, FALSE otherwise.
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 HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromNcpHost);
225 
226     /**
227      * This method registers a callback to provide received raw IPv6 datagrams.
228      *
229      * By default, this callback does not pass Thread control traffic.  See SetReceiveIp6FilterEnabled() to change
230      * the Thread control traffic filter setting.
231      *
232      * @param[in]  aCallback         A pointer to a function that is called when an IPv6 datagram is received
233      *                               or nullptr to disable the callback.
234      * @param[in]  aCallbackContext  A pointer to application-specific context.
235      *
236      * @sa IsReceiveIp6FilterEnabled
237      * @sa SetReceiveIp6FilterEnabled
238      *
239      */
240     void SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback, void *aCallbackContext);
241 
242     /**
243      * This method indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
244      * via the callback specified in SetReceiveIp6DatagramCallback().
245      *
246      * @returns  TRUE if Thread control traffic is filtered out, FALSE otherwise.
247      *
248      * @sa SetReceiveDatagramCallback
249      * @sa SetReceiveIp6FilterEnabled
250      *
251      */
IsReceiveIp6FilterEnabled(void) const252     bool IsReceiveIp6FilterEnabled(void) const { return mIsReceiveIp6FilterEnabled; }
253 
254     /**
255      * This method sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams
256      * via the callback specified in SetReceiveIp6DatagramCallback().
257      *
258      * @param[in]  aEnabled  TRUE if Thread control traffic is filtered out, FALSE otherwise.
259      *
260      * @sa SetReceiveDatagramCallback
261      * @sa IsReceiveIp6FilterEnabled
262      *
263      */
SetReceiveIp6FilterEnabled(bool aEnabled)264     void SetReceiveIp6FilterEnabled(bool aEnabled) { mIsReceiveIp6FilterEnabled = aEnabled; }
265 
266     /**
267      * This method indicates whether or not IPv6 forwarding is enabled.
268      *
269      * @returns TRUE if IPv6 forwarding is enabled, FALSE otherwise.
270      *
271      */
IsForwardingEnabled(void) const272     bool IsForwardingEnabled(void) const { return mForwardingEnabled; }
273 
274     /**
275      * This method enables/disables IPv6 forwarding.
276      *
277      * @param[in]  aEnable  TRUE to enable IPv6 forwarding, FALSE otherwise.
278      *
279      */
SetForwardingEnabled(bool aEnable)280     void SetForwardingEnabled(bool aEnable) { mForwardingEnabled = aEnable; }
281 
282     /**
283      * This method perform default source address selection.
284      *
285      * @param[in]  aMessageInfo  A reference to the message information.
286      *
287      * @returns A pointer to the selected IPv6 source address or nullptr if no source address was found.
288      *
289      */
290     const Netif::UnicastAddress *SelectSourceAddress(MessageInfo &aMessageInfo);
291 
292     /**
293      * This method returns a reference to the send queue.
294      *
295      * @returns A reference to the send queue.
296      *
297      */
GetSendQueue(void) const298     const PriorityQueue &GetSendQueue(void) const { return mSendQueue; }
299 
300     /**
301      * This static method converts an IP protocol number to a string.
302      *
303      * @param[in] aIpPorto  An IP protocol number.
304      *
305      * @returns The string representation of @p aIpProto.
306      *
307      */
308     static const char *IpProtoToString(uint8_t aIpProto);
309 
310 private:
311     static constexpr uint8_t kDefaultHopLimit      = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT;
312     static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT;
313 
314     static constexpr uint16_t kMinimalMtu = 1280;
315 
316     static constexpr uint32_t kStateUpdatePeriod = 1000;
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               aFromNcpHost,
329                                  Message::Ownership aMessageOwnership);
330     Error HandleExtensionHeaders(Message &    aMessage,
331                                  Netif *      aNetif,
332                                  MessageInfo &aMessageInfo,
333                                  Header &     aHeader,
334                                  uint8_t &    aNextHeader,
335                                  bool         aIsOutbound,
336                                  bool         aFromNcpHost,
337                                  bool &       aReceive);
338     Error FragmentDatagram(Message &aMessage, uint8_t aIpProto);
339     Error HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost);
340 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
341     void CleanupFragmentationBuffer(void);
342     void HandleTimeTick(void);
343     void UpdateReassemblyList(void);
344     void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode);
345 #endif
346     Error AddMplOption(Message &aMessage, Header &aHeader);
347     Error AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo);
348     Error InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo);
349     Error RemoveMplOption(Message &aMessage);
350     Error HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive);
351     Error HandlePayload(Header &           aIp6Header,
352                         Message &          aMessage,
353                         MessageInfo &      aMessageInfo,
354                         uint8_t            aIpProto,
355                         Message::Ownership aMessageOwnership);
356     bool  ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromNcpHost) const;
357     bool  IsOnLink(const Address &aAddress) const;
358 
359     bool                 mForwardingEnabled;
360     bool                 mIsReceiveIp6FilterEnabled;
361     otIp6ReceiveCallback mReceiveIp6DatagramCallback;
362     void *               mReceiveIp6DatagramCallbackContext;
363 
364     PriorityQueue mSendQueue;
365     Tasklet       mSendQueueTask;
366 
367     Icmp mIcmp;
368     Udp  mUdp;
369     Mpl  mMpl;
370 
371 #if OPENTHREAD_CONFIG_TCP_ENABLE
372     Tcp mTcp;
373 #endif
374 
375 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
376     MessageQueue mReassemblyList;
377 #endif
378 };
379 
380 /**
381  * @}
382  *
383  */
384 
385 } // namespace Ip6
386 } // namespace ot
387 
388 #endif // IP6_HPP_
389