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