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, &param);
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