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