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