• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "setup_context_ext.h"
17 
18 #include <new>
19 #include <string>
20 #include <vector>
21 
22 #include "inet_addr.h"
23 #include "napi_utils.h"
24 #include "net_manager_constants.h"
25 #include "netmanager_base_common_utils.h"
26 #include "netmgr_ext_log_wrapper.h"
27 #include "vpn_config_utils_ext.h"
28 
29 namespace OHOS {
30 namespace NetManagerStandard {
31 namespace {
32 constexpr uint8_t NET_FAMILY_IPV4 = 1;
33 constexpr uint8_t NET_FAMILY_IPV6 = 2;
34 constexpr int32_t NET_MASK_MAX_LENGTH = 32;
35 constexpr int32_t IPV6_NET_PREFIX_MAX_LENGTH = 128;
36 constexpr int32_t PARAM_JUST_OPTIONS = 1;
37 constexpr int32_t PARAM_OPTIONS_AND_CALLBACK = 2;
38 constexpr const char *CONFIG_ADDRESSES = "addresses";
39 constexpr const char *CONFIG_ROUTES = "routes";
40 constexpr const char *NET_ADDRESS = "address";
41 constexpr const char *NET_FAMILY = "family";
42 constexpr const char *NET_PORT = "port";
43 constexpr const char *NET_PREFIXLENGTH = "prefixLength";
44 constexpr const char *NET_INTERFACE = "interface";
45 constexpr const char *NET_DESTINATION = "destination";
46 constexpr const char *NET_GATEWAY = "gateway";
47 constexpr const char *NET_HAS_GATEWAY = "hasGateway";
48 constexpr const char *NET_ISDEFAULTROUTE = "isDefaultRoute";
49 constexpr const char *NET_ISEXCLUDEDROUTE = "isExcludedRoute";
50 constexpr const char *CONFIG_DNSADDRESSES = "dnsAddresses";
51 constexpr const char *CONFIG_SEARCHDOMAINS = "searchDomains";
52 constexpr const char *CONFIG_MTU = "mtu";
53 constexpr const char *CONFIG_ISIPV4ACCEPTED = "isIPv4Accepted";
54 constexpr const char *CONFIG_ISIPV6ACCEPTED = "isIPv6Accepted";
55 constexpr const char *CONFIG_ISLEGACY = "isLegacy";
56 constexpr const char *CONFIG_ISMETERED = "isMetered";
57 constexpr const char *CONFIG_ISBLOCKING = "isBlocking";
58 constexpr const char *CONFIG_TRUSTEDAPPLICATIONS = "trustedApplications";
59 constexpr const char *CONFIG_BLOCKEDAPPLICATIONS = "blockedApplications";
CheckParamsType(napi_env env,napi_value * params,size_t paramsCount)60 bool CheckParamsType(napi_env env, napi_value *params, size_t paramsCount)
61 {
62     switch (paramsCount) {
63         case PARAM_JUST_OPTIONS:
64             return (NapiUtils::GetValueType(env, params[0]) == napi_object);
65         case PARAM_OPTIONS_AND_CALLBACK:
66             return ((NapiUtils::GetValueType(env, params[0]) == napi_object) &&
67                     (NapiUtils::GetValueType(env, params[1]) == napi_function));
68         default:
69             return false;
70     }
71 }
72 
GetStringFromJsMandatoryItem(napi_env env,napi_value object,const std::string & key,std::string & value)73 bool GetStringFromJsMandatoryItem(napi_env env, napi_value object, const std::string &key, std::string &value)
74 {
75     if (NapiUtils::GetValueType(env, NapiUtils::GetNamedProperty(env, object, key)) != napi_string) {
76         NETMGR_EXT_LOG_E("param [%{public}s] type is mismatch", key.c_str());
77         return false;
78     }
79     value = NapiUtils::GetStringPropertyUtf8(env, object, key);
80     return (value.empty()) ? false : true;
81 }
82 
GetStringFromJsOptionItem(napi_env env,napi_value object,const std::string & key,std::string & value)83 void GetStringFromJsOptionItem(napi_env env, napi_value object, const std::string &key, std::string &value)
84 {
85     if (NapiUtils::HasNamedProperty(env, object, key)) {
86         if (NapiUtils::GetValueType(env, NapiUtils::GetNamedProperty(env, object, key)) == napi_string) {
87             value = NapiUtils::GetStringPropertyUtf8(env, object, key);
88             NETMGR_EXT_LOG_I("%{public}s: %{public}s", key.c_str(), value.c_str());
89         } else {
90             NETMGR_EXT_LOG_E("param [%{public}s] type is mismatch", key.c_str());
91         }
92     }
93 }
94 
GetUint8FromJsOptionItem(napi_env env,napi_value object,const std::string & key,uint8_t & value)95 void GetUint8FromJsOptionItem(napi_env env, napi_value object, const std::string &key, uint8_t &value)
96 {
97     if (NapiUtils::HasNamedProperty(env, object, key)) {
98         if (NapiUtils::GetValueType(env, NapiUtils::GetNamedProperty(env, object, key)) == napi_number) {
99             value = static_cast<uint8_t>(NapiUtils::GetUint32Property(env, object, key));
100             NETMGR_EXT_LOG_I("%{public}s: %{public}d", key.c_str(), value);
101         } else {
102             NETMGR_EXT_LOG_E("param [%{public}s] type is mismatch", key.c_str());
103         }
104     }
105 }
106 
GetBoolFromJsOptionItem(napi_env env,napi_value object,const std::string & key,bool & value)107 void GetBoolFromJsOptionItem(napi_env env, napi_value object, const std::string &key, bool &value)
108 {
109     if (NapiUtils::HasNamedProperty(env, object, key)) {
110         if (NapiUtils::GetValueType(env, NapiUtils::GetNamedProperty(env, object, key)) == napi_boolean) {
111             value = NapiUtils::GetBooleanProperty(env, object, key);
112             NETMGR_EXT_LOG_I("%{public}s: %{public}d", key.c_str(), value);
113         } else {
114             NETMGR_EXT_LOG_E("param [%{public}s] type is mismatch", key.c_str());
115         }
116     }
117 }
118 } // namespace
119 
SetUpContext(napi_env env,std::shared_ptr<EventManager> & manager)120 SetUpContext::SetUpContext(napi_env env, std::shared_ptr<EventManager>& manager) : BaseContext(env, manager) {}
121 
ParseParams(napi_value * params,size_t paramsCount)122 void SetUpContext::ParseParams(napi_value *params, size_t paramsCount)
123 {
124     if (!CheckParamsType(GetEnv(), params, paramsCount)) {
125         NETMGR_EXT_LOG_E("params type is mismatch");
126         SetNeedThrowException(true);
127         SetErrorCode(NETMANAGER_EXT_ERR_PARAMETER_ERROR);
128         return;
129     }
130     if (!ParseVpnConfig(params)) {
131         NETMGR_EXT_LOG_E("parse vpn config from js failed");
132         SetNeedThrowException(true);
133         SetErrorCode(NETMANAGER_EXT_ERR_PARAMETER_ERROR);
134         return;
135     }
136     if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
137         SetParseOK(SetCallback(params[1]) == napi_ok);
138         return;
139     }
140     SetParseOK(true);
141 }
142 
ParseVpnConfig(napi_value * params)143 bool SetUpContext::ParseVpnConfig(napi_value *params)
144 {
145 #ifdef SUPPORT_SYSVPN
146     if (params == nullptr) {
147         NETMGR_EXT_LOG_E("params is nullptr");
148         return false;
149     }
150     if (NapiUtils::HasNamedProperty(GetEnv(), params[0], VpnConfigUtilsExt::CONFIG_VPN_TYPE)) {
151         if (!VpnConfigUtilsExt::ParseSysVpnConfig(GetEnv(), params, sysVpnConfig_)) {
152             NETMGR_EXT_LOG_E("ParsesysVpnconfig is failed");
153             return false;
154         }
155         NETMGR_EXT_LOG_I("setup parse sysvpn config, id=%{public}s, type=%{public}d",
156             sysVpnConfig_->vpnId_.c_str(), sysVpnConfig_->vpnType_);
157         return true;
158     } else if (NapiUtils::HasNamedProperty(GetEnv(), params[0], VpnConfigUtilsExt::CONFIG_VPN_ID)) {
159         vpnConfig_ = new (std::nothrow) VpnConfig();
160         if (vpnConfig_ == nullptr) {
161             NETMGR_EXT_LOG_E("vpnConfig is nullptr");
162             return false;
163         }
164         vpnConfig_->vpnId_ = NapiUtils::GetStringPropertyUtf8(GetEnv(), params[0], VpnConfigUtilsExt::CONFIG_VPN_ID);
165         NETMGR_EXT_LOG_I("setup parse vpn config, id=%{public}s", vpnConfig_->vpnId_.c_str());
166         if (!ParseAddrRouteParams(params[0]) || !ParseChoiceableParams(params[0])) {
167             return false;
168         }
169         return true;
170     }
171 #endif // SUPPORT_SYSVPN
172     vpnConfig_ = new (std::nothrow) VpnConfig();
173     if (vpnConfig_ == nullptr) {
174         NETMGR_EXT_LOG_E("vpnConfig is nullptr");
175         return false;
176     }
177     if (!ParseAddrRouteParams(params[0]) || !ParseChoiceableParams(params[0])) {
178         return false;
179     }
180     return true;
181 }
182 
ParseAddressFamily(napi_env env,napi_value netAddress,uint8_t & family)183 static bool ParseAddressFamily(napi_env env, napi_value netAddress, uint8_t &family)
184 {
185     // The value is 1 for IPv4 and 2 for IPv6. The default value is 1.
186     if (!NapiUtils::HasNamedProperty(env, netAddress, NET_FAMILY)) {
187         family = NET_FAMILY_IPV4;
188         return true;
189     }
190     GetUint8FromJsOptionItem(env, netAddress, NET_FAMILY, family);
191     if (family == NET_FAMILY_IPV4 || family == NET_FAMILY_IPV6) {
192         return true;
193     } else {
194         NETMGR_EXT_LOG_E("family %{public}u is mismatch", family);
195         return false;
196     }
197 }
198 
ParseAddress(napi_env env,napi_value address,struct INetAddr & iNetAddr)199 static bool ParseAddress(napi_env env, napi_value address, struct INetAddr &iNetAddr)
200 {
201     napi_value netAddress = NapiUtils::GetNamedProperty(env, address, NET_ADDRESS);
202     if (NapiUtils::GetValueType(env, netAddress) != napi_object) {
203         NETMGR_EXT_LOG_E("param address type is mismatch");
204         return false;
205     }
206 
207     if (!GetStringFromJsMandatoryItem(env, netAddress, NET_ADDRESS, iNetAddr.address_)) {
208         NETMGR_EXT_LOG_E("get address-address failed");
209         return false;
210     }
211 
212     bool isIpv6 = CommonUtils::IsValidIPV6(iNetAddr.address_);
213     if (!isIpv6) {
214         if (!CommonUtils::IsValidIPV4(iNetAddr.address_)) {
215             NETMGR_EXT_LOG_E("invalid ip address");
216             return false;
217         }
218     }
219 
220     if (!ParseAddressFamily(env, netAddress, iNetAddr.family_)) {
221         return false;
222     }
223     GetUint8FromJsOptionItem(env, netAddress, NET_PORT, iNetAddr.port_);
224 
225     if (NapiUtils::GetValueType(env, NapiUtils::GetNamedProperty(env, address, NET_PREFIXLENGTH)) != napi_number) {
226         NETMGR_EXT_LOG_E("param [%{public}s] type is mismatch", NET_PREFIXLENGTH);
227         return false;
228     }
229     iNetAddr.prefixlen_ = static_cast<uint8_t>(NapiUtils::GetUint32Property(env, address, NET_PREFIXLENGTH));
230     if (isIpv6 && iNetAddr.prefixlen_ == 0) {
231         iNetAddr.prefixlen_ = CommonUtils::Ipv6PrefixLen(iNetAddr.address_);
232     }
233 
234     NETMGR_EXT_LOG_I("isIpv6:%{public}d, %{public}s: %{public}d", isIpv6, NET_PREFIXLENGTH, iNetAddr.prefixlen_);
235 
236     uint32_t prefix = iNetAddr.prefixlen_;
237     if (prefix == 0 || prefix > (isIpv6 ? IPV6_NET_PREFIX_MAX_LENGTH : NET_MASK_MAX_LENGTH)) {
238         NETMGR_EXT_LOG_E("prefix: %{public}d error", prefix);
239         return false;
240     }
241     if (!isIpv6 && prefix != NET_MASK_MAX_LENGTH) {
242         uint32_t maskUint = (0xFFFFFFFF << (NET_MASK_MAX_LENGTH - prefix));
243         uint32_t ipAddrUint = CommonUtils::ConvertIpv4Address(iNetAddr.address_);
244         uint32_t subNetAddress = ipAddrUint & maskUint;
245         uint32_t boardcastAddress = subNetAddress | (~maskUint);
246         if ((ipAddrUint == subNetAddress) || (ipAddrUint == boardcastAddress)) {
247             NETMGR_EXT_LOG_E("invalid ip address");
248             return false;
249         }
250     }
251     return true;
252 }
253 
ParseDestination(napi_env env,napi_value jsRoute,struct INetAddr & iNetAddr)254 static bool ParseDestination(napi_env env, napi_value jsRoute, struct INetAddr &iNetAddr)
255 {
256     napi_value destination = NapiUtils::GetNamedProperty(env, jsRoute, NET_DESTINATION);
257     if (NapiUtils::GetValueType(env, destination) != napi_object) {
258         NETMGR_EXT_LOG_E("param destination type is mismatch");
259         return false;
260     }
261 
262     napi_value netAddress = NapiUtils::GetNamedProperty(env, destination, NET_ADDRESS);
263     if (NapiUtils::GetValueType(env, netAddress) != napi_object) {
264         NETMGR_EXT_LOG_E("param address type is mismatch");
265         return false;
266     }
267 
268     if (!GetStringFromJsMandatoryItem(env, netAddress, NET_ADDRESS, iNetAddr.address_)) {
269         NETMGR_EXT_LOG_E("get destination-address failed");
270         return false;
271     }
272 
273     if (!CommonUtils::IsValidIPV4(iNetAddr.address_) && !CommonUtils::IsValidIPV6(iNetAddr.address_)) {
274         NETMGR_EXT_LOG_E("invalid ip address");
275         return false;
276     }
277     if (!ParseAddressFamily(env, netAddress, iNetAddr.family_)) {
278         return false;
279     }
280     GetUint8FromJsOptionItem(env, netAddress, NET_PORT, iNetAddr.port_);
281     GetUint8FromJsOptionItem(env, destination, NET_PREFIXLENGTH, iNetAddr.prefixlen_);
282     return true;
283 }
284 
ParseGateway(napi_env env,napi_value jsRoute,struct INetAddr & iNetAddr)285 static bool ParseGateway(napi_env env, napi_value jsRoute, struct INetAddr &iNetAddr)
286 {
287     napi_value gateway = NapiUtils::GetNamedProperty(env, jsRoute, NET_GATEWAY);
288     if (NapiUtils::GetValueType(env, gateway) != napi_object) {
289         NETMGR_EXT_LOG_E("param gateway type is mismatch");
290         return false;
291     }
292 
293     GetStringFromJsMandatoryItem(env, gateway, NET_ADDRESS, iNetAddr.address_);
294 
295     if (!ParseAddressFamily(env, gateway, iNetAddr.family_)) {
296         return false;
297     }
298     GetUint8FromJsOptionItem(env, gateway, NET_PORT, iNetAddr.port_);
299     return true;
300 }
301 
ParseRoute(napi_env env,napi_value jsRoute,Route & route)302 static bool ParseRoute(napi_env env, napi_value jsRoute, Route &route)
303 {
304     GetStringFromJsOptionItem(env, jsRoute, NET_INTERFACE, route.iface_);
305 
306     if (!ParseDestination(env, jsRoute, route.destination_)) {
307         NETMGR_EXT_LOG_E("ParseDestination failed");
308         return false;
309     }
310     if (!ParseGateway(env, jsRoute, route.gateway_)) {
311         NETMGR_EXT_LOG_E("ParseGateway failed");
312         return false;
313     }
314 
315     GetBoolFromJsOptionItem(env, jsRoute, NET_HAS_GATEWAY, route.hasGateway_);
316     GetBoolFromJsOptionItem(env, jsRoute, NET_ISDEFAULTROUTE, route.isDefaultRoute_);
317     GetBoolFromJsOptionItem(env, jsRoute, NET_ISEXCLUDEDROUTE, route.isExcludedRoute_);
318     return true;
319 }
320 
ParseAddrRouteParams(napi_value config)321 bool SetUpContext::ParseAddrRouteParams(napi_value config)
322 {
323     // parse addresses.
324     if (NapiUtils::HasNamedProperty(GetEnv(), config, CONFIG_ADDRESSES)) {
325         napi_value addrArray = NapiUtils::GetNamedProperty(GetEnv(), config, CONFIG_ADDRESSES);
326         if (!NapiUtils::IsArray(GetEnv(), addrArray)) {
327             NETMGR_EXT_LOG_E("addresses is not array");
328             return false;
329         }
330         uint32_t addrLength = NapiUtils::GetArrayLength(GetEnv(), addrArray);
331         for (uint32_t i = 0; i < addrLength; ++i) { // set length limit.
332             INetAddr iNetAddr;
333             if (!ParseAddress(GetEnv(), NapiUtils::GetArrayElement(GetEnv(), addrArray, i), iNetAddr)) {
334                 NETMGR_EXT_LOG_E("ParseAddress failed");
335                 return false;
336             }
337             vpnConfig_->addresses_.emplace_back(iNetAddr);
338             bool isIpv6 = CommonUtils::IsValidIPV6(iNetAddr.address_);
339             vpnConfig_->isAcceptIPv4_ = !isIpv6;
340             vpnConfig_->isAcceptIPv6_ = isIpv6;
341         }
342     }
343 
344     // parse routes.
345     if (NapiUtils::HasNamedProperty(GetEnv(), config, CONFIG_ROUTES)) {
346         napi_value routes = NapiUtils::GetNamedProperty(GetEnv(), config, CONFIG_ROUTES);
347         if (!NapiUtils::IsArray(GetEnv(), routes)) {
348             NETMGR_EXT_LOG_E("routes is not array");
349             return false;
350         }
351         uint32_t routesLength = NapiUtils::GetArrayLength(GetEnv(), routes);
352         for (uint32_t idx = 0; idx < routesLength; ++idx) { // set length limit.
353             struct Route routeInfo;
354             if (!ParseRoute(GetEnv(), NapiUtils::GetArrayElement(GetEnv(), routes, idx), routeInfo)) {
355                 NETMGR_EXT_LOG_E("ParseRoute failed");
356                 return false;
357             }
358             vpnConfig_->routes_.emplace_back(routeInfo);
359         }
360     }
361     return true;
362 }
363 
ParseOptionArrayString(napi_env env,napi_value config,const std::string & key,std::vector<std::string> & vector)364 static bool ParseOptionArrayString(napi_env env, napi_value config, const std::string &key,
365                                    std::vector<std::string> &vector)
366 {
367     if (NapiUtils::HasNamedProperty(env, config, key)) {
368         napi_value array = NapiUtils::GetNamedProperty(env, config, key);
369         if (!NapiUtils::IsArray(env, array)) {
370             NETMGR_EXT_LOG_E("param [%{public}s] is not array", key.c_str());
371             return false;
372         }
373         uint32_t arrayLength = NapiUtils::GetArrayLength(env, array);
374         for (uint32_t i = 0; i < arrayLength; ++i) {
375             std::string item = NapiUtils::GetStringFromValueUtf8(env, NapiUtils::GetArrayElement(env, array, i));
376             NETMGR_EXT_LOG_D("%{public}s: %{public}s", key.c_str(), item.c_str());
377             vector.push_back(item);
378         }
379     }
380     return true;
381 }
382 
ParseChoiceableParams(napi_value config)383 bool SetUpContext::ParseChoiceableParams(napi_value config)
384 {
385     ParseOptionArrayString(GetEnv(), config, CONFIG_DNSADDRESSES, vpnConfig_->dnsAddresses_);
386     ParseOptionArrayString(GetEnv(), config, CONFIG_SEARCHDOMAINS, vpnConfig_->searchDomains_);
387 
388     if (NapiUtils::HasNamedProperty(GetEnv(), config, CONFIG_MTU)) {
389         if (NapiUtils::GetValueType(GetEnv(), NapiUtils::GetNamedProperty(GetEnv(), config, CONFIG_MTU)) ==
390             napi_number) {
391             vpnConfig_->mtu_ = NapiUtils::GetInt32Property(GetEnv(), config, CONFIG_MTU);
392             NETMGR_EXT_LOG_I("%{public}s: %{public}d", CONFIG_MTU, vpnConfig_->mtu_);
393         } else {
394             NETMGR_EXT_LOG_E("param [%{public}s] type is mismatch", CONFIG_MTU);
395         }
396     }
397 
398     GetBoolFromJsOptionItem(GetEnv(), config, CONFIG_ISIPV4ACCEPTED, vpnConfig_->isAcceptIPv4_);
399     GetBoolFromJsOptionItem(GetEnv(), config, CONFIG_ISIPV6ACCEPTED, vpnConfig_->isAcceptIPv6_);
400     GetBoolFromJsOptionItem(GetEnv(), config, CONFIG_ISLEGACY, vpnConfig_->isLegacy_);
401     GetBoolFromJsOptionItem(GetEnv(), config, CONFIG_ISMETERED, vpnConfig_->isMetered_);
402     GetBoolFromJsOptionItem(GetEnv(), config, CONFIG_ISBLOCKING, vpnConfig_->isBlocking_);
403 
404     ParseOptionArrayString(GetEnv(), config, CONFIG_TRUSTEDAPPLICATIONS, vpnConfig_->acceptedApplications_);
405     ParseOptionArrayString(GetEnv(), config, CONFIG_BLOCKEDAPPLICATIONS, vpnConfig_->refusedApplications_);
406     return true;
407 }
408 } // namespace NetManagerStandard
409 } // namespace OHOS
410