1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "distributed_manager.h"
17
18 #include <arpa/inet.h>
19 #include <fcntl.h>
20 #include <netinet/in.h>
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <sys/un.h>
25 #include <thread>
26 #include <unistd.h>
27 #include <linux/if.h>
28 #include <linux/if_tun.h>
29 #include <linux/ipv6.h>
30
31 #include "init_socket.h"
32 #include "net_manager_constants.h"
33 #include "netmanager_base_common_utils.h"
34 #include "netnative_log_wrapper.h"
35 #include "securec.h"
36
37 namespace OHOS {
38 namespace NetManagerStandard {
39
40 namespace {
41 constexpr const char *DISTRIBUTED_TUN_DEVICE_PATH = "/dev/tun";
42 constexpr int32_t NET_MASK_MAX_LENGTH = 24;
43 constexpr int32_t DISTRIBUTED_MTU = 1400;
44 constexpr const char *IP_CMD_PATH = "/system/bin/ip";
45 } // namespace
46
CreateDistributedInterface(const std::string & ifName)47 int32_t DistributedManager::CreateDistributedInterface(const std::string &ifName)
48 {
49 net4Sock_ = socket(AF_INET, SOCK_DGRAM, 0);
50 if (net4Sock_ < 0) {
51 NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
52 return NETMANAGER_ERROR;
53 }
54
55 if (tunFd_ != 0) {
56 return NETMANAGER_SUCCESS;
57 }
58
59 ifreq ifr{};
60 if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
61 return NETMANAGER_ERROR;
62 }
63
64 int32_t tunfd = open(DISTRIBUTED_TUN_DEVICE_PATH, O_RDWR | O_NONBLOCK);
65 if (tunfd <= 0) {
66 NETNATIVE_LOGE("open virtual distributed nic failed: %{public}d", errno);
67 return NETMANAGER_ERROR;
68 }
69
70 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
71 if (ioctl(tunfd, TUNSETIFF, &ifr) < 0) {
72 close(tunfd);
73 NETNATIVE_LOGE("tun set iff error: %{public}d", errno);
74 return NETMANAGER_ERROR;
75 }
76
77 NETNATIVE_LOGI("create virtual device successfully, [%{public}d]", tunfd);
78 tunFd_ = tunfd;
79
80 return NETMANAGER_SUCCESS;
81 }
82
SetDistributedNicResult(std::atomic_int & fd,unsigned long cmd,ifreq & ifr)83 int32_t DistributedManager::SetDistributedNicResult(std::atomic_int &fd, unsigned long cmd, ifreq &ifr)
84 {
85 if (fd > 0) {
86 if (ioctl(fd, cmd, &ifr) < 0) {
87 NETNATIVE_LOGE("set virnic error, errno:%{public}d", errno);
88 return NETMANAGER_ERROR;
89 }
90 return NETMANAGER_SUCCESS;
91 }
92 return NETMANAGER_ERROR;
93 }
94
InitIfreq(ifreq & ifr,const std::string & cardName)95 int32_t DistributedManager::InitIfreq(ifreq &ifr, const std::string &cardName)
96 {
97 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
98 NETNATIVE_LOGE("memset_s ifr failed!");
99 return NETMANAGER_ERROR;
100 }
101 if (strncpy_s(ifr.ifr_name, IFNAMSIZ, cardName.c_str(), strlen(cardName.c_str())) != EOK) {
102 NETNATIVE_LOGE("strcpy_s ifr name fail");
103 return NETMANAGER_ERROR;
104 }
105 return NETMANAGER_SUCCESS;
106 }
107
SetDistributedNicMtu(const std::string & ifName,int32_t mtu)108 int32_t DistributedManager::SetDistributedNicMtu(const std::string &ifName, int32_t mtu)
109 {
110 if (mtu <= 0) {
111 NETNATIVE_LOGE("invalid mtu value");
112 return NETMANAGER_ERROR;
113 }
114
115 ifreq ifr{};
116 if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
117 return NETMANAGER_ERROR;
118 }
119
120 ifr.ifr_mtu = mtu;
121 int32_t ret4 = SetDistributedNicResult(net4Sock_, SIOCSIFMTU, ifr);
122 if (ret4 == NETMANAGER_ERROR || (net4Sock_ < 0)) {
123 NETNATIVE_LOGI("set MTU failed");
124 return NETMANAGER_ERROR;
125 } else {
126 NETNATIVE_LOGI("set MTU success");
127 return NETMANAGER_SUCCESS;
128 }
129 }
130
SetDistributedNicAddress(const std::string & ifName,const std::string & tunAddr)131 int32_t DistributedManager::SetDistributedNicAddress(const std::string &ifName, const std::string &tunAddr)
132 {
133 ifreq ifr{};
134 if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
135 return NETMANAGER_ERROR;
136 }
137
138 bool isIpv6 = CommonUtils::IsValidIPV6(tunAddr);
139 if (isIpv6) {
140 NETNATIVE_LOGE("distributed nic not support ipv6 by now");
141 return NETMANAGER_ERROR;
142 } else {
143 in_addr ipv4Addr = {};
144 if (inet_aton(tunAddr.c_str(), &ipv4Addr) == 0) {
145 NETNATIVE_LOGE("addr inet_aton error");
146 return NETMANAGER_ERROR;
147 }
148
149 auto sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_addr);
150 sin->sin_family = AF_INET;
151 sin->sin_addr = ipv4Addr;
152 if (ioctl(net4Sock_, SIOCSIFADDR, &ifr) < 0) {
153 NETNATIVE_LOGE("ioctl set ipv4 address failed: %{public}d", errno);
154 return NETMANAGER_ERROR;
155 }
156
157 int32_t prefix = NET_MASK_MAX_LENGTH;
158 in_addr_t mask = prefix ? (0xFFFFFFFF << (NET_MASK_MAX_LENGTH - prefix)) : 0;
159 sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_netmask);
160 sin->sin_family = AF_INET;
161 sin->sin_addr.s_addr = htonl(mask);
162 if (ioctl(net4Sock_, SIOCSIFNETMASK, &ifr) < 0) {
163 NETNATIVE_LOGE("ioctl set ip mask failed: %{public}d", errno);
164 return NETMANAGER_ERROR;
165 }
166 }
167
168 NETNATIVE_LOGI("set ip address success");
169 return NETMANAGER_SUCCESS;
170 }
171
SetDistributedNicUp(const std::string & ifName)172 int32_t DistributedManager::SetDistributedNicUp(const std::string &ifName)
173 {
174 ifreq ifr{};
175 if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
176 return NETMANAGER_ERROR;
177 }
178
179 ifr.ifr_flags = static_cast<uint16_t>(IFF_UP | IFF_NOARP);
180
181 int32_t ret4 = SetDistributedNicResult(net4Sock_, SIOCSIFFLAGS, ifr);
182 if (ret4 == NETMANAGER_ERROR || (net4Sock_ < 0)) {
183 NETNATIVE_LOGI("set iff up failed");
184 return NETMANAGER_ERROR;
185 } else {
186 NETNATIVE_LOGI("set iff up success");
187 return NETMANAGER_SUCCESS;
188 }
189 }
190
SetDistributedNicDown(const std::string & ifName)191 int32_t DistributedManager::SetDistributedNicDown(const std::string &ifName)
192 {
193 ifreq ifr{};
194 if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
195 return NETMANAGER_ERROR;
196 }
197
198 ifr.ifr_flags = (uint16_t)ifr.ifr_flags & ~IFF_UP;
199 int32_t ret4 = SetDistributedNicResult(net4Sock_, SIOCSIFFLAGS, ifr);
200 if (ret4 == NETMANAGER_ERROR || (net4Sock_ < 0)) {
201 NETNATIVE_LOGI("set iff down failed");
202 return NETMANAGER_ERROR;
203 } else {
204 NETNATIVE_LOGI("set iff down success");
205 return NETMANAGER_SUCCESS;
206 }
207 }
208
CloseDistributedSocket()209 void DistributedManager::CloseDistributedSocket()
210 {
211 if (net4Sock_ > 0) {
212 close(net4Sock_);
213 net4Sock_ = 0;
214 }
215 }
216
CloseDistributedTunFd()217 void DistributedManager::CloseDistributedTunFd()
218 {
219 if (tunFd_ > 0) {
220 close(tunFd_);
221 tunFd_ = 0;
222 }
223 }
224
CreateDistributedNic(const std::string & virNicAddr,const std::string & ifName)225 int32_t DistributedManager::CreateDistributedNic(const std::string &virNicAddr, const std::string &ifName)
226 {
227 NETNATIVE_LOGI("CreateVirnic, mtu:%{public}d", DISTRIBUTED_MTU);
228 if (CreateDistributedInterface(ifName) != NETMANAGER_SUCCESS) {
229 CloseDistributedSocket();
230 return NETMANAGER_ERROR;
231 }
232 if (SetDistributedNicMtu(ifName, DISTRIBUTED_MTU) != NETMANAGER_SUCCESS ||
233 SetDistributedNicAddress(ifName, virNicAddr) != NETMANAGER_SUCCESS) {
234 SetDistributedNicDown(ifName);
235 CloseDistributedSocket();
236 return NETMANAGER_ERROR;
237 }
238 if (SetDistributedNicUp(ifName) != NETMANAGER_SUCCESS) {
239 CloseDistributedSocket();
240 return NETMANAGER_ERROR;
241 }
242 CloseDistributedSocket();
243
244 return NETMANAGER_SUCCESS;
245 }
246
DestroyDistributedNic(const std::string & ifName)247 int32_t DistributedManager::DestroyDistributedNic(const std::string &ifName)
248 {
249 SetDistributedNicDown(ifName);
250 return NETMANAGER_SUCCESS;
251 }
252
SetServerNicInfo(const std::string & iif,const std::string & devIface)253 void DistributedManager::SetServerNicInfo(const std::string &iif, const std::string &devIface)
254 {
255 serverIif_ = iif;
256 serverDevIface_ = devIface;
257 }
258
GetServerIifNic()259 std::string DistributedManager::GetServerIifNic()
260 {
261 return serverIif_;
262 }
263
GetServerDevIfaceNic()264 std::string DistributedManager::GetServerDevIfaceNic()
265 {
266 return serverDevIface_;
267 }
268
ConfigVirnicAndVeth(const std::string & virNicAddr,const std::string & virnicName,const std::string & virnicVethName)269 int32_t DistributedManager::ConfigVirnicAndVeth(const std::string &virNicAddr, const std::string &virnicName,
270 const std::string &virnicVethName)
271 {
272 if (virnicName.empty() || virnicVethName.empty()) {
273 NETNATIVE_LOGE("NicName is nullptr");
274 return NETMANAGER_ERROR;
275 }
276
277 if (!CommonUtils::IsValidIPV4(virNicAddr)) {
278 NETNATIVE_LOGE("the virNicAddr is not valid");
279 return NETMANAGER_ERROR;
280 }
281
282 // Step1: ip link add virnic type veth peer name virnic1
283 std::string out;
284 std::string createVirnic = std::string(IP_CMD_PATH) + " link add " + virnicName +
285 " type veth peer name " + virnicVethName;
286 NETNATIVE_LOGI("setup virnic and veth : %{public}s", createVirnic.c_str());
287 if (CommonUtils::ForkExec(createVirnic.c_str(), &out) != NETMANAGER_SUCCESS) {
288 NETNATIVE_LOGE("setup virnic and veth failed, output %{public}s", out.c_str());
289 return NETMANAGER_ERROR;
290 }
291
292 // Step2-1: ip link set virnic up
293 std::string virnicUp = std::string(IP_CMD_PATH) + " link set " + virnicName + " up";
294 NETNATIVE_LOGI("set virnic up: %{public}s", virnicUp.c_str());
295 if (CommonUtils::ForkExec(virnicUp.c_str(), &out) != NETMANAGER_SUCCESS) {
296 NETNATIVE_LOGE("set virnic up, output: %{public}s.", out.c_str());
297 return NETMANAGER_ERROR;
298 }
299 // Step2-2: ip link set virnic-veth up
300 std::string virnicVethUp = std::string(IP_CMD_PATH) + " link set " + virnicVethName + " up";
301 NETNATIVE_LOGI("set virnicVeth up: %{public}s", virnicVethUp.c_str());
302 if (CommonUtils::ForkExec(virnicVethUp.c_str(), &out) != NETMANAGER_SUCCESS) {
303 NETNATIVE_LOGE("set virnicVeth up failed, output: %{public}s.", out.c_str());
304 return NETMANAGER_ERROR;
305 }
306
307 // Step3-1: ip addr add xx.xx.xx.xx/24 dev virnic
308 std::string cfgVirnic = std::string(IP_CMD_PATH) + " addr add " + virNicAddr + "/24 dev " + virnicName;
309 NETNATIVE_LOGI("add virnic ip: %{public}s", CommonUtils::AnonymousIpInStr(cfgVirnic).c_str());
310 if (CommonUtils::ForkExec(cfgVirnic.c_str(), &out) != NETMANAGER_SUCCESS) {
311 NETNATIVE_LOGE("add virnic ip failed, output %{public}s.", out.c_str());
312 return NETMANAGER_ERROR;
313 }
314 std::string maskAddr = CommonUtils::GetMaskByLength(DEFAULT_GATEWAY_MASK_MAX_LENGTH);
315 std::string virNicVethAddr = CommonUtils::GetGatewayAddr(virNicAddr, maskAddr);
316 if (virNicVethAddr.empty()) {
317 NETNATIVE_LOGE("get gateway addr is empty");
318 return NETMANAGER_ERROR;
319 }
320
321 // Step3-1: ip addr add xx.xx.xx.1/24 dev virnic
322 std::string cfgVirnicVeth = std::string(IP_CMD_PATH) + " addr add " + virNicVethAddr + "/24 dev " + virnicVethName;
323 NETNATIVE_LOGI("add virNic-veth ip: %{public}s", CommonUtils::AnonymousIpInStr(cfgVirnicVeth).c_str());
324 if (CommonUtils::ForkExec(cfgVirnicVeth.c_str(), &out) != NETMANAGER_SUCCESS) {
325 NETNATIVE_LOGE("add virNic-veth ip failed, output %{public}s.", out.c_str());
326 return NETMANAGER_ERROR;
327 }
328
329 return NETMANAGER_SUCCESS;
330 }
331
DisableVirnic(const std::string & virnicName)332 void DistributedManager::DisableVirnic(const std::string &virnicName)
333 {
334 std::string out;
335 std::string delVirnic = std::string(IP_CMD_PATH) + " link del " + virnicName;
336 NETNATIVE_LOGI("del virnic: %{public}s", delVirnic.c_str());
337 if (CommonUtils::ForkExec(delVirnic.c_str(), &out) != NETMANAGER_SUCCESS) {
338 NETNATIVE_LOGE("DisableVirnic del Virnic failed, output %{public}s", out.c_str());
339 }
340 }
341 } // namespace NetManagerStandard
342 } // namespace OHOS
343