• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "securec.h"
27 #include "if_config.h"
28 #include "ip_tools.h"
29 #include <thread>
30 
31 namespace OHOS {
32 namespace Wifi {
33 const std::string SYSTEM_COMMAND_IP = "/system/bin/ip";
34 const int SYSTEM_COMMAND_ERR = -1;
35 const int SYSTEM_NOT_EXECUTED = 127;
36 const int RECEIVE_BUFFER_LEN = 64;
37 
GetInstance()38 IfConfig &IfConfig::GetInstance()
39 {
40     static IfConfig ifConfig;
41     return ifConfig;
42 }
43 
IfConfig()44 IfConfig::IfConfig()
45 {}
46 
~IfConfig()47 IfConfig::~IfConfig()
48 {}
49 
SyncExecuteCommand(const std::string & cmd)50 bool IfConfig::SyncExecuteCommand(const std::string& cmd)
51 {
52     int ret = system(cmd.c_str());
53     if (ret == SYSTEM_COMMAND_ERR || ret == SYSTEM_NOT_EXECUTED) {
54         LOGE("exec failed. cmd: %s, error:%{public}d", cmd.c_str(), errno);
55         return false;
56     }
57     LOGI("Exec cmd end - sync");
58     return true;
59 }
60 
AsyncExecuteCommand(const std::string & cmd)61 bool IfConfig::AsyncExecuteCommand(const std::string& cmd)
62 {
63     std::thread t(
64         [cmd]() {
65             FILE *fp = nullptr;
66             char buffer[RECEIVE_BUFFER_LEN];
67             if ((fp = popen(cmd.c_str(), "r")) != nullptr) {
68                 while (fgets(buffer, sizeof(buffer), fp) != nullptr) {
69                     LOGD("exec cmd receive: %{public}s", buffer);
70                 }
71                 pclose(fp);
72             } else {
73                 LOGE("exec cmd popen error!");
74             }
75             LOGI("Exec cmd end - async");
76         }
77     );
78     t.detach();
79     return true;
80 }
81 
82 /**
83  * @Description : Execute script commands
84  * @Return success:true failed:false
85  */
ExecCommand(const std::vector<std::string> & vecCommandArg)86 bool IfConfig::ExecCommand(const std::vector<std::string> &vecCommandArg)
87 {
88     std::string command;
89     for (auto iter : vecCommandArg) {
90         command += iter;
91         command += " ";
92     }
93     LOGI("Exec cmd start: [%s]", command.c_str());
94     return AsyncExecuteCommand(command);
95 }
96 
97 /**
98  * @Description : Flush the IpAddr
99  * @Return None
100  */
FlushIpAddr(const std::string & ifName,const int & ipType)101 void IfConfig::FlushIpAddr(const std::string& ifName, const int& ipType)
102 {
103     LOGI("Flush IP, ifName: %{public}s", ifName.c_str());
104 
105     if (ipType != static_cast<int>(IpType::IPTYPE_IPV4)) {
106         return;
107     }
108     struct ifreq ifr;
109     if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK ||
110         strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifName.c_str()) != EOK) {
111         LOGE("Init the ifreq stuct failed!");
112         return;
113     }
114     int fd = socket(AF_INET, SOCK_DGRAM, 0);
115     if (fd < 0) {
116         LOGE("AddIpAddr:socket error");
117         return;
118     }
119     struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr);
120     sin->sin_family = AF_INET;
121     /* ipAddr */
122     if (inet_aton("0.0.0.0", &(sin->sin_addr)) < 0) {
123         LOGE("AddIpAddr:inet_aton error");
124         close(fd);
125         return;
126     }
127     if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) {
128         LOGE("AddIpAddr:ioctl SIOCSIFADDR error");
129         close(fd);
130         return;
131     }
132     close(fd);
133     return;
134 }
135 
136 /**
137  * @Description : Add the IpAddr
138  * @Return None
139  */
AddIpAddr(const std::string & ifName,const std::string & ipAddr,const std::string & mask,const int & ipType)140 void IfConfig::AddIpAddr(
141     const std::string &ifName, const std::string &ipAddr, const std::string &mask, const int &ipType)
142 {
143     LOGI("Add ip address, ifName = %{public}s", ifName.c_str());
144 
145     if (!CheckIfaceValid(ifName)) {
146         return;
147     }
148     if (ipType == static_cast<int>(IpType::IPTYPE_IPV4)) {
149         struct ifreq ifr;
150         if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK ||
151             strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifName.c_str()) != EOK) {
152             LOGE("set ifr info failed!");
153             return;
154         }
155 
156         struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr);
157         sin->sin_family = AF_INET;
158 
159         // ipAddr
160         if (inet_aton(ipAddr.c_str(), &(sin->sin_addr)) < 0) {
161             LOGE("inet_aton   error\n");
162             return;
163         }
164 
165         int fd = socket(AF_INET, SOCK_DGRAM, 0);
166         if (fd < 0) {
167             LOGE("socket error\n");
168             return;
169         }
170 
171         if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) {
172             LOGE("ioctl   SIOCSIFADDR   error\n");
173             close(fd);
174             return;
175         }
176 
177         // netMask
178         if (inet_aton(mask.c_str(), &(sin->sin_addr)) < 0) {
179             LOGE("inet_pton   error\n");
180             close(fd);
181             return;
182         }
183 
184         if (ioctl(fd, SIOCSIFNETMASK, &ifr) < 0) {
185             LOGE("ioctl SIOCSIFNETMASK error");
186             close(fd);
187             return;
188         }
189         close(fd);
190     } else {
191         std::vector<std::string> ipRouteCmd;
192         ipRouteCmd.clear();
193         ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
194         ipRouteCmd.push_back("-6");
195         ipRouteCmd.push_back("addr");
196         ipRouteCmd.push_back("add");
197         ipRouteCmd.push_back(ipAddr);
198         ipRouteCmd.push_back("dev");
199         ipRouteCmd.push_back(ifName);
200         ExecCommand(ipRouteCmd);
201     }
202 
203     return;
204 }
205 
206 /**
207  * @Description : set proxy
208  * @param isAuto - whether to automatically proxy[in]
209  * @param proxy - proxy host name[in]
210  * @param port - port[in]
211  * @param noProxys - objects to bypass proxy[in]
212  * @Return None
213  */
SetProxy(bool isAuto,const std::string & proxy,const std::string & port,const std::string & noProxys,const std::string & pac)214 void IfConfig::SetProxy(
215     bool isAuto, const std::string &proxy, const std::string &port, const std::string &noProxys, const std::string &pac)
216 {
217     LOGI("SetProxy pac=[%s]\n", pac.c_str());
218     std::vector<std::string> ipRouteCmd;
219 
220     if (!isAuto) {
221         // Add proxy
222         if (!proxy.empty()) {
223             ipRouteCmd.clear();
224             ipRouteCmd.push_back("export");
225             ipRouteCmd.push_back("http_proxy=" + proxy + ":" + port);
226             ExecCommand(ipRouteCmd);
227         }
228 
229         // Bypass proxy
230         if (!noProxys.empty()) {
231             ipRouteCmd.clear();
232             ipRouteCmd.push_back("export");
233             ipRouteCmd.push_back("no_proxy=" + noProxys);
234             ExecCommand(ipRouteCmd);
235         }
236     }
237     return;
238 }
239 
GetIpAddr(const std::string & ifName,std::string & ipAddr)240 bool IfConfig::GetIpAddr(const std::string& ifName, std::string& ipAddr)
241 {
242     struct ifreq ifr;
243     if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK ||
244         strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifName.c_str()) != EOK) {
245         LOGE("set ifr info failed!");
246         return false;
247     }
248     int fd = socket(AF_INET, SOCK_DGRAM, 0);
249     if (fd < 0) {
250         LOGE("socket error\n");
251         return false;
252     }
253     if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
254         perror("ioctl error!\n");
255         close(fd);
256         return false;
257     }
258     struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr);
259     ipAddr = inet_ntoa(sin->sin_addr);
260     close(fd);
261     return true;
262 }
263 
CheckIfaceValid(const std::string & ifname)264 bool IfConfig::CheckIfaceValid(const std::string& ifname)
265 {
266     struct if_nameindex *ifidxs, *ifni;
267 
268     ifidxs = if_nameindex();
269     if (ifidxs == nullptr) {
270         LOGE("can not get interfaces");
271         return false;
272     }
273     for (ifni = ifidxs; !(ifni->if_index == 0 && ifni->if_name == nullptr); ifni++) {
274         if (strncmp(ifni->if_name, ifname.c_str(), strlen(ifni->if_name)) == 0) {
275             if_freenameindex(ifidxs);
276             return true;
277         }
278     }
279     if_freenameindex(ifidxs);
280     LOGE("invalid interface: %{public}s", ifname.c_str());
281     return false;
282 }
283 }  // namespace Wifi
284 }  // namespace OHOS