1 /*
2 * Copyright (C) 2021-2022 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 <unistd.h>
17 #include <arpa/inet.h>
18 #include <net/if.h>
19 #include <net/route.h>
20 #include <netinet/in.h>
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <iostream>
25 #include <vector>
26 #include <thread>
27 #include "securec.h"
28 #include "if_config.h"
29 #include "ip_tools.h"
30 #include "ipv4_address.h"
31 #include "ipv6_address.h"
32 #include "wifi_config_center.h"
33
34 namespace OHOS {
35 namespace Wifi {
36 const std::string SYSTEM_COMMAND_IP = "/system/bin/ip";
37 const int EXECVE_EXT_COMMAND = 127;
38 const int RECEIVE_BUFFER_LEN = 64;
39 const int MAX_COMMAND_ARG = 32;
40 #ifdef OHOS_ARCH_LITE
41 const std::string SYSTEM_COMMAND_NDC = "/system/bin/ndc";
42 const int IPV6_SUFFIX_LEN = 3;
43 const int MAX_IFNAME_LEN = 13;
44 #endif
45
GetInstance()46 IfConfig &IfConfig::GetInstance()
47 {
48 static IfConfig ifConfig;
49 return ifConfig;
50 }
51
IfConfig()52 IfConfig::IfConfig()
53 {}
54
~IfConfig()55 IfConfig::~IfConfig()
56 {}
57
58 /**
59 * @Description : Execute script commands
60 * @Return success:true failed:false
61 */
ExecCommand(const std::vector<std::string> & vecCommandArg)62 bool IfConfig::ExecCommand(const std::vector<std::string> &vecCommandArg)
63 {
64 int argvSize = static_cast<int>(vecCommandArg.size());
65 if (argvSize > MAX_COMMAND_ARG) {
66 LOGE("IfConfig ExecCommand vecCommandArg size invalid.");
67 return false;
68 }
69 std::thread t(
70 [vecCommandArg, argvSize]() {
71 int fd[2] = {0};
72 if (pipe(fd) < 0) {
73 LOGE("ifconfig create pipe failed.");
74 return;
75 }
76 int pid = fork();
77 if (pid == -1) {
78 LOGE("ifconfig fork child process failed.");
79 return;
80 }
81 if (pid == 0) {
82 const char *execveStr[MAX_COMMAND_ARG];
83 int i = 0;
84 for (i = 0; i < argvSize && i < (MAX_COMMAND_ARG - 1); i++) {
85 execveStr[i] = vecCommandArg[i].c_str();
86 }
87 execveStr[i] = nullptr;
88 char *env[] = {nullptr};
89 close(fd[0]);
90 dup2(fd[1], STDOUT_FILENO);
91 close(fd[1]);
92 /* last member of execveStr should be nullptr */
93 if (execve(vecCommandArg[0].c_str(), (char *const*)execveStr, env) < 0) {
94 LOGE("execve %{public}s failed.", vecCommandArg[0].c_str());
95 }
96 _exit(EXECVE_EXT_COMMAND);
97 }
98 close(fd[1]);
99 FILE *fp = fdopen(fd[0], "r");
100 if (fp == nullptr) {
101 LOGE("ifconfig fdopen failed.");
102 return;
103 }
104 char buffer[RECEIVE_BUFFER_LEN];
105 while (fgets(buffer, sizeof(buffer), fp) != nullptr) {
106 LOGD("exec cmd receive: %{public}s", buffer);
107 }
108 fclose(fp);
109 }
110 );
111 t.detach();
112 return true;
113 }
114
115 /**
116 * @Description : Flush the IpAddr
117 * @Return None
118 */
FlushIpAddr(const std::string & ifName,const int & ipType)119 void IfConfig::FlushIpAddr(const std::string& ifName, const int& ipType)
120 {
121 LOGI("Flush IP, ifName: %{public}s", ifName.c_str());
122
123 if (ipType != static_cast<int>(IpType::IPTYPE_IPV4)) {
124 return;
125 }
126 struct ifreq ifr;
127 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK ||
128 strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifName.c_str()) != EOK) {
129 LOGE("Init the ifreq struct failed!");
130 return;
131 }
132 int fd = socket(AF_INET, SOCK_DGRAM, 0);
133 if (fd < 0) {
134 LOGE("AddIpAddr:socket error");
135 return;
136 }
137 struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr);
138 sin->sin_family = AF_INET;
139 /* ipAddr */
140 if (inet_aton("0.0.0.0", &(sin->sin_addr)) < 0) {
141 LOGE("AddIpAddr:inet_aton error");
142 close(fd);
143 return;
144 }
145 if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) {
146 LOGE("AddIpAddr:ioctl SIOCSIFADDR error");
147 close(fd);
148 return;
149 }
150 close(fd);
151 return;
152 }
153
154 /**
155 * @Description : Add the IpAddr
156 * @Return None
157 */
AddIpAddr(const std::string & ifName,const std::string & ipAddr,const std::string & mask,const int & ipType)158 void IfConfig::AddIpAddr(
159 const std::string &ifName, const std::string &ipAddr, const std::string &mask, const int &ipType)
160 {
161 LOGI("Add ip address, ifName = %{public}s", ifName.c_str());
162
163 if (!CheckIfaceValid(ifName)) {
164 return;
165 }
166 if (ipType == static_cast<int>(IpType::IPTYPE_IPV4)) {
167 struct ifreq ifr;
168 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK ||
169 strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifName.c_str()) != EOK) {
170 LOGE("set ifr info failed!");
171 return;
172 }
173
174 struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr);
175 sin->sin_family = AF_INET;
176
177 // ipAddr
178 if (inet_aton(ipAddr.c_str(), &(sin->sin_addr)) < 0) {
179 LOGE("inet_aton error\n");
180 return;
181 }
182
183 int fd = socket(AF_INET, SOCK_DGRAM, 0);
184 if (fd < 0) {
185 LOGE("socket error\n");
186 return;
187 }
188
189 if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) {
190 LOGE("ioctl SIOCSIFADDR error\n");
191 close(fd);
192 return;
193 }
194
195 // netMask
196 if (inet_aton(mask.c_str(), &(sin->sin_addr)) < 0) {
197 LOGE("inet_pton error\n");
198 close(fd);
199 return;
200 }
201
202 if (ioctl(fd, SIOCSIFNETMASK, &ifr) < 0) {
203 LOGE("ioctl SIOCSIFNETMASK error");
204 close(fd);
205 return;
206 }
207 close(fd);
208 } else {
209 std::vector<std::string> ipRouteCmd;
210 ipRouteCmd.clear();
211 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
212 ipRouteCmd.push_back("-6");
213 ipRouteCmd.push_back("addr");
214 ipRouteCmd.push_back("add");
215 ipRouteCmd.push_back(ipAddr);
216 ipRouteCmd.push_back("dev");
217 ipRouteCmd.push_back(ifName);
218 ExecCommand(ipRouteCmd);
219 }
220
221 return;
222 }
223
224 /**
225 * @Description : set proxy
226 * @param isAuto - whether to automatically proxy[in]
227 * @param proxy - proxy host name[in]
228 * @param port - port[in]
229 * @param noProxys - objects to bypass proxy[in]
230 * @Return None
231 */
SetProxy(bool isAuto,const std::string & proxy,const std::string & port,const std::string & noProxys,const std::string & pac)232 void IfConfig::SetProxy(
233 bool isAuto, const std::string &proxy, const std::string &port, const std::string &noProxys, const std::string &pac)
234 {
235 LOGI("SetProxy pac=[%s]\n", pac.c_str());
236 std::vector<std::string> ipRouteCmd;
237
238 if (!isAuto) {
239 // Add proxy
240 if (!proxy.empty()) {
241 ipRouteCmd.clear();
242 ipRouteCmd.push_back("export");
243 ipRouteCmd.push_back("http_proxy=" + proxy + ":" + port);
244 }
245
246 // Bypass proxy
247 if (!noProxys.empty()) {
248 ipRouteCmd.clear();
249 ipRouteCmd.push_back("export");
250 ipRouteCmd.push_back("no_proxy=" + noProxys);
251 }
252 }
253 return;
254 }
255
GetIpAddr(const std::string & ifName,std::string & ipAddr)256 bool IfConfig::GetIpAddr(const std::string& ifName, std::string& ipAddr)
257 {
258 struct ifreq ifr;
259 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK ||
260 strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifName.c_str()) != EOK) {
261 LOGE("set ifr info failed!");
262 return false;
263 }
264 int fd = socket(AF_INET, SOCK_DGRAM, 0);
265 if (fd < 0) {
266 LOGE("socket error\n");
267 return false;
268 }
269 if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
270 perror("ioctl error!\n");
271 close(fd);
272 return false;
273 }
274 struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr);
275 ipAddr = inet_ntoa(sin->sin_addr);
276 close(fd);
277 return true;
278 }
279
CheckIfaceValid(const std::string & ifname)280 bool IfConfig::CheckIfaceValid(const std::string& ifname)
281 {
282 struct if_nameindex *ifidxs, *ifni;
283 ifidxs = if_nameindex();
284 if (ifidxs == nullptr) {
285 LOGE("can not get interfaces");
286 return false;
287 }
288 for (ifni = ifidxs; !(ifni->if_index == 0 && ifni->if_name == nullptr); ifni++) {
289 if ((ifni->if_name != nullptr) &&
290 strcmp(ifni->if_name, ifname.c_str()) == 0) {
291 if_freenameindex(ifidxs);
292 return true;
293 }
294 }
295 if_freenameindex(ifidxs);
296 LOGE("invalid interface: %{public}s", ifname.c_str());
297 return false;
298 }
299
300 #ifdef OHOS_ARCH_LITE
301 /**
302 * @Description : Set the network card routing, DNS
303 * @Return success:0 failed:-1
304 */
SetIfDnsAndRoute(const DhcpResult * dhcpResult,int ipType,int instId)305 int IfConfig::SetIfDnsAndRoute(const DhcpResult *dhcpResult, int ipType, int instId)
306 {
307 LOGD("ipType=%d, ip=%s, gateway=%s, subnet=%s, strDns1=%s, strDns2=%s",
308 dhcpResult->iptype,
309 dhcpResult->strOptClientId,
310 dhcpResult->strOptSubnet,
311 dhcpResult->strOptRouter1,
312 dhcpResult->strOptDns1,
313 dhcpResult->strOptDns2);
314 SetNetDns(WifiConfigCenter::GetInstance().GetStaIfaceName(), dhcpResult->strOptDns1, dhcpResult->strOptDns2);
315 AddIfRoute(WifiConfigCenter::GetInstance().GetStaIfaceName(), dhcpResult->strOptClientId, dhcpResult->strOptSubnet,
316 dhcpResult->strOptRouter1, ipType);
317 LOGI("set dns and route finished!");
318 return 0;
319 }
320
321 /**
322 * @Description : Set DNS
323 * @Return None
324 */
SetNetDns(const std::string & ifName,const std::string & dns1,const std::string & dns2)325 void IfConfig::SetNetDns(const std::string& ifName, const std::string& dns1, const std::string& dns2)
326 {
327 std::vector<std::string> ipRouteCmd;
328 ipRouteCmd.clear();
329 ipRouteCmd.push_back(SYSTEM_COMMAND_NDC);
330 ipRouteCmd.push_back("resolver");
331 ipRouteCmd.push_back("setnetdns");
332 ipRouteCmd.push_back(ifName);
333 ipRouteCmd.push_back("");
334 if (Ipv4Address::IsValidIPv4(dns1) || Ipv6Address::IsValidIPv6(dns1)) {
335 ipRouteCmd.push_back(dns1);
336 }
337 if (Ipv4Address::IsValidIPv4(dns2) || Ipv6Address::IsValidIPv6(dns2)) {
338 ipRouteCmd.push_back(dns2);
339 }
340 ExecCommand(ipRouteCmd);
341 return;
342 }
343
344 /**
345 * @Description : Add Route
346 * @Return None
347 */
AddIfRoute(const std::string & ifName,const std::string & ipAddr,const std::string & mask,const std::string & gateWay,const int & ipType)348 void IfConfig::AddIfRoute(const std::string &ifName, const std::string &ipAddr, const std::string &mask,
349 const std::string &gateWay, const int &ipType)
350 {
351 if (ipType == static_cast<int>(IpType::IPTYPE_IPV4)) {
352 AddIpv4Route(ifName, ipAddr, mask, gateWay);
353 } else {
354 AddIpv6Route(ifName, ipAddr, mask, gateWay);
355 }
356 return;
357 }
358
359 /**
360 * @Description : set Ipv4 Route
361 * @Return None
362 */
AddIpv4Route(const std::string & ifName,const std::string & ipAddr,const std::string & mask,const std::string & gateWay)363 void IfConfig::AddIpv4Route(
364 const std::string &ifName, const std::string &ipAddr, const std::string &mask, const std::string &gateWay)
365 {
366 LOGI("Enter AddIpv4Route, ifName is %{public}s, ipAddr is %{private}s, mask is %s, gateWay is %{private}s",
367 ifName.c_str(),
368 ipAddr.c_str(),
369 mask.c_str(),
370 gateWay.c_str());
371
372 struct rtentry route;
373 if (memset_s(&route, sizeof(route), 0, sizeof(route)) != EOK) {
374 LOGE("memset_s route info failed!");
375 return;
376 }
377
378 struct sockaddr_in *addr = reinterpret_cast<struct sockaddr_in *>(&route.rt_gateway);
379 addr->sin_family = AF_INET;
380 if (inet_aton(gateWay.c_str(), &(addr->sin_addr)) < 0) {
381 LOGE("inet_aton error\n");
382 return;
383 }
384 addr = reinterpret_cast<struct sockaddr_in *>(&route.rt_dst);
385 addr->sin_family = AF_INET;
386 addr->sin_addr.s_addr = INADDR_ANY;
387 addr = reinterpret_cast<struct sockaddr_in *>(&route.rt_genmask);
388 addr->sin_family = AF_INET;
389 addr->sin_addr.s_addr = INADDR_ANY;
390 char strIfName[MAX_IFNAME_LEN + 1] = {0};
391 if (strcpy_s(strIfName, sizeof(strIfName), ifName.c_str()) != EOK) {
392 LOGE("strcpy_s error\n");
393 return;
394 }
395 route.rt_dev = strIfName;
396 route.rt_flags = RTF_UP | RTF_GATEWAY;
397 route.rt_metric = 0;
398
399 int fd = socket(AF_INET, SOCK_DGRAM, 0);
400 if (fd < 0) {
401 LOGE("socket error\n");
402 return;
403 }
404 if (ioctl(fd, SIOCADDRT, &route) < 0) {
405 LOGE("ioctl SIOCADDRT error");
406 }
407 close(fd);
408 return;
409 }
410
411 /**
412 * @Description : set Ipv6 Route
413 * @Return None
414 */
AddIpv6Route(const std::string & ifName,const std::string & ipAddr,const std::string & mask,const std::string & gateWay)415 void IfConfig::AddIpv6Route(
416 const std::string &ifName, const std::string &ipAddr, const std::string &mask, const std::string &gateWay)
417 {
418 std::vector<std::string> ipRouteCmd;
419 ipRouteCmd.clear();
420 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
421 ipRouteCmd.push_back("-6 rule add");
422 ipRouteCmd.push_back("fwmark");
423 ipRouteCmd.push_back("0x0/0xffff");
424 ipRouteCmd.push_back("lookup");
425 ipRouteCmd.push_back("254");
426 ipRouteCmd.push_back("prio");
427 ipRouteCmd.push_back("17000");
428 ExecCommand(ipRouteCmd);
429 // Add routing network segment
430 ipRouteCmd.clear();
431 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
432 ipRouteCmd.push_back("-6 route add");
433 ipRouteCmd.push_back(mask + ipAddr.substr(ipAddr.length() - IPV6_SUFFIX_LEN, ipAddr.length()));
434 ipRouteCmd.push_back("dev");
435 ipRouteCmd.push_back(ifName);
436 ipRouteCmd.push_back("table");
437 ipRouteCmd.push_back("254");
438 ExecCommand(ipRouteCmd);
439 // Delete the default gateway
440 ipRouteCmd.clear();
441 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
442 ipRouteCmd.push_back("-6 route del default");
443 ipRouteCmd.push_back("dev");
444 ipRouteCmd.push_back(ifName);
445 ipRouteCmd.push_back("table");
446 ipRouteCmd.push_back("254");
447 ExecCommand(ipRouteCmd);
448 // Add the default gateway
449 ipRouteCmd.clear();
450 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
451 ipRouteCmd.push_back("-6 route add default");
452 ipRouteCmd.push_back("via");
453 ipRouteCmd.push_back(gateWay);
454 ipRouteCmd.push_back("dev");
455 ipRouteCmd.push_back(ifName);
456 ipRouteCmd.push_back("table");
457 ipRouteCmd.push_back("254");
458 ExecCommand(ipRouteCmd);
459 // Flush routing cache
460 ipRouteCmd.clear();
461 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
462 ipRouteCmd.push_back("-6 route flush cache");
463 ExecCommand(ipRouteCmd);
464 }
465 #endif
466 } // namespace Wifi
467 } // namespace OHOS
468