1 /*
2  *  Copyright (c) 2021, 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 implements the infrastructure interface for posix.
32  */
33 
34 #ifndef OT_POSIX_PLATFORM_INFRA_IF_HPP_
35 #define OT_POSIX_PLATFORM_INFRA_IF_HPP_
36 
37 #include "openthread-posix-config.h"
38 
39 #include <net/if.h>
40 #include <openthread/nat64.h>
41 #include <openthread/openthread-system.h>
42 
43 #include "core/common/non_copyable.hpp"
44 
45 #include "logger.hpp"
46 #include "mainloop.hpp"
47 #include "multicast_routing.hpp"
48 
49 #if OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
50 
51 namespace ot {
52 namespace Posix {
53 
54 /**
55  * Manages infrastructure network interface.
56  *
57  */
58 class InfraNetif : public Mainloop::Source, public Logger<InfraNetif>, private NonCopyable
59 {
60 public:
61     static const char kLogModuleName[]; ///< Module name used for logging.
62 
63     /**
64      * Updates the fd_set and timeout for mainloop.
65      *
66      * @param[in,out]   aContext    A reference to the mainloop context.
67      *
68      */
69     void Update(otSysMainloopContext &aContext) override;
70 
71     /**
72      * Performs infrastructure network interface processing.
73      *
74      * @param[in]   aContext   A reference to the mainloop context.
75      *
76      */
77     void Process(const otSysMainloopContext &aContext) override;
78 
79     /**
80      * Initializes the infrastructure network interface.
81      *
82      * To specify the infrastructure network interface, you need to call SetInfraNetif() after Init().
83      *
84      * @note This method is called before OpenThread instance is created.
85      *
86      */
87     void Init(void);
88 
89     /**
90      * Sets the infrastructure network interface.
91      *
92      * @param[in]  aIfName       A pointer to infrastructure network interface name.
93      * @param[in]  aIcmp6Socket  A SOCK_RAW socket for sending/receiving ICMPv6 messages. If you don't need border
94      *                           routing feature, you can pass in -1.
95      *
96      */
97     void SetInfraNetif(const char *aIfName, int aIcmp6Socket);
98 
99     /**
100      * Sets up the infrastructure network interface.
101      *
102      * @note This method is called after OpenThread instance is created.
103      *
104      */
105     void SetUp(void);
106 
107     /**
108      * Tears down the infrastructure network interface.
109      *
110      * @note This method is called before OpenThread instance is destructed.
111      *
112      */
113     void TearDown(void);
114 
115     /**
116      * Deinitializes the infrastructure network interface.
117      *
118      * @note This method is called after OpenThread instance is destructed.
119      *
120      */
121     void Deinit(void);
122 
123     /**
124      * Checks whether the infrastructure network interface is running.
125      *
126      */
127     bool IsRunning(void) const;
128 
129     /**
130      * Returns the ifr_flags of the infrastructure network interface.
131      *
132      * @returns The ifr_flags of the infrastructure network interface.
133      *
134      */
135     uint32_t GetFlags(void) const;
136 
137     /**
138      * This functions counts the number of addresses on the infrastructure network interface.
139      *
140      * @param[out] aAddressCounters  The counters of addresses on infrastructure network interface.
141      *
142      */
143     void CountAddresses(otSysInfraNetIfAddressCounters &aAddressCounters) const;
144 
145     /**
146      * Handles the backbone state change events.
147      *
148      * @param[in] aInstance  A pointer to the OpenThread instance.
149      * @param[in] aFlags     Flags that denote the state change events.
150      *
151      */
152     void HandleBackboneStateChange(otInstance *aInstance, otChangedFlags aFlags);
153 
154     /**
155      * Sends an ICMPv6 Neighbor Discovery message on given infrastructure interface.
156      *
157      * See RFC 4861: https://tools.ietf.org/html/rfc4861.
158      *
159      * @param[in]  aInfraIfIndex  The index of the infrastructure interface this message is sent to.
160      * @param[in]  aDestAddress   The destination address this message is sent to.
161      * @param[in]  aBuffer        The ICMPv6 message buffer. The ICMPv6 checksum is left zero and the
162      *                            platform should do the checksum calculate.
163      * @param[in]  aBufferLength  The length of the message buffer.
164      *
165      * @note  Per RFC 4861, the implementation should send the message with IPv6 link-local source address
166      *        of interface @p aInfraIfIndex and IP Hop Limit 255.
167      *
168      * @retval OT_ERROR_NONE    Successfully sent the ICMPv6 message.
169      * @retval OT_ERROR_FAILED  Failed to send the ICMPv6 message.
170      *
171      */
172     otError SendIcmp6Nd(uint32_t            aInfraIfIndex,
173                         const otIp6Address &aDestAddress,
174                         const uint8_t      *aBuffer,
175                         uint16_t            aBufferLength);
176 
177 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE && OPENTHREAD_POSIX_CONFIG_NAT64_AIL_PREFIX_ENABLE
178     /**
179      * Sends an asynchronous address lookup for the well-known host name "ipv4only.arpa"
180      * to discover the NAT64 prefix.
181      *
182      * @param[in]  aInfraIfIndex  The index of the infrastructure interface the address look-up is sent to.
183      *
184      * @retval  OT_ERROR_NONE    Successfully request address look-up.
185      * @retval  OT_ERROR_FAILED  Failed to request address look-up.
186      *
187      */
188     otError DiscoverNat64Prefix(uint32_t aInfraIfIndex);
189 #endif
190 
191     /**
192      * Gets the infrastructure network interface name.
193      *
194      * @returns The infrastructure network interface name, or `nullptr` if not specified.
195      *
196      */
GetNetifName(void) const197     const char *GetNetifName(void) const { return (mInfraIfIndex != 0) ? mInfraIfName : nullptr; }
198 
199     /**
200      * Gets the infrastructure network interface index.
201      *
202      * @returns The infrastructure network interface index.
203      *
204      */
GetNetifIndex(void) const205     uint32_t GetNetifIndex(void) const { return mInfraIfIndex; }
206 
207     /**
208      * Gets the infrastructure network interface singleton.
209      *
210      * @returns The singleton object.
211      *
212      */
213     static InfraNetif &Get(void);
214 
215     /**
216      * Creates a socket for sending/receiving ICMPv6 messages.
217      *
218      * @param[in] aInfraIfName  The infrastructure network interface name.
219      *
220      * @returns The file descriptor of the socket.
221      *
222      */
223     static int CreateIcmp6Socket(const char *aInfraIfName);
224 
225 private:
226     static const char         kWellKnownIpv4OnlyName[];   // "ipv4only.arpa"
227     static const otIp4Address kWellKnownIpv4OnlyAddress1; // 192.0.0.170
228     static const otIp4Address kWellKnownIpv4OnlyAddress2; // 192.0.0.171
229     static const uint8_t      kValidNat64PrefixLength[];
230 
231     char     mInfraIfName[IFNAMSIZ];
232     uint32_t mInfraIfIndex = 0;
233 
234 #ifdef __linux__
235     int mNetLinkSocket = -1;
236 #endif
237 
238 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
239     int mInfraIfIcmp6Socket = -1;
240 #endif
241 #if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
242     MulticastRoutingManager mMulticastRoutingManager;
243 #endif
244 
245     bool HasLinkLocalAddress(void) const;
246 
247 #ifdef __linux__
248     void ReceiveNetLinkMessage(void);
249 #endif
250 
251 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE && OPENTHREAD_POSIX_CONFIG_NAT64_AIL_PREFIX_ENABLE
252 #ifdef __linux__
253     static void DiscoverNat64PrefixDone(union sigval sv);
254 #endif // #ifdef __linux__
255 #endif
256 
257 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
258     void SetInfraNetifIcmp6SocketForBorderRouting(int aIcmp6Socket);
259     void ReceiveIcmp6Message(void);
260 #endif
261 };
262 
263 } // namespace Posix
264 } // namespace ot
265 #endif // OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
266 
267 #endif // OT_POSIX_PLATFORM_INFRA_IF_HPP_
268