1 /*
2 * Copyright (c) 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 "net_connection_ffi.h"
17 #include "net_all_capabilities.h"
18 #include "net_conn_client.h"
19 #include "net_connection_impl.h"
20 #include "net_handle.h"
21 #include "net_link_info.h"
22 #include "net_manager_constants.h"
23 #include "net_specifier.h"
24 #include <arpa/inet.h>
25 #include <netdb.h>
26
27 namespace OHOS::NetManagerStandard {
28
29 constexpr int32_t NO_PERMISSION_CODE = 1;
30 constexpr int32_t RESOURCE_UNAVALIEBLE_CODE = 11;
31 constexpr int32_t NET_UNREACHABLE_CODE = 101;
32 static constexpr size_t MAX_IPV4_STR_LEN = 16;
33 static constexpr size_t MAX_IPV6_STR_LEN = 64;
34
35 EXTERN_C_START
TransErrorCode(int32_t error)36 int32_t TransErrorCode(int32_t error)
37 {
38 switch (error) {
39 case NO_PERMISSION_CODE:
40 return NETMANAGER_ERR_PERMISSION_DENIED;
41 case RESOURCE_UNAVALIEBLE_CODE:
42 return NETMANAGER_ERR_INVALID_PARAMETER;
43 case NET_UNREACHABLE_CODE:
44 return NETMANAGER_ERR_INTERNAL;
45 default:
46 return NETMANAGER_ERR_OPERATION_FAILED;
47 }
48 }
49
CJ_CreateNetConnection(CNetSpecifier netSpecifier,uint32_t timeout)50 int64_t CJ_CreateNetConnection(CNetSpecifier netSpecifier, uint32_t timeout)
51 {
52 auto connection = FFI::FFIData::Create<NetConnectionProxy>(netSpecifier, timeout);
53 if (!connection) {
54 return ERR_INVALID_INSTANCE_CODE;
55 }
56 return connection->GetID();
57 }
58
CJ_ReleaseNetConnection(int64_t connId)59 void CJ_ReleaseNetConnection(int64_t connId)
60 {
61 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
62 if (!instance) {
63 return;
64 }
65 instance->Release();
66 FFI::FFIData::Release(connId);
67 }
68
CJ_GetDefaultNet(int32_t & netId)69 int32_t CJ_GetDefaultNet(int32_t &netId)
70 {
71 NetHandle netHandle;
72 auto ret = NetConnClient::GetInstance().GetDefaultNet(netHandle);
73 if (ret == NETMANAGER_SUCCESS) {
74 netId = netHandle.GetNetId();
75 }
76 return ret;
77 }
78
ParseAddrInfo(addrinfo * res,std::vector<CNetAddress> & addresses_)79 void ParseAddrInfo(addrinfo *res, std::vector<CNetAddress> &addresses_)
80 {
81 for (addrinfo *tmp = res; tmp != nullptr; tmp = tmp->ai_next) {
82 std::string host_;
83 if (tmp->ai_family == AF_INET) {
84 auto addr = reinterpret_cast<sockaddr_in *>(tmp->ai_addr);
85 char ip[MAX_IPV4_STR_LEN] = {0};
86 inet_ntop(AF_INET, &addr->sin_addr, ip, sizeof(ip));
87 host_ = ip;
88 } else if (tmp->ai_family == AF_INET6) {
89 auto addr = reinterpret_cast<sockaddr_in6 *>(tmp->ai_addr);
90 char ip[MAX_IPV6_STR_LEN] = {0};
91 inet_ntop(AF_INET6, &addr->sin6_addr, ip, sizeof(ip));
92 host_ = ip;
93 }
94
95 uint16_t port = 0;
96 if (tmp->ai_addr->sa_family == AF_INET) {
97 auto addr4 = reinterpret_cast<sockaddr_in *>(tmp->ai_addr);
98 port = addr4->sin_port;
99 } else if (tmp->ai_addr->sa_family == AF_INET6) {
100 auto addr6 = reinterpret_cast<sockaddr_in6 *>(tmp->ai_addr);
101 port = addr6->sin6_port;
102 }
103
104 CNetAddress address = {.address = MallocCString(host_), .family = tmp->ai_addr->sa_family, .port = port};
105 addresses_.emplace_back(address);
106 }
107 }
108
CJ_GetAddressesByName(int32_t netId,const char * host)109 RetNetAddressArr CJ_GetAddressesByName(int32_t netId, const char *host)
110 {
111 RetNetAddressArr ret = {.code = NETMANAGER_ERROR, .size = 0, .data = nullptr};
112 addrinfo *res = nullptr;
113 queryparam param;
114 param.qp_type = QEURY_TYPE_NORMAL;
115 param.qp_netid = netId;
116 int status = getaddrinfo_ext(host, nullptr, nullptr, &res, ¶m);
117 if (status < 0) {
118 ret.code = TransErrorCode(errno);
119 NETMANAGER_BASE_LOGE("getaddrinfo_ext errno %{public}d %{public}s", errno, strerror(errno));
120 return ret;
121 }
122 ret.code = status;
123
124 std::vector<CNetAddress> addresses_;
125 ParseAddrInfo(res, addresses_);
126 freeaddrinfo(res);
127
128 ret.size = static_cast<int64_t>(addresses_.size());
129 if (ret.size > 0) {
130 ret.data = static_cast<CNetAddress *>(malloc(sizeof(CNetAddress) * ret.size));
131 if (ret.data == nullptr) {
132 ret.code = NETMANAGER_ERR_INTERNAL;
133 return ret;
134 }
135 for (int64_t i = 0; i < ret.size; i++) {
136 ret.data[i] = CNetAddress(addresses_[i]);
137 }
138 }
139 return ret;
140 }
141
CJ_IsDefaultNetMetered(bool & ret)142 int32_t CJ_IsDefaultNetMetered(bool &ret)
143 {
144 ret = false;
145 return NetConnClient::GetInstance().IsDefaultNetMetered(ret);
146 }
147
CJ_HasDefaultNet(bool & ret)148 int32_t CJ_HasDefaultNet(bool &ret)
149 {
150 ret = false;
151 return NetConnClient::GetInstance().HasDefaultNet(ret);
152 }
153
CJ_GetNetCapabilities(int32_t netId,CNetCapabilities & ret)154 int32_t CJ_GetNetCapabilities(int32_t netId, CNetCapabilities &ret)
155 {
156 NetHandle netHandle{netId};
157 NetAllCapabilities capabilities;
158 auto code = NetConnClient::GetInstance().GetNetCapabilities(netHandle, capabilities);
159 if (code == NETMANAGER_SUCCESS) {
160 ret.linkUpBandwidthKbps = capabilities.linkUpBandwidthKbps_;
161 ret.linkDownBandwidthKbps = capabilities.linkDownBandwidthKbps_;
162 ret.bearedTypeSize = static_cast<int64_t>(capabilities.bearerTypes_.size());
163 ret.networkCapSize = static_cast<int64_t>(capabilities.netCaps_.size());
164 if (ret.bearedTypeSize > 0) {
165 ret.bearerTypes = static_cast<int32_t *>(malloc(sizeof(int32_t) * ret.bearedTypeSize));
166 if (ret.bearerTypes == nullptr) {
167 return NETMANAGER_ERR_INTERNAL;
168 }
169 int i = 0;
170 for (auto it = capabilities.bearerTypes_.begin(); it != capabilities.bearerTypes_.end(); ++it) {
171 ret.bearerTypes[i] = *it;
172 i++;
173 }
174 }
175 if (ret.networkCapSize > 0) {
176 ret.networkCap = static_cast<int32_t *>(malloc(sizeof(int32_t) * ret.networkCapSize));
177 if (ret.networkCap == nullptr) {
178 free(ret.bearerTypes);
179 return NETMANAGER_ERR_INTERNAL;
180 }
181 int i = 0;
182 for (auto it = capabilities.netCaps_.begin(); it != capabilities.netCaps_.end(); ++it) {
183 ret.networkCap[i] = *it;
184 i++;
185 }
186 }
187 }
188 return code;
189 }
190
SetLinkAddr(NetLinkInfo & linkInfo,CConnectionProperties & ret)191 bool SetLinkAddr(NetLinkInfo &linkInfo, CConnectionProperties &ret)
192 {
193 if (ret.linkAddressSize > 0) {
194 ret.linkAddresses = static_cast<CLinkAddress *>(malloc(sizeof(CLinkAddress) * ret.linkAddressSize));
195 if (ret.linkAddresses == nullptr) {
196 return false;
197 }
198 int i = 0;
199 for (auto it = linkInfo.netAddrList_.begin(); it != linkInfo.netAddrList_.end(); ++it, ++i) {
200 CNetAddress netAddr{.address = MallocCString(it->address_), .family = it->family_, .port = it->port_};
201 ret.linkAddresses[i] = CLinkAddress{.address = netAddr, .prefixLength = it->prefixlen_};
202 }
203 }
204 return true;
205 }
206
SetDns(NetLinkInfo & linkInfo,CConnectionProperties & ret)207 bool SetDns(NetLinkInfo &linkInfo, CConnectionProperties &ret)
208 {
209 if (ret.dnsSize > 0) {
210 ret.dnses = static_cast<CNetAddress *>(malloc(sizeof(CNetAddress) * ret.dnsSize));
211 if (ret.dnses == nullptr) {
212 free(ret.linkAddresses);
213 return false;
214 }
215 int i = 0;
216 for (auto it = linkInfo.dnsList_.begin(); it != linkInfo.dnsList_.end(); ++it, ++i) {
217 ret.dnses[i] =
218 CNetAddress{.address = MallocCString(it->address_), .family = it->family_, .port = it->port_};
219 }
220 }
221 return true;
222 }
223
SetRoute(NetLinkInfo & linkInfo,CConnectionProperties & ret)224 bool SetRoute(NetLinkInfo &linkInfo, CConnectionProperties &ret)
225 {
226 if (ret.routeSize > 0) {
227 ret.routes = static_cast<CRouteInfo *>(malloc(sizeof(CRouteInfo) * ret.routeSize));
228 if (ret.routes == nullptr) {
229 free(ret.linkAddresses);
230 free(ret.dnses);
231 return false;
232 }
233 int i = 0;
234
235 for (auto it = linkInfo.routeList_.begin(); it != linkInfo.routeList_.end(); ++it, ++i) {
236 CNetAddress destAddr = {.address = MallocCString(it->destination_.address_),
237 .family = it->destination_.family_,
238 .port = it->destination_.port_};
239 CLinkAddress dest = {.address = destAddr, .prefixLength = it->destination_.prefixlen_};
240 CNetAddress gateway = {.address = MallocCString(it->gateway_.address_),
241 .family = it->gateway_.family_,
242 .port = it->gateway_.port_};
243 ret.routes[i] = CRouteInfo{.interfaceName = MallocCString(it->iface_),
244 .destination = dest,
245 .gateway = gateway,
246 .hasGateway = it->hasGateway_,
247 .isDefaultRoute = it->isDefaultRoute_};
248 }
249 }
250 return true;
251 }
252
CJ_GetConnectionProperties(int32_t netId,CConnectionProperties & ret)253 int32_t CJ_GetConnectionProperties(int32_t netId, CConnectionProperties &ret)
254 {
255 NetHandle netHandle{netId};
256 NetLinkInfo linkInfo;
257 auto code = NetConnClient::GetInstance().GetConnectionProperties(netHandle, linkInfo);
258 if (code == NETMANAGER_SUCCESS) {
259 ret.interfaceName = MallocCString(linkInfo.ifaceName_);
260 ret.domains = MallocCString(linkInfo.domain_);
261 ret.mtu = linkInfo.mtu_;
262 ret.linkAddresses = nullptr;
263 ret.dnses = nullptr;
264 ret.routes = nullptr;
265 ret.linkAddressSize = static_cast<int64_t>(linkInfo.netAddrList_.size());
266 ret.dnsSize = static_cast<int64_t>(linkInfo.dnsList_.size());
267 ret.routeSize = static_cast<int64_t>(linkInfo.routeList_.size());
268
269 if (!SetLinkAddr(linkInfo, ret) || !SetDns(linkInfo, ret) || !SetRoute(linkInfo, ret)) {
270 return NETMANAGER_ERR_INTERNAL;
271 }
272 }
273 return code;
274 }
275
CJ_GetGlobalHttpProxy(CHttpProxy & chttpProxy)276 int32_t CJ_GetGlobalHttpProxy(CHttpProxy &chttpProxy)
277 {
278 HttpProxy httpProxy;
279 auto ret = NetConnClient::GetInstance().GetGlobalHttpProxy(httpProxy);
280 if (ret == NETMANAGER_SUCCESS) {
281 chttpProxy.host = MallocCString(httpProxy.GetHost());
282 chttpProxy.port = httpProxy.GetPort();
283 auto list = httpProxy.GetExclusionList();
284 chttpProxy.exclusionListSize = static_cast<int64_t>(list.size());
285 chttpProxy.exclusionList = MallocCStringList(list);
286 }
287 return ret;
288 }
289
CJ_GetDefaultHttpProxy(CHttpProxy & chttpProxy)290 int32_t CJ_GetDefaultHttpProxy(CHttpProxy &chttpProxy)
291 {
292 HttpProxy httpProxy;
293 auto ret = NetConnClient::GetInstance().GetDefaultHttpProxy(httpProxy);
294 if (ret == NETMANAGER_SUCCESS) {
295 chttpProxy.host = MallocCString(httpProxy.GetHost());
296 chttpProxy.port = httpProxy.GetPort();
297 auto list = httpProxy.GetExclusionList();
298 chttpProxy.exclusionListSize = static_cast<int64_t>(list.size());
299 chttpProxy.exclusionList = MallocCStringList(list);
300 }
301 return ret;
302 }
303
CJ_SetGlobalHttpProxy(CHttpProxy cHttpProxy)304 int32_t CJ_SetGlobalHttpProxy(CHttpProxy cHttpProxy)
305 {
306 std::string host(cHttpProxy.host);
307 std::string newHost = host;
308 std::list<std::string> exclusionList;
309 for (uint32_t i = 0; i < cHttpProxy.exclusionListSize; ++i) {
310 std::string tmp(cHttpProxy.exclusionList[i]);
311 std::string item = tmp;
312 exclusionList.push_back(item);
313 }
314 HttpProxy httpProxy(newHost, cHttpProxy.port, exclusionList);
315 return NetConnClient::GetInstance().SetGlobalHttpProxy(httpProxy);
316 }
317
CJ_GetAppNet(int32_t & netId)318 int32_t CJ_GetAppNet(int32_t &netId)
319 {
320 return NetConnClient::GetInstance().GetAppNet(netId);
321 }
322
CJ_SetAppNet(int32_t netId)323 int32_t CJ_SetAppNet(int32_t netId)
324 {
325 return NetConnClient::GetInstance().SetAppNet(netId);
326 }
327
CJ_GetAllNets()328 RetDataCArrI32 CJ_GetAllNets()
329 {
330 std::list<sptr<NetHandle>> netList;
331 auto code = NetConnClient::GetInstance().GetAllNets(netList);
332 CArrI32 data = {.head = nullptr, .size = 0 };
333 RetDataCArrI32 ret = {.code = code, .data = data};
334 if (code != NETMANAGER_SUCCESS) {
335 return ret;
336 }
337 auto listSize = netList.size();
338 ret.data.size = static_cast<int64_t>(listSize);
339 if (listSize > 0) {
340 int32_t *retValue = static_cast<int32_t *>(malloc(sizeof(int32_t) * listSize));
341 if (retValue == nullptr) {
342 ret.code = NETMANAGER_ERR_INTERNAL;
343 return ret;
344 }
345 int i = 0;
346 for (auto it = netList.begin(); it != netList.end(); ++it) {
347 NetHandle netHandle = *it->GetRefPtr();
348 retValue[i] = netHandle.GetNetId();
349 i++;
350 }
351 ret.data.head = retValue;
352 }
353
354 return ret;
355 }
356
CJ_EnableAirplaneMode()357 int32_t CJ_EnableAirplaneMode()
358 {
359 return NetConnClient::GetInstance().SetAirplaneMode(true);
360 }
361
CJ_DisableAirplaneMode()362 int32_t CJ_DisableAirplaneMode()
363 {
364 return NetConnClient::GetInstance().SetAirplaneMode(false);
365 }
366
CJ_ReportNetConnected(int32_t netId)367 int32_t CJ_ReportNetConnected(int32_t netId)
368 {
369 NetHandle netHandle{netId};
370 return NetConnClient::GetInstance().NetDetection(netHandle);
371 }
372
CJ_ReportNetDisconnected(int32_t netId)373 int32_t CJ_ReportNetDisconnected(int32_t netId)
374 {
375 NetHandle netHandle{netId};
376 return NetConnClient::GetInstance().NetDetection(netHandle);
377 }
378
CJ_NetHandleBindSocket(int32_t netId,int socketFd)379 int32_t CJ_NetHandleBindSocket(int32_t netId, int socketFd)
380 {
381 NetHandle handle(netId);
382 return handle.BindSocket(socketFd);
383 }
384
CJ_NetConnectionRegister(int64_t id)385 int32_t CJ_NetConnectionRegister(int64_t id)
386 {
387 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(id);
388 if (!instance) {
389 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, id);
390 return ERR_INVALID_INSTANCE_CODE;
391 }
392 return instance->RegisterCallback();
393 }
394
CJ_NetConnectionUnRegister(int64_t id)395 int32_t CJ_NetConnectionUnRegister(int64_t id)
396 {
397 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(id);
398 if (!instance) {
399 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, id);
400 return ERR_INVALID_INSTANCE_CODE;
401 }
402 return instance->UnregisterCallback();
403 }
404
CJ_OnNetAvailable(int64_t connId,void (* callback)(int32_t))405 void CJ_OnNetAvailable(int64_t connId, void (*callback)(int32_t))
406 {
407 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
408 if (!instance) {
409 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
410 return;
411 }
412 instance->OnNetAvailible(callback);
413 }
414
CJ_OnNetBlockStatusChange(int64_t connId,void (* callback)(int32_t,bool))415 void CJ_OnNetBlockStatusChange(int64_t connId, void (*callback)(int32_t, bool))
416 {
417 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
418 if (!instance) {
419 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
420 return;
421 }
422 instance->OnNetBlockStatusChange(callback);
423 }
424
CJ_OnNetCapabilitiesChange(int64_t connId,void (* callback)(CNetCapabilityInfo))425 void CJ_OnNetCapabilitiesChange(int64_t connId, void (*callback)(CNetCapabilityInfo))
426 {
427 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
428 if (!instance) {
429 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
430 return;
431 }
432 instance->OnNetCapabilitiesChange(callback);
433 }
434
CJ_OnNetConnectionPropertiesChange(int64_t connId,void (* callback)(int32_t,CConnectionProperties))435 void CJ_OnNetConnectionPropertiesChange(int64_t connId, void (*callback)(int32_t, CConnectionProperties))
436 {
437 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
438 if (!instance) {
439 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
440 return;
441 }
442 instance->OnNetConnectionPropertiesChange(callback);
443 }
444
CJ_OnNetLost(int64_t connId,void (* callback)(int32_t))445 void CJ_OnNetLost(int64_t connId, void (*callback)(int32_t))
446 {
447 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
448 if (!instance) {
449 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
450 return;
451 }
452 instance->OnNetLost(callback);
453 }
454
CJ_OnNetUnavailable(int64_t connId,void (* callback)())455 void CJ_OnNetUnavailable(int64_t connId, void (*callback)())
456 {
457 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
458 if (!instance) {
459 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
460 return;
461 }
462 instance->OnNetUnavailable(callback);
463 }
464
MallocCString(const std::string & origin)465 char *MallocCString(const std::string &origin)
466 {
467 if (origin.empty()) {
468 return nullptr;
469 }
470 auto len = origin.length() + 1;
471 char *res = static_cast<char *>(malloc(sizeof(char) * len));
472 if (res == nullptr) {
473 return nullptr;
474 }
475 return std::char_traits<char>::copy(res, origin.c_str(), len);
476 }
477
MallocCStringList(std::list<std::string> & list)478 char **MallocCStringList(std::list<std::string> &list)
479 {
480 auto size = list.size();
481 if (size <= 0) {
482 return nullptr;
483 }
484 auto arr = static_cast<char **>(malloc(sizeof(char *) * size));
485 if (arr == nullptr) {
486 return nullptr;
487 }
488 int i = 0;
489 for (auto it = list.begin(); it != list.end(); ++it) {
490 arr[i] = MallocCString(*it);
491 i++;
492 }
493 return arr;
494 }
495 EXTERN_C_END
496 } // namespace OHOS::NetManagerStandard