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 <linux/if.h>
21 #include <linux/if_tun.h>
22 #include <linux/ipv6.h>
23 #include <netinet/in.h>
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <sys/un.h>
28 #include <thread>
29 #include <unistd.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 = 32;
43 constexpr int32_t DISTRIBUTED_MTU = 1400;
44 } // namespace
45 
CreateDistributedInterface(const std::string &ifName)46 int32_t DistributedManager::CreateDistributedInterface(const std::string &ifName)
47 {
48     net4Sock_ = socket(AF_INET, SOCK_DGRAM, 0);
49     if (net4Sock_ < 0) {
50         NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
51         return NETMANAGER_ERROR;
52     }
53 
54     if (tunFd_ != 0) {
55         return NETMANAGER_SUCCESS;
56     }
57 
58     ifreq ifr{};
59     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
60         return NETMANAGER_ERROR;
61     }
62 
63     int32_t tunfd = open(DISTRIBUTED_TUN_DEVICE_PATH, O_RDWR | O_NONBLOCK);
64     if (tunfd <= 0) {
65         NETNATIVE_LOGE("open virtual distributed nic failed: %{public}d", errno);
66         return NETMANAGER_ERROR;
67     }
68 
69     ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
70     if (ioctl(tunfd, TUNSETIFF, &ifr) < 0) {
71         close(tunfd);
72         NETNATIVE_LOGE("tun set iff error: %{public}d", errno);
73         return NETMANAGER_ERROR;
74     }
75 
76     NETNATIVE_LOGI("create virtual device successfully, [%{public}d]", tunfd);
77     tunFd_ = tunfd;
78 
79     return NETMANAGER_SUCCESS;
80 }
81 
SetDistributedNicResult(std::atomic_int &fd, unsigned long cmd, ifreq &ifr)82 int32_t DistributedManager::SetDistributedNicResult(std::atomic_int &fd, unsigned long cmd, ifreq &ifr)
83 {
84     if (fd > 0) {
85         if (ioctl(fd, cmd, &ifr) < 0) {
86             NETNATIVE_LOGE("set virnic error, errno:%{public}d", errno);
87             return NETMANAGER_ERROR;
88         }
89         return NETMANAGER_SUCCESS;
90     }
91     return NETMANAGER_ERROR;
92 }
93 
InitIfreq(ifreq &ifr, const std::string &cardName)94 int32_t DistributedManager::InitIfreq(ifreq &ifr, const std::string &cardName)
95 {
96     if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
97         NETNATIVE_LOGE("memset_s ifr failed!");
98         return NETMANAGER_ERROR;
99     }
100     if (strncpy_s(ifr.ifr_name, IFNAMSIZ, cardName.c_str(), strlen(cardName.c_str())) != EOK) {
101         NETNATIVE_LOGE("strcpy_s ifr name fail");
102         return NETMANAGER_ERROR;
103     }
104     return NETMANAGER_SUCCESS;
105 }
106 
SetDistributedNicMtu(const std::string &ifName, int32_t mtu)107 int32_t DistributedManager::SetDistributedNicMtu(const std::string &ifName, int32_t mtu)
108 {
109     if (mtu <= 0) {
110         NETNATIVE_LOGE("invalid mtu value");
111         return NETMANAGER_ERROR;
112     }
113 
114     ifreq ifr{};
115     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
116         return NETMANAGER_ERROR;
117     }
118 
119     ifr.ifr_mtu = mtu;
120     int32_t ret4 = SetDistributedNicResult(net4Sock_, SIOCSIFMTU, ifr);
121     if (ret4 == NETMANAGER_ERROR || (net4Sock_ < 0)) {
122         NETNATIVE_LOGI("set MTU failed");
123         return NETMANAGER_ERROR;
124     } else {
125         NETNATIVE_LOGI("set MTU success");
126         return NETMANAGER_SUCCESS;
127     }
128 }
129 
SetDistributedNicAddress(const std::string &ifName, const std::string &tunAddr)130 int32_t DistributedManager::SetDistributedNicAddress(const std::string &ifName, const std::string &tunAddr)
131 {
132     ifreq ifr{};
133     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
134         return NETMANAGER_ERROR;
135     }
136 
137     bool isIpv6 = CommonUtils::IsValidIPV6(tunAddr);
138     if (isIpv6) {
139         NETNATIVE_LOGE("distributed nic not support ipv6 by now");
140         return NETMANAGER_ERROR;
141     } else {
142         in_addr ipv4Addr = {};
143         if (inet_aton(tunAddr.c_str(), &ipv4Addr) == 0) {
144             NETNATIVE_LOGE("addr inet_aton error");
145             return NETMANAGER_ERROR;
146         }
147 
148         auto sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_addr);
149         sin->sin_family = AF_INET;
150         sin->sin_addr = ipv4Addr;
151         if (ioctl(net4Sock_, SIOCSIFADDR, &ifr) < 0) {
152             NETNATIVE_LOGE("ioctl set ipv4 address failed: %{public}d", errno);
153             return NETMANAGER_ERROR;
154         }
155 
156         int32_t prefix = NET_MASK_MAX_LENGTH;
157         in_addr_t mask = prefix ? (0xFFFFFFFF << (NET_MASK_MAX_LENGTH - prefix)) : 0;
158         sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_netmask);
159         sin->sin_family = AF_INET;
160         sin->sin_addr.s_addr = htonl(mask);
161         if (ioctl(net4Sock_, SIOCSIFNETMASK, &ifr) < 0) {
162             NETNATIVE_LOGE("ioctl set ip mask failed: %{public}d", errno);
163             return NETMANAGER_ERROR;
164         }
165     }
166 
167     NETNATIVE_LOGI("set ip address success");
168     return NETMANAGER_SUCCESS;
169 }
170 
SetDistributedNicUp(const std::string &ifName)171 int32_t DistributedManager::SetDistributedNicUp(const std::string &ifName)
172 {
173     ifreq ifr{};
174     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
175         return NETMANAGER_ERROR;
176     }
177 
178     ifr.ifr_flags = static_cast<uint16_t>(IFF_UP | IFF_NOARP);
179 
180     int32_t ret4 = SetDistributedNicResult(net4Sock_, SIOCSIFFLAGS, ifr);
181     if (ret4 == NETMANAGER_ERROR || (net4Sock_ < 0)) {
182         NETNATIVE_LOGI("set iff up failed");
183         return NETMANAGER_ERROR;
184     } else {
185         NETNATIVE_LOGI("set iff up success");
186         return NETMANAGER_SUCCESS;
187     }
188 }
189 
SetDistributedNicDown(const std::string &ifName)190 int32_t DistributedManager::SetDistributedNicDown(const std::string &ifName)
191 {
192     ifreq ifr{};
193     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
194         return NETMANAGER_ERROR;
195     }
196 
197     ifr.ifr_flags = (uint16_t)ifr.ifr_flags & ~IFF_UP;
198     int32_t ret4 = SetDistributedNicResult(net4Sock_, SIOCSIFFLAGS, ifr);
199     if (ret4 == NETMANAGER_ERROR || (net4Sock_ < 0)) {
200         NETNATIVE_LOGI("set iff down failed");
201         return NETMANAGER_ERROR;
202     } else {
203         NETNATIVE_LOGI("set iff down success");
204         return NETMANAGER_SUCCESS;
205     }
206 }
207 
CloseDistributedSocket()208 void DistributedManager::CloseDistributedSocket()
209 {
210     if (net4Sock_ > 0) {
211         close(net4Sock_);
212         net4Sock_ = 0;
213     }
214 }
215 
CloseDistributedTunFd()216 void DistributedManager::CloseDistributedTunFd()
217 {
218     if (tunFd_ > 0) {
219         close(tunFd_);
220         tunFd_ = 0;
221     }
222 }
223 
CreateDistributedNic(const std::string &virNicAddr, const std::string &ifName)224 int32_t DistributedManager::CreateDistributedNic(const std::string &virNicAddr, const std::string &ifName)
225 {
226     NETNATIVE_LOGI("CreateVirnic, mtu:%{public}d", DISTRIBUTED_MTU);
227     if (CreateDistributedInterface(ifName) != NETMANAGER_SUCCESS) {
228         CloseDistributedSocket();
229         return NETMANAGER_ERROR;
230     }
231     if (SetDistributedNicMtu(ifName, DISTRIBUTED_MTU) != NETMANAGER_SUCCESS ||
232         SetDistributedNicAddress(ifName, virNicAddr) != NETMANAGER_SUCCESS) {
233         SetDistributedNicDown(ifName);
234         CloseDistributedSocket();
235         return NETMANAGER_ERROR;
236     }
237     if (SetDistributedNicUp(ifName) != NETMANAGER_SUCCESS) {
238         CloseDistributedSocket();
239         return NETMANAGER_ERROR;
240     }
241     CloseDistributedSocket();
242 
243     return NETMANAGER_SUCCESS;
244 }
245 
DestroyDistributedNic(const std::string &ifName)246 int32_t DistributedManager::DestroyDistributedNic(const std::string &ifName)
247 {
248     SetDistributedNicDown(ifName);
249     return NETMANAGER_SUCCESS;
250 }
251 
SetServerNicInfo(const std::string &iif, const std::string &devIface)252 void DistributedManager::SetServerNicInfo(const std::string &iif, const std::string &devIface)
253 {
254     serverIif_ = iif;
255     serverDevIface_ = devIface;
256 }
257 
GetServerIifNic()258 std::string DistributedManager::GetServerIifNic()
259 {
260     return serverIif_;
261 }
262 
GetServerDevIfaceNic()263 std::string DistributedManager::GetServerDevIfaceNic()
264 {
265     return serverDevIface_;
266 }
267 
268 } // namespace NetManagerStandard
269 } // namespace OHOS
270