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