• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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