1 /*
2 * Copyright (c) 2024, 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 #ifdef __linux__
30
31 #define OTBR_LOG_TAG "NETIF"
32
33 #include "netif.hpp"
34
35 #include <assert.h>
36 #include <fcntl.h>
37 #include <linux/if.h>
38 #include <linux/if_tun.h>
39 #include <linux/netlink.h>
40 #include <linux/rtnetlink.h>
41 #include <net/if.h>
42 #include <net/if_arp.h>
43 #include <sys/ioctl.h>
44 #include <unistd.h>
45
46 #include "common/code_utils.hpp"
47 #include "common/logging.hpp"
48 #include "common/types.hpp"
49 #include "utils/socket_utils.hpp"
50
51 #ifndef OTBR_POSIX_TUN_DEVICE
52 #define OTBR_POSIX_TUN_DEVICE "/dev/net/tun"
53 #endif
54
55 namespace otbr {
56
AddRtAttr(nlmsghdr * aHeader,uint32_t aMaxLen,uint8_t aType,const void * aData,uint8_t aLen)57 static struct rtattr *AddRtAttr(nlmsghdr *aHeader, uint32_t aMaxLen, uint8_t aType, const void *aData, uint8_t aLen)
58 {
59 uint8_t len = RTA_LENGTH(aLen);
60 rtattr *rta;
61
62 assert(NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len) <= aMaxLen);
63 OTBR_UNUSED_VARIABLE(aMaxLen);
64
65 rta = reinterpret_cast<rtattr *>(reinterpret_cast<char *>(aHeader) + NLMSG_ALIGN((aHeader)->nlmsg_len));
66 rta->rta_type = aType;
67 rta->rta_len = len;
68 if (aLen)
69 {
70 memcpy(RTA_DATA(rta), aData, aLen);
71 }
72 aHeader->nlmsg_len = NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len);
73
74 return rta;
75 }
76
CreateTunDevice(const std::string & aInterfaceName)77 otbrError Netif::CreateTunDevice(const std::string &aInterfaceName)
78 {
79 ifreq ifr;
80 otbrError error = OTBR_ERROR_NONE;
81
82 VerifyOrExit(aInterfaceName.size() < IFNAMSIZ, error = OTBR_ERROR_INVALID_ARGS);
83
84 memset(&ifr, 0, sizeof(ifr));
85 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
86 if (aInterfaceName.size() > 0)
87 {
88 strncpy(ifr.ifr_name, aInterfaceName.c_str(), aInterfaceName.size());
89 }
90 else
91 {
92 strncpy(ifr.ifr_name, "wpan%d", IFNAMSIZ);
93 }
94
95 mTunFd = open(OTBR_POSIX_TUN_DEVICE, O_RDWR | O_CLOEXEC | O_NONBLOCK);
96 VerifyOrExit(mTunFd >= 0, error = OTBR_ERROR_ERRNO);
97
98 VerifyOrExit(ioctl(mTunFd, TUNSETIFF, &ifr) == 0, error = OTBR_ERROR_ERRNO);
99
100 mNetifName.assign(ifr.ifr_name, strlen(ifr.ifr_name));
101 otbrLogInfo("Netif name: %s", mNetifName.c_str());
102
103 VerifyOrExit(ioctl(mTunFd, TUNSETLINK, ARPHRD_NONE) == 0, error = OTBR_ERROR_ERRNO);
104
105 ifr.ifr_mtu = static_cast<int>(kIp6Mtu);
106 VerifyOrExit(ioctl(mIpFd, SIOCSIFMTU, &ifr) == 0, error = OTBR_ERROR_ERRNO);
107
108 exit:
109 return error;
110 }
111
InitNetlink(void)112 otbrError Netif::InitNetlink(void)
113 {
114 otbrError error = OTBR_ERROR_NONE;
115
116 mNetlinkFd = SocketWithCloseExec(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, kSocketNonBlock);
117 VerifyOrExit(mNetlinkFd >= 0, error = OTBR_ERROR_ERRNO);
118
119 #if defined(SOL_NETLINK)
120 {
121 int enable = 1;
122
123 #if defined(NETLINK_EXT_ACK)
124 if (setsockopt(mNetlinkFd, SOL_NETLINK, NETLINK_EXT_ACK, &enable, sizeof(enable)) != 0)
125 {
126 otbrLogWarning("Failed to enable NETLINK_EXT_ACK: %s", strerror(errno));
127 }
128 #endif
129 #if defined(NETLINK_CAP_ACK)
130 if (setsockopt(mNetlinkFd, SOL_NETLINK, NETLINK_CAP_ACK, &enable, sizeof(enable)) != 0)
131 {
132 otbrLogWarning("Failed to enable NETLINK_CAP_ACK: %s", strerror(errno));
133 }
134 #endif
135 }
136 #endif
137
138 {
139 sockaddr_nl sa;
140
141 memset(&sa, 0, sizeof(sa));
142 sa.nl_family = AF_NETLINK;
143 sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR;
144 VerifyOrExit(bind(mNetlinkFd, reinterpret_cast<sockaddr *>(&sa), sizeof(sa)) == 0, error = OTBR_ERROR_ERRNO);
145 }
146
147 exit:
148 return error;
149 }
150
PlatformSpecificInit(void)151 void Netif::PlatformSpecificInit(void)
152 {
153 SetAddrGenModeToNone();
154 }
155
SetAddrGenModeToNone(void)156 void Netif::SetAddrGenModeToNone(void)
157 {
158 struct
159 {
160 nlmsghdr nh;
161 ifinfomsg ifi;
162 char buf[512];
163 } req;
164
165 const uint8_t mode = IN6_ADDR_GEN_MODE_NONE;
166
167 memset(&req, 0, sizeof(req));
168
169 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(ifinfomsg));
170 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
171 req.nh.nlmsg_type = RTM_NEWLINK;
172 req.nh.nlmsg_pid = 0;
173 req.nh.nlmsg_seq = ++mNetlinkSequence;
174
175 req.ifi.ifi_index = static_cast<int>(mNetifIndex);
176 req.ifi.ifi_change = 0xffffffff;
177 req.ifi.ifi_flags = IFF_MULTICAST | IFF_NOARP;
178
179 {
180 rtattr *afSpec = AddRtAttr(&req.nh, sizeof(req), IFLA_AF_SPEC, 0, 0);
181 rtattr *afInet6 = AddRtAttr(&req.nh, sizeof(req), AF_INET6, 0, 0);
182 rtattr *inet6AddrGenMode = AddRtAttr(&req.nh, sizeof(req), IFLA_INET6_ADDR_GEN_MODE, &mode, sizeof(mode));
183
184 afInet6->rta_len += inet6AddrGenMode->rta_len;
185 afSpec->rta_len += afInet6->rta_len;
186 }
187
188 if (send(mNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
189 {
190 otbrLogInfo("Sent request#%u to set addr_gen_mode to %d", mNetlinkSequence, mode);
191 }
192 else
193 {
194 otbrLogWarning("Failed to send request#%u to set addr_gen_mode to %d", mNetlinkSequence, mode);
195 }
196 }
197
ProcessUnicastAddressChange(const Ip6AddressInfo & aAddressInfo,bool aIsAdded)198 void Netif::ProcessUnicastAddressChange(const Ip6AddressInfo &aAddressInfo, bool aIsAdded)
199 {
200 struct
201 {
202 nlmsghdr nh;
203 ifaddrmsg ifa;
204 char buf[512];
205 } req;
206
207 assert(mIpFd >= 0);
208 memset(&req, 0, sizeof(req));
209
210 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrmsg));
211 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (aIsAdded ? (NLM_F_CREATE | NLM_F_EXCL) : 0);
212 req.nh.nlmsg_type = aIsAdded ? RTM_NEWADDR : RTM_DELADDR;
213 req.nh.nlmsg_pid = 0;
214 req.nh.nlmsg_seq = ++mNetlinkSequence;
215
216 req.ifa.ifa_family = AF_INET6;
217 req.ifa.ifa_prefixlen = aAddressInfo.mPrefixLength;
218 req.ifa.ifa_flags = IFA_F_NODAD;
219 req.ifa.ifa_scope = aAddressInfo.mScope;
220 req.ifa.ifa_index = mNetifIndex;
221
222 AddRtAttr(&req.nh, sizeof(req), IFA_LOCAL, &aAddressInfo.mAddress, sizeof(aAddressInfo.mAddress));
223
224 if (!aAddressInfo.mPreferred || aAddressInfo.mMeshLocal)
225 {
226 ifa_cacheinfo cacheinfo;
227
228 memset(&cacheinfo, 0, sizeof(cacheinfo));
229 cacheinfo.ifa_valid = UINT32_MAX;
230
231 AddRtAttr(&req.nh, sizeof(req), IFA_CACHEINFO, &cacheinfo, sizeof(cacheinfo));
232 }
233
234 if (send(mNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
235 {
236 otbrLogInfo("Sent request#%u to %s %s/%u", mNetlinkSequence, (aIsAdded ? "add" : "remove"),
237 Ip6Address(aAddressInfo.mAddress).ToString().c_str(), aAddressInfo.mPrefixLength);
238 }
239 else
240 {
241 otbrLogWarning("Failed to send request#%u to %s %s/%u", mNetlinkSequence, (aIsAdded ? "add" : "remove"),
242 Ip6Address(aAddressInfo.mAddress).ToString().c_str(), aAddressInfo.mPrefixLength);
243 }
244 }
245
246 } // namespace otbr
247
248 #endif // __linux__
249