From ab5f347b7f50e8a47940c53334e2c9bac490309d Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Sun, 4 Apr 2021 11:28:06 +0800 Subject: Add networkCreate API. Deprecate networkCreate[Physical/Vpn] OEMs need VPN type information in Netd for customization. According to stable AIDL rules, Netd can neither extend parameters in the existing networkCreateVpn, nor add a new API with the identical name (function overloading). Thus, add an extensible API which can create physical network, virtual network, and so on. Deprecate networkCreatePhysical and networkCreateVpn. Bug: 171872481 Test: atest Change-Id: I9094593c902d91d90a8210960c608f0a50f163ff --- server/Android.bp | 3 + server/NdcDispatcher.cpp | 6 + server/NetdNativeService.cpp | 22 ++- server/NetdNativeService.h | 1 + server/NetworkController.cpp | 7 +- server/NetworkController.h | 2 +- .../current/android/net/INetd.aidl | 7 + .../current/android/net/NativeNetworkConfig.aidl | 43 +++++ .../current/android/net/NativeNetworkType.aidl | 39 +++++ .../current/android/net/NativeVpnType.aidl | 41 +++++ server/binder/android/net/INetd.aidl | 12 ++ server/binder/android/net/NativeNetworkConfig.aidl | 52 ++++++ server/binder/android/net/NativeNetworkType.aidl | 30 ++++ server/binder/android/net/NativeVpnType.aidl | 40 +++++ tests/binder_test.cpp | 179 ++++++++++++++++----- 15 files changed, 443 insertions(+), 41 deletions(-) create mode 100644 server/aidl_api/netd_aidl_interface/current/android/net/NativeNetworkConfig.aidl create mode 100644 server/aidl_api/netd_aidl_interface/current/android/net/NativeNetworkType.aidl create mode 100644 server/aidl_api/netd_aidl_interface/current/android/net/NativeVpnType.aidl create mode 100644 server/binder/android/net/NativeNetworkConfig.aidl create mode 100644 server/binder/android/net/NativeNetworkType.aidl create mode 100644 server/binder/android/net/NativeVpnType.aidl diff --git a/server/Android.bp b/server/Android.bp index 9e76ca7d..29f1b74d 100644 --- a/server/Android.bp +++ b/server/Android.bp @@ -60,6 +60,9 @@ aidl_interface { "binder/android/net/INetdUnsolicitedEventListener.aidl", "binder/android/net/InterfaceConfigurationParcel.aidl", "binder/android/net/MarkMaskParcel.aidl", + "binder/android/net/NativeNetworkConfig.aidl", + "binder/android/net/NativeNetworkType.aidl", + "binder/android/net/NativeVpnType.aidl", "binder/android/net/RouteInfoParcel.aidl", "binder/android/net/TetherConfigParcel.aidl", "binder/android/net/TetherOffloadRuleParcel.aidl", diff --git a/server/NdcDispatcher.cpp b/server/NdcDispatcher.cpp index e5cad456..80ad7fb6 100644 --- a/server/NdcDispatcher.cpp +++ b/server/NdcDispatcher.cpp @@ -1051,7 +1051,10 @@ int NdcDispatcher::NetworkCommand::runCommand(NdcClient* cli, int argc, char** a unsigned netId = stringToNetId(argv[2]); if (argc == 5 && !strcmp(argv[3], "vpn")) { bool secure = strtol(argv[4], nullptr, 2); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (Status status = mNetd->networkCreateVpn(netId, secure); !status.isOk()) { +#pragma clang diagnostic pop return operationError(cli, "createVirtualNetwork() failed", status.serviceSpecificErrorCode()); } @@ -1065,7 +1068,10 @@ int NdcDispatcher::NetworkCommand::runCommand(NdcClient* cli, int argc, char** a return syntaxError(cli, "Unknown permission"); } } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (Status status = mNetd->networkCreatePhysical(netId, permission); !status.isOk()) { +#pragma clang diagnostic pop return operationError(cli, "createPhysicalNetwork() failed", status.serviceSpecificErrorCode()); } diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp index 7d70527c..05c515d3 100644 --- a/server/NetdNativeService.cpp +++ b/server/NetdNativeService.cpp @@ -52,6 +52,7 @@ using android::base::StringPrintf; using android::base::WriteStringToFile; +using android::net::NativeNetworkType; using android::net::TetherOffloadRuleParcel; using android::net::TetherStatsParcel; using android::net::UidRangeParcel; @@ -345,15 +346,34 @@ binder::Status NetdNativeService::bandwidthRemoveNiceApp(int32_t uid) { return statusFromErrcode(res); } +// TODO: Remove this function when there are no users. Currently, it is still used by DNS resolver +// tests. binder::Status NetdNativeService::networkCreatePhysical(int32_t netId, int32_t permission) { ENFORCE_NETWORK_STACK_PERMISSIONS(); int ret = gCtls->netCtrl.createPhysicalNetwork(netId, convertPermission(permission)); return statusFromErrcode(ret); } +// TODO: Remove this function when there are no users. Currently, it is still used by DNS resolver +// tests. binder::Status NetdNativeService::networkCreateVpn(int32_t netId, bool secure) { ENFORCE_NETWORK_STACK_PERMISSIONS(); - int ret = gCtls->netCtrl.createVirtualNetwork(netId, secure); + // The value of vpnType does not matter here, because it is not used in AOSP and is only + // implemented by OEMs. Also, the RPC is going to deprecate. Just pick a value defined in INetd + // as default. + int ret = gCtls->netCtrl.createVirtualNetwork(netId, secure, NativeVpnType::LEGACY); + return statusFromErrcode(ret); +} + +binder::Status NetdNativeService::networkCreate(const NativeNetworkConfig& config) { + ENFORCE_NETWORK_STACK_PERMISSIONS(); + int ret = -EINVAL; + if (config.networkType == NativeNetworkType::PHYSICAL) { + ret = gCtls->netCtrl.createPhysicalNetwork(config.netId, + convertPermission(config.permission)); + } else if (config.networkType == NativeNetworkType::VIRTUAL) { + ret = gCtls->netCtrl.createVirtualNetwork(config.netId, config.secure, config.vpnType); + } return statusFromErrcode(ret); } diff --git a/server/NetdNativeService.h b/server/NetdNativeService.h index 243cf0ff..1e995ef2 100644 --- a/server/NetdNativeService.h +++ b/server/NetdNativeService.h @@ -64,6 +64,7 @@ class NetdNativeService : public BinderService, public BnNetd // Network and routing commands. binder::Status networkCreatePhysical(int32_t netId, int32_t permission) override; binder::Status networkCreateVpn(int32_t netId, bool secure) override; + binder::Status networkCreate(const NativeNetworkConfig& config) override; binder::Status networkDestroy(int32_t netId) override; binder::Status networkAddInterface(int32_t netId, const std::string& iface) override; diff --git a/server/NetworkController.cpp b/server/NetworkController.cpp index 1d68b201..ff52db5b 100644 --- a/server/NetworkController.cpp +++ b/server/NetworkController.cpp @@ -437,7 +437,7 @@ int NetworkController::createPhysicalOemNetwork(Permission permission, unsigned return ret; } -int NetworkController::createVirtualNetwork(unsigned netId, bool secure) { +int NetworkController::createVirtualNetwork(unsigned netId, bool secure, NativeVpnType vpnType) { ScopedWLock lock(mRWLock); if (!(MIN_NET_ID <= netId && netId <= MAX_NET_ID)) { @@ -450,6 +450,11 @@ int NetworkController::createVirtualNetwork(unsigned netId, bool secure) { return -EEXIST; } + if (vpnType < NativeVpnType::SERVICE || NativeVpnType::OEM < vpnType) { + ALOGE("invalid vpnType %d", static_cast(vpnType)); + return -EINVAL; + } + if (int ret = modifyFallthroughLocked(netId, true)) { return ret; } diff --git a/server/NetworkController.h b/server/NetworkController.h index 61ae1aad..46302252 100644 --- a/server/NetworkController.h +++ b/server/NetworkController.h @@ -107,7 +107,7 @@ public: [[nodiscard]] int createPhysicalNetwork(unsigned netId, Permission permission); [[nodiscard]] int createPhysicalOemNetwork(Permission permission, unsigned* netId); - [[nodiscard]] int createVirtualNetwork(unsigned netId, bool secure); + [[nodiscard]] int createVirtualNetwork(unsigned netId, bool secure, NativeVpnType vpnType); [[nodiscard]] int destroyNetwork(unsigned netId); [[nodiscard]] int addInterfaceToNetwork(unsigned netId, const char* interface); diff --git a/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl b/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl index 99a36e6e..a7952f28 100644 --- a/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl +++ b/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl @@ -37,7 +37,13 @@ interface INetd { boolean isAlive(); boolean firewallReplaceUidChain(in @utf8InCpp String chainName, boolean isAllowlist, in int[] uids); boolean bandwidthEnableDataSaver(boolean enable); + /** + * @deprecated use networkCreate() instead. + */ void networkCreatePhysical(int netId, int permission); + /** + * @deprecated use networkCreate() instead. + */ void networkCreateVpn(int netId, boolean secure); void networkDestroy(int netId); void networkAddInterface(int netId, in @utf8InCpp String iface); @@ -138,6 +144,7 @@ interface INetd { android.net.TetherStatsParcel[] tetherOffloadGetStats(); void tetherOffloadSetInterfaceQuota(int ifIndex, long quotaBytes); android.net.TetherStatsParcel tetherOffloadGetAndClearStats(int ifIndex); + void networkCreate(in android.net.NativeNetworkConfig config); const int IPV4 = 4; const int IPV6 = 6; const int CONF = 1; diff --git a/server/aidl_api/netd_aidl_interface/current/android/net/NativeNetworkConfig.aidl b/server/aidl_api/netd_aidl_interface/current/android/net/NativeNetworkConfig.aidl new file mode 100644 index 00000000..76562b29 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/current/android/net/NativeNetworkConfig.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +@JavaDerive(equals=true, toString=true) @JavaOnlyImmutable +parcelable NativeNetworkConfig { + int netId; + android.net.NativeNetworkType networkType = android.net.NativeNetworkType.PHYSICAL; + int permission; + boolean secure; + android.net.NativeVpnType vpnType = android.net.NativeVpnType.PLATFORM; +} diff --git a/server/aidl_api/netd_aidl_interface/current/android/net/NativeNetworkType.aidl b/server/aidl_api/netd_aidl_interface/current/android/net/NativeNetworkType.aidl new file mode 100644 index 00000000..06c8979d --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/current/android/net/NativeNetworkType.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@Backing(type="int") +enum NativeNetworkType { + PHYSICAL = 0, + VIRTUAL = 1, +} diff --git a/server/aidl_api/netd_aidl_interface/current/android/net/NativeVpnType.aidl b/server/aidl_api/netd_aidl_interface/current/android/net/NativeVpnType.aidl new file mode 100644 index 00000000..8a8be839 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/current/android/net/NativeVpnType.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@Backing(type="int") +enum NativeVpnType { + SERVICE = 1, + PLATFORM = 2, + LEGACY = 3, + OEM = 4, +} diff --git a/server/binder/android/net/INetd.aidl b/server/binder/android/net/INetd.aidl index ee263933..8a028314 100644 --- a/server/binder/android/net/INetd.aidl +++ b/server/binder/android/net/INetd.aidl @@ -19,6 +19,7 @@ package android.net; import android.net.INetdUnsolicitedEventListener; import android.net.InterfaceConfigurationParcel; import android.net.MarkMaskParcel; +import android.net.NativeNetworkConfig; import android.net.RouteInfoParcel; import android.net.TetherConfigParcel; import android.net.TetherOffloadRuleParcel; @@ -69,6 +70,7 @@ interface INetd { /** * Creates a physical network (i.e., one containing physical interfaces. + * @deprecated use networkCreate() instead. * * @param netId the networkId to create. * @param permission the permission necessary to use the network. Must be one of @@ -81,6 +83,7 @@ interface INetd { /** * Creates a VPN network. + * @deprecated use networkCreate() instead. * * @param netId the network to create. * @param secure whether unprivileged apps are allowed to bypass the VPN. @@ -1337,4 +1340,13 @@ interface INetd { * cause of the failure. */ TetherStatsParcel tetherOffloadGetAndClearStats(int ifIndex); + + /** + * Creates a network. + * + * @param config the configuration of network. + * @throws ServiceSpecificException in case of failure, with an error code corresponding to the + * unix errno. + */ + void networkCreate(in NativeNetworkConfig config); } diff --git a/server/binder/android/net/NativeNetworkConfig.aidl b/server/binder/android/net/NativeNetworkConfig.aidl new file mode 100644 index 00000000..2c4f83a4 --- /dev/null +++ b/server/binder/android/net/NativeNetworkConfig.aidl @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.NativeNetworkType; +import android.net.NativeVpnType; + +/** + * The configuration to create a network. + * + * {@hide} + */ +@JavaDerive(toString=true, equals=true) +@JavaOnlyImmutable +parcelable NativeNetworkConfig { + /** The networkId to create. */ + int netId; + + /** + * The type of network, e.g. physical network or virtual network. + */ + NativeNetworkType networkType = NativeNetworkType.PHYSICAL; + + /** + * For physical networks. The permission necessary to use the network. Must be one of + * PERMISSION_NONE/PERMISSION_NETWORK/PERMISSION_SYSTEM. Ignored for all other network types. + */ + int permission; + + /** + * For virtual networks. Whether unprivileged apps are allowed to bypass the VPN. Ignored for + * all other network types. + */ + boolean secure; + + /** For virtual networks. The type of VPN to create. Ignored for all other network types. */ + NativeVpnType vpnType = NativeVpnType.PLATFORM; +} diff --git a/server/binder/android/net/NativeNetworkType.aidl b/server/binder/android/net/NativeNetworkType.aidl new file mode 100644 index 00000000..d6670294 --- /dev/null +++ b/server/binder/android/net/NativeNetworkType.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +@Backing(type="int") +enum NativeNetworkType { + /** + * Physical network type. + */ + PHYSICAL = 0, + + /** + * Virtual private network type. + */ + VIRTUAL = 1, +} \ No newline at end of file diff --git a/server/binder/android/net/NativeVpnType.aidl b/server/binder/android/net/NativeVpnType.aidl new file mode 100644 index 00000000..cd1b4474 --- /dev/null +++ b/server/binder/android/net/NativeVpnType.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +@Backing(type="int") +enum NativeVpnType { + /** + * A VPN created by an app using the VpnService API. + */ + SERVICE = 1, + + /** + * A VPN created using a VpnManager API such as startProvisionedVpnProfile. + */ + PLATFORM = 2, + + /** + * An IPsec VPN created by the built-in LegacyVpnRunner. + */ + LEGACY = 3, + + /** + * An VPN created by OEM code through other means than VpnService or VpnManager. + */ + OEM = 4, +} \ No newline at end of file diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp index b5572ede..22cba742 100644 --- a/tests/binder_test.cpp +++ b/tests/binder_test.cpp @@ -106,6 +106,9 @@ using android::net::INetd; using android::net::InterfaceConfigurationParcel; using android::net::InterfaceController; using android::net::MarkMaskParcel; +using android::net::NativeNetworkConfig; +using android::net::NativeNetworkType; +using android::net::NativeVpnType; using android::net::RULE_PRIORITY_DEFAULT_NETWORK; using android::net::RULE_PRIORITY_EXPLICIT_NETWORK; using android::net::RULE_PRIORITY_PROHIBIT_NON_VPN; @@ -245,11 +248,29 @@ TEST_F(NetdBinderTest, IsAlive) { ASSERT_TRUE(isAlive); } +namespace { + +NativeNetworkConfig makeNativeNetworkConfig(int netId, NativeNetworkType networkType, + int permission, bool secure) { + NativeNetworkConfig config = {}; + config.netId = netId; + config.networkType = networkType; + config.permission = permission; + config.secure = secure; + // The vpnType doesn't matter in AOSP. Just pick a well defined one from INetd. + config.vpnType = NativeVpnType::PLATFORM; + return config; +} + +} // namespace + bool testNetworkExistsButCannotConnect(const sp& netd, TunInterface& ifc, const int netId) { // If this network exists, we should definitely not be able to create it. - // Note that this networkCreatePhysical is never allowed to create reserved network IDs, so + // Note that this networkCreate is never allowed to create reserved network IDs, so // this call may fail for other reasons than the network already existing. - EXPECT_FALSE(netd->networkCreatePhysical(netId, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(netId, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_FALSE(netd->networkCreate(config).isOk()); // Test if the network exist by adding interface. INetd has no dedicated method to query. When // the network exists and the interface can be added, the function succeeds. When the network // exists but the interface cannot be added, it fails with EINVAL, otherwise it is ENONET. @@ -567,11 +588,17 @@ UidRangeParcel makeUidRangeParcel(int start, int stop) { } // namespace TEST_F(NetdBinderTest, NetworkInterfaces) { - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); - EXPECT_EQ(EEXIST, mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE) - .serviceSpecificErrorCode()); - EXPECT_EQ(EEXIST, mNetd->networkCreateVpn(TEST_NETID1, true).serviceSpecificErrorCode()); - EXPECT_TRUE(mNetd->networkCreateVpn(TEST_NETID2, true).isOk()); + auto config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); + EXPECT_EQ(EEXIST, mNetd->networkCreate(config).serviceSpecificErrorCode()); + + config.networkType = NativeNetworkType::VIRTUAL; + config.secure = true; + EXPECT_EQ(EEXIST, mNetd->networkCreate(config).serviceSpecificErrorCode()); + + config.netId = TEST_NETID2; + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); EXPECT_EQ(EBUSY, @@ -584,8 +611,10 @@ TEST_F(NetdBinderTest, NetworkInterfaces) { } TEST_F(NetdBinderTest, NetworkUidRules) { - EXPECT_TRUE(mNetd->networkCreateVpn(TEST_NETID1, true).isOk()); - EXPECT_EQ(EEXIST, mNetd->networkCreateVpn(TEST_NETID1, true).serviceSpecificErrorCode()); + auto config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::VIRTUAL, + INetd::PERMISSION_NONE, true); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); + EXPECT_EQ(EEXIST, mNetd->networkCreate(config).serviceSpecificErrorCode()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); std::vector uidRanges = {makeUidRangeParcel(BASE_UID + 8005, BASE_UID + 8012), @@ -1284,7 +1313,9 @@ TEST_F(NetdBinderTest, ClatdStartStop) { EXPECT_EQ(ENODEV, status.serviceSpecificErrorCode()); // ... so create a test physical network and add our tun to it. - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); // Prefix must be 96 bits long. @@ -1448,9 +1479,13 @@ TEST_F(NetdBinderTest, TestIpfwdEnableDisableStatusForwarding) { TEST_F(NetdBinderTest, TestIpfwdAddRemoveInterfaceForward) { // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + auto config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID2, INetd::PERMISSION_NONE).isOk()); + + config.netId = TEST_NETID2; + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID2, sTun2.name()).isOk()); binder::Status status = mNetd->ipfwdAddInterfaceForward(sTun.name(), sTun2.name()); @@ -1566,7 +1601,9 @@ TEST_F(NetdBinderTest, BandwidthSetRemoveInterfaceQuota) { long testQuotaBytes = 5550; // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); binder::Status status = mNetd->bandwidthSetInterfaceQuota(sTun.name(), testQuotaBytes); @@ -1584,7 +1621,9 @@ TEST_F(NetdBinderTest, BandwidthSetRemoveInterfaceQuota) { TEST_F(NetdBinderTest, BandwidthSetRemoveInterfaceAlert) { long testAlertBytes = 373; // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); // Need to have a prior interface quota set to set an alert binder::Status status = mNetd->bandwidthSetInterfaceQuota(sTun.name(), testAlertBytes); @@ -1795,7 +1834,9 @@ TEST_F(NetdBinderTest, NetworkAddRemoveRouteUserPermission) { const std::vector testUids = {testUid}; // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); // Setup route for testing nextHop @@ -1949,7 +1990,9 @@ TEST_F(NetdBinderTest, NetworkAddRemoveRouteUserPermission) { TEST_F(NetdBinderTest, NetworkPermissionDefault) { // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); // Get current default network NetId @@ -2598,7 +2641,9 @@ TEST_F(NetdBinderTest, InterfaceGetCfg) { InterfaceConfigurationParcel interfaceCfgResult; // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); binder::Status status = mNetd->interfaceGetCfg(sTun.name(), &interfaceCfgResult); @@ -2617,7 +2662,9 @@ TEST_F(NetdBinderTest, InterfaceSetCfg) { std::vector downFlags = {"down"}; // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); // Set tun interface down. @@ -2655,7 +2702,9 @@ TEST_F(NetdBinderTest, InterfaceClearAddr) { std::vector noFlags{}; // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); auto interfaceCfg = makeInterfaceCfgParcel(sTun.name(), testAddr, testPrefixLength, noFlags); @@ -2673,7 +2722,9 @@ TEST_F(NetdBinderTest, InterfaceClearAddr) { TEST_F(NetdBinderTest, InterfaceSetEnableIPv6) { // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); // disable @@ -2694,7 +2745,9 @@ TEST_F(NetdBinderTest, InterfaceSetMtu) { const int testMtu = 1200; // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); binder::Status status = mNetd->interfaceSetMtu(sTun.name(), testMtu); @@ -2980,7 +3033,9 @@ TEST_F(NetdBinderTest, NDC) { } // Add test physical network - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); for (const auto& td : kTestData) { @@ -3070,11 +3125,16 @@ void NetdBinderTest::createVpnNetworkWithUid(bool secure, uid_t uid, int vpnNetI sTun2.init(); // Create physical network with fallthroughNetId but not set it as default network - EXPECT_TRUE(mNetd->networkCreatePhysical(fallthroughNetId, INetd::PERMISSION_NONE).isOk()); + auto config = makeNativeNetworkConfig(fallthroughNetId, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(fallthroughNetId, sTun.name()).isOk()); // Create VPN with vpnNetId - EXPECT_TRUE(mNetd->networkCreateVpn(vpnNetId, secure).isOk()); + config.netId = vpnNetId; + config.networkType = NativeNetworkType::VIRTUAL; + config.secure = secure; + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); // Add uid to VPN EXPECT_TRUE(mNetd->networkAddUidRanges(vpnNetId, {makeUidRangeParcel(uid, uid)}).isOk()); @@ -3091,14 +3151,18 @@ void NetdBinderTest::createAndSetDefaultNetwork(int netId, const std::string& in // backup current default network. ASSERT_TRUE(mNetd->networkGetDefault(&mStoredDefaultNetwork).isOk()); - EXPECT_TRUE(mNetd->networkCreatePhysical(netId, permission).isOk()); + const auto& config = + makeNativeNetworkConfig(netId, NativeNetworkType::PHYSICAL, permission, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(netId, interface).isOk()); EXPECT_TRUE(mNetd->networkSetDefault(netId).isOk()); } void NetdBinderTest::createPhysicalNetwork(int netId, const std::string& interface, int permission) { - EXPECT_TRUE(mNetd->networkCreatePhysical(netId, permission).isOk()); + const auto& config = + makeNativeNetworkConfig(netId, NativeNetworkType::PHYSICAL, permission, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(netId, interface).isOk()); } @@ -3118,7 +3182,9 @@ void NetdBinderTest::createVpnAndOtherPhysicalNetwork(int systemDefaultNetId, in int vpnNetId, bool secure) { createDefaultAndOtherPhysicalNetwork(systemDefaultNetId, otherNetId); - EXPECT_TRUE(mNetd->networkCreateVpn(vpnNetId, secure).isOk()); + auto config = makeNativeNetworkConfig(vpnNetId, NativeNetworkType::VIRTUAL, + INetd::PERMISSION_NONE, secure); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(vpnNetId, sTun3.name()).isOk()); EXPECT_TRUE(mNetd->networkAddRoute(vpnNetId, sTun3.name(), "2001:db8::/32", "").isOk()); } @@ -3362,12 +3428,15 @@ TEST_F(NetdBinderTest, GetFwmarkForNetwork) { ASSERT_TRUE(mNetd->networkGetDefault(&mStoredDefaultNetwork).isOk()); // Add test physical network 1 and set as default network. - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + auto config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); EXPECT_TRUE(mNetd->networkAddRoute(TEST_NETID1, sTun.name(), "2001:db8::/32", "").isOk()); EXPECT_TRUE(mNetd->networkSetDefault(TEST_NETID1).isOk()); // Add test physical network 2 - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID2, INetd::PERMISSION_NONE).isOk()); + config.netId = TEST_NETID2; + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID2, sTun2.name()).isOk()); // Get fwmark for network 1. @@ -3572,7 +3641,9 @@ TEST_F(NetdBinderTest, DISABLED_TetherOffloadForwarding) { // Use one of the test's tun interfaces as upstream. // It must be part of a network or it will not have the clsact attached. - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_NETID1, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(TEST_NETID1, sTun.name()).isOk()); int fd1 = sTun.getFdForTesting(); EXPECT_TRUE(tcQdiscExists(sTun.name())); @@ -3703,14 +3774,20 @@ TEST_F(NetdBinderTest, TestServiceDump) { std::vector testData; // Send some IPCs and for each one add an element to testData telling us what to expect. - EXPECT_TRUE(mNetd->networkCreatePhysical(TEST_DUMP_NETID, INetd::PERMISSION_NONE).isOk()); - testData.push_back({"networkCreatePhysical(65123, 0)", "networkCreatePhysical.*65123"}); + const auto& config = makeNativeNetworkConfig(TEST_DUMP_NETID, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); + testData.push_back( + {"networkCreate(NativeNetworkConfig{netId: 65123, networkType: PHYSICAL, " + "permission: 0, secure: false, vpnType: PLATFORM})", + "networkCreate.*65123"}); - EXPECT_EQ(EEXIST, mNetd->networkCreatePhysical(TEST_DUMP_NETID, INetd::PERMISSION_NONE) - .serviceSpecificErrorCode()); + EXPECT_EQ(EEXIST, mNetd->networkCreate(config).serviceSpecificErrorCode()); testData.push_back( - {"networkCreatePhysical(65123, 0) -> ServiceSpecificException(17, \"File exists\")", - "networkCreatePhysical.*65123.*17"}); + {"networkCreate(NativeNetworkConfig{netId: 65123, networkType: PHYSICAL, " + "permission: 0, secure: false, vpnType: PLATFORM}) " + "-> ServiceSpecificException(17, \"File exists\")", + "networkCreate.*65123.*17"}); EXPECT_TRUE(mNetd->networkAddInterface(TEST_DUMP_NETID, sTun.name()).isOk()); testData.push_back({StringPrintf("networkAddInterface(65123, %s)", sTun.name().c_str()), @@ -3889,7 +3966,9 @@ void expectUnreachableError(uid_t uid, unsigned netId, int selectionMode) { // Verify whether API reject overlapped UID ranges TEST_F(NetdBinderTest, PerAppDefaultNetwork_OverlappedUidRanges) { - EXPECT_TRUE(mNetd->networkCreatePhysical(APP_DEFAULT_NETID, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(APP_DEFAULT_NETID, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(APP_DEFAULT_NETID, sTun.name()).isOk()); std::vector uidRanges = {makeUidRangeParcel(BASE_UID + 1, BASE_UID + 1), @@ -3932,7 +4011,9 @@ TEST_F(NetdBinderTest, PerAppDefaultNetwork_OverlappedUidRanges) { // Verify whether IP rules for app default network are correctly configured. TEST_F(NetdBinderTest, PerAppDefaultNetwork_VerifyIpRules) { - EXPECT_TRUE(mNetd->networkCreatePhysical(APP_DEFAULT_NETID, INetd::PERMISSION_NONE).isOk()); + const auto& config = makeNativeNetworkConfig(APP_DEFAULT_NETID, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); EXPECT_TRUE(mNetd->networkAddInterface(APP_DEFAULT_NETID, sTun.name()).isOk()); std::vector uidRanges = {makeUidRangeParcel(BASE_UID + 8005, BASE_UID + 8012), @@ -4250,3 +4331,25 @@ TEST_P(VpnParameterizedTest, UnconnectedSocket) { // uid is in both app and VPN range. Traffic goes through VPN. expectPacketSentOnNetId(TEST_UID2, NETID_UNSET, vpnFd, UNCONNECTED_SOCKET); } + +TEST_F(NetdBinderTest, NetworkCreate) { + auto config = makeNativeNetworkConfig(TEST_NETID1, NativeNetworkType::PHYSICAL, + INetd::PERMISSION_NONE, false); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); + EXPECT_TRUE(mNetd->networkDestroy(config.netId).isOk()); + + config.networkType = NativeNetworkType::VIRTUAL; + config.secure = true; + config.vpnType = NativeVpnType::OEM; + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); + + // invalid network type + auto wrongConfig = makeNativeNetworkConfig(TEST_NETID2, static_cast(-1), + INetd::PERMISSION_NONE, false); + EXPECT_EQ(EINVAL, mNetd->networkCreate(wrongConfig).serviceSpecificErrorCode()); + + // invalid VPN type + wrongConfig.networkType = NativeNetworkType::VIRTUAL; + wrongConfig.vpnType = static_cast(-1); + EXPECT_EQ(EINVAL, mNetd->networkCreate(wrongConfig).serviceSpecificErrorCode()); +} -- cgit v1.2.3