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
33 namespace OHOS {
34 namespace Wifi {
35 const std::string SYSTEM_COMMAND_IP = "/system/bin/ip";
36 const int EXECVE_EXT_COMMAND = 127;
37 const int RECEIVE_BUFFER_LEN = 64;
38 const int MAX_COMMAND_ARG = 32;
39 #ifdef OHOS_ARCH_LITE
40 const std::string SYSTEM_COMMAND_NDC = "/system/bin/ndc";
41 const std::string IFNAME = "wlan0";
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 = 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)305 int IfConfig::SetIfDnsAndRoute(const DhcpResult &dhcpResult, int ipType)
306 {
307 LOGD("ipType=%d, ip=%s, gateway=%s, subnet=%s, strDns1=%s, strDns2=%s",
308 dhcpResult.iptype,
309 dhcpResult.strYourCli.c_str(),
310 dhcpResult.strSubnet.c_str(),
311 dhcpResult.strRouter1.c_str(),
312 dhcpResult.strDns1.c_str(),
313 dhcpResult.strDns2.c_str());
314 SetNetDns(IFNAME, dhcpResult.strDns1, dhcpResult.strDns2);
315 AddIfRoute(IFNAME, dhcpResult.strYourCli, dhcpResult.strSubnet, dhcpResult.strRouter1, ipType);
316 LOGI("set dns and route finished!");
317 return 0;
318 }
319
320 /**
321 * @Description : Set DNS
322 * @Return None
323 */
SetNetDns(const std::string & ifName,const std::string & dns1,const std::string & dns2)324 void IfConfig::SetNetDns(const std::string& ifName, const std::string& dns1, const std::string& dns2)
325 {
326 std::vector<std::string> ipRouteCmd;
327 ipRouteCmd.clear();
328 ipRouteCmd.push_back(SYSTEM_COMMAND_NDC);
329 ipRouteCmd.push_back("resolver");
330 ipRouteCmd.push_back("setnetdns");
331 ipRouteCmd.push_back(ifName);
332 ipRouteCmd.push_back("");
333 if (Ipv4Address::IsValidIPv4(dns1) || Ipv6Address::IsValidIPv6(dns1)) {
334 ipRouteCmd.push_back(dns1);
335 }
336 if (Ipv4Address::IsValidIPv4(dns2) || Ipv6Address::IsValidIPv6(dns2)) {
337 ipRouteCmd.push_back(dns2);
338 }
339 ExecCommand(ipRouteCmd);
340 return;
341 }
342
343 /**
344 * @Description : Add Route
345 * @Return None
346 */
AddIfRoute(const std::string & ifName,const std::string & ipAddr,const std::string & mask,const std::string & gateWay,const int & ipType)347 void IfConfig::AddIfRoute(const std::string &ifName, const std::string &ipAddr, const std::string &mask,
348 const std::string &gateWay, const int &ipType)
349 {
350 if (ipType == static_cast<int>(IpType::IPTYPE_IPV4)) {
351 AddIpv4Route(ifName, ipAddr, mask, gateWay);
352 } else {
353 AddIpv6Route(ifName, ipAddr, mask, gateWay);
354 }
355 return;
356 }
357
358 /**
359 * @Description : set Ipv4 Route
360 * @Return None
361 */
AddIpv4Route(const std::string & ifName,const std::string & ipAddr,const std::string & mask,const std::string & gateWay)362 void IfConfig::AddIpv4Route(
363 const std::string &ifName, const std::string &ipAddr, const std::string &mask, const std::string &gateWay)
364 {
365 LOGI("Enter AddIpv4Route, ifName is %{public}s, ipAddr is %{private}s, mask is %s, gateWay is %{private}s",
366 ifName.c_str(),
367 ipAddr.c_str(),
368 mask.c_str(),
369 gateWay.c_str());
370
371 struct rtentry route;
372 if (memset_s(&route, sizeof(route), 0, sizeof(route)) != EOK) {
373 LOGE("memset_s route info failed!");
374 return;
375 }
376
377 struct sockaddr_in *addr = reinterpret_cast<struct sockaddr_in *>(&route.rt_gateway);
378 addr->sin_family = AF_INET;
379 if (inet_aton(gateWay.c_str(), &(addr->sin_addr)) < 0) {
380 LOGE("inet_aton error\n");
381 return;
382 }
383 addr = reinterpret_cast<struct sockaddr_in *>(&route.rt_dst);
384 addr->sin_family = AF_INET;
385 addr->sin_addr.s_addr = INADDR_ANY;
386 addr = reinterpret_cast<struct sockaddr_in *>(&route.rt_genmask);
387 addr->sin_family = AF_INET;
388 addr->sin_addr.s_addr = INADDR_ANY;
389 char strIfName[MAX_IFNAME_LEN + 1] = {0};
390 if (strcpy_s(strIfName, sizeof(strIfName), ifName.c_str()) != EOK) {
391 LOGE("strcpy_s error\n");
392 return;
393 }
394 route.rt_dev = strIfName;
395 route.rt_flags = RTF_UP | RTF_GATEWAY;
396 route.rt_metric = 0;
397
398 int fd = socket(AF_INET, SOCK_DGRAM, 0);
399 if (fd < 0) {
400 LOGE("socket error\n");
401 return;
402 }
403 if (ioctl(fd, SIOCADDRT, &route) < 0) {
404 LOGE("ioctl SIOCADDRT error");
405 }
406 close(fd);
407 return;
408 }
409
410 /**
411 * @Description : set Ipv6 Route
412 * @Return None
413 */
AddIpv6Route(const std::string & ifName,const std::string & ipAddr,const std::string & mask,const std::string & gateWay)414 void IfConfig::AddIpv6Route(
415 const std::string &ifName, const std::string &ipAddr, const std::string &mask, const std::string &gateWay)
416 {
417 std::vector<std::string> ipRouteCmd;
418 ipRouteCmd.clear();
419 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
420 ipRouteCmd.push_back("-6 rule add");
421 ipRouteCmd.push_back("fwmark");
422 ipRouteCmd.push_back("0x0/0xffff");
423 ipRouteCmd.push_back("lookup");
424 ipRouteCmd.push_back("254");
425 ipRouteCmd.push_back("prio");
426 ipRouteCmd.push_back("17000");
427 ExecCommand(ipRouteCmd);
428 // Add routing network segment
429 ipRouteCmd.clear();
430 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
431 ipRouteCmd.push_back("-6 route add");
432 ipRouteCmd.push_back(mask + ipAddr.substr(ipAddr.length() - IPV6_SUFFIX_LEN, ipAddr.length()));
433 ipRouteCmd.push_back("dev");
434 ipRouteCmd.push_back(ifName);
435 ipRouteCmd.push_back("table");
436 ipRouteCmd.push_back("254");
437 ExecCommand(ipRouteCmd);
438 // Delete the default gateway
439 ipRouteCmd.clear();
440 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
441 ipRouteCmd.push_back("-6 route del default");
442 ipRouteCmd.push_back("dev");
443 ipRouteCmd.push_back(ifName);
444 ipRouteCmd.push_back("table");
445 ipRouteCmd.push_back("254");
446 ExecCommand(ipRouteCmd);
447 // Add the default gateway
448 ipRouteCmd.clear();
449 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
450 ipRouteCmd.push_back("-6 route add default");
451 ipRouteCmd.push_back("via");
452 ipRouteCmd.push_back(gateWay);
453 ipRouteCmd.push_back("dev");
454 ipRouteCmd.push_back(ifName);
455 ipRouteCmd.push_back("table");
456 ipRouteCmd.push_back("254");
457 ExecCommand(ipRouteCmd);
458 // Flush routing cache
459 ipRouteCmd.clear();
460 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
461 ipRouteCmd.push_back("-6 route flush cache");
462 ExecCommand(ipRouteCmd);
463 }
464 #endif
465 } // namespace Wifi
466 } // namespace OHOS
467