• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-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 <arpa/inet.h>
17 #include <cstring>
18 #include <fcntl.h>
19 #include <fstream>
20 #include <future>
21 #include <list>
22 #include <memory>
23 #include <netdb.h>
24 #include <regex>
25 #include <securec.h>
26 #include <sys/socket.h>
27 #include <thread>
28 #include <pthread.h>
29 #include <unistd.h>
30 #include <string>
31 
32 #include "net_monitor.h"
33 #include "dns_config_client.h"
34 #include "event_report.h"
35 #include "fwmark_client.h"
36 #include "netmanager_base_common_utils.h"
37 #include "netsys_controller.h"
38 #include "net_http_proxy_tracker.h"
39 #include "net_mgr_log_wrapper.h"
40 #include "net_manager_constants.h"
41 #include "tiny_count_down_latch.h"
42 
43 namespace OHOS {
44 namespace NetManagerStandard {
45 namespace {
46 constexpr int32_t INIT_DETECTION_DELAY_MS = 1 * 1000;
47 constexpr int32_t MAX_FAILED_DETECTION_DELAY_MS = 10 * 60 * 1000;
48 constexpr int32_t PRIMARY_DETECTION_RESULT_WAIT_MS = 3 * 1000;
49 constexpr int32_t ALL_DETECTION_RESULT_WAIT_MS = 10 * 1000;
50 constexpr int32_t CAPTIVE_PORTAL_DETECTION_DELAY_MS = 15 * 1000;
51 constexpr int32_t SCREENOFF_PORTAL_DETECTION_DELAY_MS = 5 * 60 * 1000;
52 constexpr int32_t DOUBLE = 2;
53 constexpr int32_t SIM_PORTAL_CODE = 302;
54 constexpr int32_t ONE_URL_DETECT_NUM = 4;
55 constexpr int32_t ALL_DETECT_THREAD_NUM = 8;
56 constexpr const char NEW_LINE_STR = '\n';
57 constexpr const char* URL_CFG_FILE = "/system/etc/netdetectionurl.conf";
58 constexpr const char* DETECT_CFG_FILE = "/system/etc/detectionconfig.conf";
59 constexpr const char *SETTINGS_DATASHARE_URI =
60         "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
61 constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
62 const std::string HTTP_URL_HEADER = "HttpProbeUrl:";
63 const std::string HTTPS_URL_HEADER = "HttpsProbeUrl:";
64 const std::string FALLBACK_HTTP_URL_HEADER = "FallbackHttpProbeUrl:";
65 const std::string FALLBACK_HTTPS_URL_HEADER = "FallbackHttpsProbeUrl:";
66 const std::string ADD_RANDOM_CFG_PREFIX = "AddSuffix:";
67 const std::string ADD_RANDOM_CFG_VALUE = "true";
68 } // namespace
NetDetectThread(const std::shared_ptr<NetMonitor> & netMonitor)69 static void NetDetectThread(const std::shared_ptr<NetMonitor> &netMonitor)
70 {
71     if (netMonitor == nullptr) {
72         NETMGR_LOG_E("netMonitor is nullptr");
73         return;
74     }
75     while (netMonitor->IsDetecting()) {
76         netMonitor->Detection();
77     }
78 }
79 
NetMonitor(uint32_t netId,NetBearType bearType,const NetLinkInfo & netLinkInfo,const std::weak_ptr<INetMonitorCallback> & callback,bool isScreenOn)80 NetMonitor::NetMonitor(uint32_t netId, NetBearType bearType, const NetLinkInfo &netLinkInfo,
81     const std::weak_ptr<INetMonitorCallback> &callback, bool isScreenOn)
82     : netId_(netId), netLinkInfo_(netLinkInfo), netMonitorCallback_(callback), isScreenOn_(isScreenOn)
83 {
84     netBearType_ = bearType;
85     LoadGlobalHttpProxy();
86     GetDetectUrlConfig();
87     GetHttpProbeUrlFromConfig();
88 }
89 
Start()90 void NetMonitor::Start()
91 {
92     NETMGR_LOG_D("Start net[%{public}d] monitor in", netId_);
93     if (isDetecting_) {
94         NETMGR_LOG_W("Net[%{public}d] monitor is detecting, no need to start", netId_);
95         return;
96     }
97     isDetecting_ = true;
98     std::thread t([sp = shared_from_this()]() { NetDetectThread(sp); });
99     std::string threadName = "netDetect";
100     pthread_setname_np(t.native_handle(), threadName.c_str());
101     t.detach();
102 }
103 
Stop()104 void NetMonitor::Stop()
105 {
106     NETMGR_LOG_I("Stop net[%{public}d] monitor in", netId_);
107     isDetecting_ = false;
108     detectionCond_.notify_all();
109     NETMGR_LOG_D("Stop net[%{public}d] monitor out", netId_);
110 }
111 
IsDetecting()112 bool NetMonitor::IsDetecting()
113 {
114     return isDetecting_.load();
115 }
116 
ProcessDetection(NetHttpProbeResult & probeResult,NetDetectionStatus & result)117 void NetMonitor::ProcessDetection(NetHttpProbeResult& probeResult, NetDetectionStatus& result)
118 {
119     if (probeResult.IsSuccessful()) {
120         NETMGR_LOG_I("Net[%{public}d] probe success", netId_);
121         isDetecting_ = false;
122         needDetectionWithoutProxy_ = true;
123         result = VERIFICATION_STATE;
124     } else if (probeResult.GetCode() == SIM_PORTAL_CODE && netBearType_ == BEARER_CELLULAR) {
125         NETMGR_LOG_E("Net[%{public}d] probe failed with 302 response on Cell", netId_);
126         detectionDelay_ = MAX_FAILED_DETECTION_DELAY_MS;
127         result = CAPTIVE_PORTAL_STATE;
128     } else if (probeResult.IsNeedPortal()) {
129         NETMGR_LOG_W("Net[%{public}d] need portal", netId_);
130         if (!isScreenOn_ && netBearType_ == BEARER_WIFI) {
131             detectionDelay_ = SCREENOFF_PORTAL_DETECTION_DELAY_MS;
132         } else {
133             detectionDelay_ = CAPTIVE_PORTAL_DETECTION_DELAY_MS;
134         }
135         result = CAPTIVE_PORTAL_STATE;
136     } else {
137         NETMGR_LOG_E("Net[%{public}d] probe failed", netId_);
138         detectionDelay_ *= DOUBLE;
139         if (detectionDelay_ == 0) {
140             detectionDelay_ = INIT_DETECTION_DELAY_MS;
141         } else if (detectionDelay_ >= MAX_FAILED_DETECTION_DELAY_MS) {
142             detectionDelay_ = MAX_FAILED_DETECTION_DELAY_MS;
143         }
144         NETMGR_LOG_I("Net probe failed detectionDelay time [%{public}d]", detectionDelay_);
145         result = INVALID_DETECTION_STATE;
146     }
147     auto monitorCallback = netMonitorCallback_.lock();
148     if (monitorCallback) {
149         monitorCallback->OnHandleNetMonitorResult(result, probeResult.GetRedirectUrl());
150     }
151     struct EventInfo eventInfo = {.monitorStatus = static_cast<int32_t>(result)};
152     EventReport::SendMonitorBehaviorEvent(eventInfo);
153     if (isDetecting_) {
154         std::unique_lock<std::mutex> locker(detectionMtx_);
155         detectionCond_.wait_for(locker, std::chrono::milliseconds(detectionDelay_));
156     }
157 }
158 
Detection()159 void NetMonitor::Detection()
160 {
161     NetHttpProbeResult probeResult = SendProbe();
162     if (isDetecting_) {
163         NetDetectionStatus result = UNKNOWN_STATE;
164         ProcessDetection(probeResult, result);
165     }
166 }
167 
SendProbe()168 NetHttpProbeResult NetMonitor::SendProbe()
169 {
170     NETMGR_LOG_I("start net detection");
171     std::lock_guard<std::mutex> monitorLocker(probeMtx_);
172     std::shared_ptr<TinyCountDownLatch> latch = std::make_shared<TinyCountDownLatch>(ONE_URL_DETECT_NUM);
173     std::shared_ptr<TinyCountDownLatch> latchAll = std::make_shared<TinyCountDownLatch>(ALL_DETECT_THREAD_NUM);
174     std::shared_ptr<ProbeThread> httpProxyThread = std::make_shared<ProbeThread>(
175         netId_, netBearType_, netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTP, httpUrl_, httpsUrl_);
176     std::shared_ptr<ProbeThread> httpsProxyThread = std::make_shared<ProbeThread>(
177         netId_, netBearType_, netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTPS, httpUrl_, httpsUrl_);
178     std::shared_ptr<ProbeThread> backHttpProxyThread = std::make_shared<ProbeThread>(netId_, netBearType_,
179         netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTP_FALLBACK, fallbackHttpUrl_, fallbackHttpsUrl_);
180     std::shared_ptr<ProbeThread> backHttpsProxyThread = std::make_shared<ProbeThread>(netId_, netBearType_,
181         netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTPS_FALLBACK, fallbackHttpUrl_, fallbackHttpsUrl_);
182     StartProbe(httpProxyThread, httpsProxyThread, backHttpProxyThread, backHttpsProxyThread, true);
183     latch->Await(std::chrono::milliseconds(PRIMARY_DETECTION_RESULT_WAIT_MS));
184     NetHttpProbeResult proxyResult = ProcessThreadDetectResult(httpProxyThread, httpsProxyThread, backHttpProxyThread,
185         backHttpsProxyThread);
186     if (proxyResult.IsNeedPortal() || proxyResult.IsSuccessful()) {
187         return proxyResult;
188     }
189     NETMGR_LOG_I("backup url detection");
190     std::shared_ptr<ProbeThread> httpNoProxyThread = std::make_shared<ProbeThread>(
191         netId_, netBearType_, netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTP, httpUrl_, httpsUrl_);
192     std::shared_ptr<ProbeThread> httpsNoProxyThread = std::make_shared<ProbeThread>(
193         netId_, netBearType_, netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTPS, httpUrl_, httpsUrl_);
194     std::shared_ptr<ProbeThread> backHttpNoProxyThread = std::make_shared<ProbeThread>(netId_, netBearType_,
195         netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTP_FALLBACK, fallbackHttpUrl_, fallbackHttpsUrl_);
196     std::shared_ptr<ProbeThread> backHttpsNoProxyThread = std::make_shared<ProbeThread>(netId_, netBearType_,
197         netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTPS_FALLBACK, fallbackHttpUrl_, fallbackHttpsUrl_);
198     StartProbe(httpNoProxyThread, httpsNoProxyThread, backHttpNoProxyThread, backHttpsNoProxyThread, false);
199     latchAll->Await(std::chrono::milliseconds(ALL_DETECTION_RESULT_WAIT_MS));
200     proxyResult = ProcessThreadDetectResult(httpProxyThread, httpsProxyThread, backHttpProxyThread,
201         backHttpsProxyThread);
202     NetHttpProbeResult noProxyResult = ProcessThreadDetectResult(httpNoProxyThread, httpsNoProxyThread,
203         backHttpNoProxyThread, backHttpsNoProxyThread);
204     if (proxyResult.IsNeedPortal()) {
205         return proxyResult;
206     } else if (noProxyResult.IsNeedPortal()) {
207         return noProxyResult;
208     } else if (proxyResult.IsSuccessful()) {
209         return proxyResult;
210     } else if (noProxyResult.IsSuccessful()) {
211         return noProxyResult;
212     } else {
213         return proxyResult;
214     }
215 }
216 
StartProbe(std::shared_ptr<ProbeThread> & httpProbeThread,std::shared_ptr<ProbeThread> & httpsProbeThread,std::shared_ptr<ProbeThread> & backHttpThread,std::shared_ptr<ProbeThread> & backHttpsThread,bool needProxy)217 void NetMonitor::StartProbe(std::shared_ptr<ProbeThread>& httpProbeThread,
218     std::shared_ptr<ProbeThread>& httpsProbeThread, std::shared_ptr<ProbeThread>& backHttpThread,
219     std::shared_ptr<ProbeThread>& backHttpsThread, bool needProxy)
220 {
221     if (needProxy) {
222         std::lock_guard<std::mutex> proxyLocker(proxyMtx_);
223         httpProbeThread->UpdateGlobalHttpProxy(globalHttpProxy_);
224         httpsProbeThread->UpdateGlobalHttpProxy(globalHttpProxy_);
225         backHttpThread->UpdateGlobalHttpProxy(globalHttpProxy_);
226         backHttpsThread->UpdateGlobalHttpProxy(globalHttpProxy_);
227     } else {
228         httpProbeThread->ProbeWithoutGlobalHttpProxy();
229         httpsProbeThread->ProbeWithoutGlobalHttpProxy();
230         backHttpThread->ProbeWithoutGlobalHttpProxy();
231         backHttpsThread->ProbeWithoutGlobalHttpProxy();
232     }
233     httpProbeThread->Start();
234     httpsProbeThread->Start();
235     backHttpThread->Start();
236     backHttpsThread->Start();
237 }
238 
GetThreadDetectResult(std::shared_ptr<ProbeThread> & probeThread,ProbeType probeType)239 NetHttpProbeResult NetMonitor::GetThreadDetectResult(std::shared_ptr<ProbeThread>& probeThread, ProbeType probeType)
240 {
241     NetHttpProbeResult result;
242     if (!probeThread->IsDetecting()) {
243         if (probeType == ProbeType::PROBE_HTTP || probeType == ProbeType::PROBE_HTTP_FALLBACK) {
244             return probeThread->GetHttpProbeResult();
245         } else {
246             return probeThread->GetHttpsProbeResult();
247         }
248     }
249     return result;
250 }
251 
ProcessThreadDetectResult(std::shared_ptr<ProbeThread> & httpProbeThread,std::shared_ptr<ProbeThread> & httpsProbeThread,std::shared_ptr<ProbeThread> & backHttpThread,std::shared_ptr<ProbeThread> & backHttpsThread)252 NetHttpProbeResult NetMonitor::ProcessThreadDetectResult(std::shared_ptr<ProbeThread>& httpProbeThread,
253     std::shared_ptr<ProbeThread>& httpsProbeThread, std::shared_ptr<ProbeThread>& backHttpThread,
254     std::shared_ptr<ProbeThread>& backHttpsThread)
255 {
256     NetHttpProbeResult httpResult = GetThreadDetectResult(httpProbeThread, ProbeType::PROBE_HTTP);
257     NetHttpProbeResult httpsResult = GetThreadDetectResult(httpsProbeThread, ProbeType::PROBE_HTTPS);
258     NetHttpProbeResult backHttpResult = GetThreadDetectResult(backHttpThread, ProbeType::PROBE_HTTP_FALLBACK);
259     NetHttpProbeResult backHttpsResult = GetThreadDetectResult(backHttpsThread, ProbeType::PROBE_HTTPS_FALLBACK);
260     if (httpResult.IsNeedPortal()) {
261         NETMGR_LOG_I("primary http detect result: portal");
262         return httpResult;
263     }
264     if (backHttpResult.IsNeedPortal()) {
265         NETMGR_LOG_I("fallback http detect result: portal");
266         return backHttpResult;
267     }
268     if (httpsResult.IsSuccessful()) {
269         NETMGR_LOG_I("primary https detect result: success");
270         return httpsResult;
271     }
272     if (backHttpsResult.IsSuccessful()) {
273         NETMGR_LOG_I("fallback https detect result: success");
274         return backHttpsResult;
275     }
276     if (httpResult.IsSuccessful() && backHttpResult.IsSuccessful()) {
277         NETMGR_LOG_I("both primary http and fallback http detect result success");
278         return httpResult;
279     }
280     return httpsResult;
281 }
282 
LoadGlobalHttpProxy()283 void NetMonitor::LoadGlobalHttpProxy()
284 {
285     if (!CheckIfSettingsDataReady()) {
286         NETMGR_LOG_E("data_share is not ready");
287         return;
288     }
289     NetHttpProxyTracker httpProxyTracker;
290     httpProxyTracker.ReadFromSettingsData(globalHttpProxy_);
291 }
292 
UpdateGlobalHttpProxy(const HttpProxy & httpProxy)293 void NetMonitor::UpdateGlobalHttpProxy(const HttpProxy &httpProxy)
294 {
295     std::unique_lock<std::mutex> proxyLocker(proxyMtx_);
296     globalHttpProxy_ = httpProxy;
297 }
298 
GetHttpProbeUrlFromConfig()299 void NetMonitor::GetHttpProbeUrlFromConfig()
300 {
301     if (!std::filesystem::exists(URL_CFG_FILE)) {
302         NETMGR_LOG_E("File not exist (%{public}s)", URL_CFG_FILE);
303         return;
304     }
305 
306     std::ifstream file(URL_CFG_FILE);
307     if (!file.is_open()) {
308         NETMGR_LOG_E("Open file failed (%{public}s)", strerror(errno));
309         return;
310     }
311 
312     std::ostringstream oss;
313     oss << file.rdbuf();
314     std::string content = oss.str();
315     auto pos = content.find(HTTP_URL_HEADER);
316     if (pos != std::string::npos) {
317         pos += HTTP_URL_HEADER.length();
318         httpUrl_ = content.substr(pos, content.find(NEW_LINE_STR, pos) - pos);
319         if (isNeedSuffix_) {
320             uint64_t ranNum = CommonUtils::GenRandomNumber();
321             httpUrl_ = httpUrl_ + std::string("_") + std::to_string(ranNum);
322         }
323     }
324 
325     pos = content.find(HTTPS_URL_HEADER);
326     if (pos != std::string::npos) {
327         pos += HTTPS_URL_HEADER.length();
328         httpsUrl_ = content.substr(pos, content.find(NEW_LINE_STR, pos) - pos);
329     }
330 
331     pos = content.find(FALLBACK_HTTP_URL_HEADER);
332     if (pos != std::string::npos) {
333         pos += FALLBACK_HTTP_URL_HEADER.length();
334         fallbackHttpUrl_ = content.substr(pos, content.find(NEW_LINE_STR, pos) - pos);
335     }
336 
337     pos = content.find(FALLBACK_HTTPS_URL_HEADER);
338     if (pos != std::string::npos) {
339         pos += FALLBACK_HTTPS_URL_HEADER.length();
340         fallbackHttpsUrl_ = content.substr(pos, content.find(NEW_LINE_STR, pos) - pos);
341     }
342     NETMGR_LOG_D("Get net detection http url:[%{public}s], https url:[%{public}s], fallback http url:[%{public}s],"
343         " fallback https url:[%{public}s]", httpUrl_.c_str(), httpsUrl_.c_str(), fallbackHttpUrl_.c_str(),
344         fallbackHttpsUrl_.c_str());
345 }
346 
GetDetectUrlConfig()347 void NetMonitor::GetDetectUrlConfig()
348 {
349     if (!std::filesystem::exists(DETECT_CFG_FILE)) {
350         NETMGR_LOG_E("File not exist (%{public}s)", DETECT_CFG_FILE);
351         return;
352     }
353 
354     std::ifstream file(DETECT_CFG_FILE);
355     if (!file.is_open()) {
356         NETMGR_LOG_E("Open file failed (%{public}s)", strerror(errno));
357         return;
358     }
359     std::ostringstream oss;
360     oss << file.rdbuf();
361     std::string content = oss.str();
362     auto pos = content.find(ADD_RANDOM_CFG_PREFIX);
363     if (pos != std::string::npos) {
364         pos += ADD_RANDOM_CFG_PREFIX.length();
365         std::string value = content.substr(pos, content.find(NEW_LINE_STR, pos) - pos);
366         value = CommonUtils::Trim(value);
367         isNeedSuffix_ = value.compare(ADD_RANDOM_CFG_VALUE) == 0;
368     }
369     NETMGR_LOG_I("is need add suffix (%{public}d)", isNeedSuffix_);
370 }
371 
CheckIfSettingsDataReady()372 bool NetMonitor::CheckIfSettingsDataReady()
373 {
374     if (isDataShareReady_) {
375         return true;
376     }
377     sptr<ISystemAbilityManager> saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
378     if (saManager == nullptr) {
379         NETMGR_LOG_E("GetSystemAbilityManager failed.");
380         return false;
381     }
382     sptr<IRemoteObject> dataShareSa = saManager->GetSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID);
383     if (dataShareSa == nullptr) {
384         NETMGR_LOG_E("Get dataShare SA Failed.");
385         return false;
386     }
387     sptr<IRemoteObject> remoteObj = saManager->GetSystemAbility(COMM_NET_CONN_MANAGER_SYS_ABILITY_ID);
388     if (remoteObj == nullptr) {
389         NETMGR_LOG_E("NetDataShareHelperUtils GetSystemAbility Service Failed.");
390         return false;
391     }
392     std::pair<int, std::shared_ptr<DataShare::DataShareHelper>> ret =
393             DataShare::DataShareHelper::Create(remoteObj, SETTINGS_DATASHARE_URI, SETTINGS_DATA_EXT_URI);
394     NETMGR_LOG_I("create data_share helper, ret=%{public}d", ret.first);
395     if (ret.first == DataShare::E_OK) {
396         NETMGR_LOG_I("create data_share helper success");
397         auto helper = ret.second;
398         if (helper != nullptr) {
399             bool releaseRet = helper->Release();
400             NETMGR_LOG_I("release data_share helper, releaseRet=%{public}d", releaseRet);
401         }
402         isDataShareReady_ = true;
403         return true;
404     } else if (ret.first == DataShare::E_DATA_SHARE_NOT_READY) {
405         NETMGR_LOG_E("create data_share helper failed");
406         isDataShareReady_ = false;
407         return false;
408     }
409     NETMGR_LOG_E("data_share unknown.");
410     return true;
411 }
412 
SetScreenState(bool isScreenOn)413 void NetMonitor::SetScreenState(bool isScreenOn)
414 {
415     isScreenOn_ = isScreenOn;
416 }
417 } // namespace NetManagerStandard
418 } // namespace OHOS
419