const uint32_t RULE_PRIORITY_LOCAL_NETWORK = 17000;
const uint32_t RULE_PRIORITY_TETHERING = 18000;
const uint32_t RULE_PRIORITY_IMPLICIT_NETWORK = 19000;
-// const uint32_t RULE_PRIORITY_BYPASSABLE_VPN = 20000;
+const uint32_t RULE_PRIORITY_BYPASSABLE_VPN = 20000;
// const uint32_t RULE_PRIORITY_VPN_FALLTHROUGH = 21000;
const uint32_t RULE_PRIORITY_DEFAULT_NETWORK = 22000;
const uint32_t RULE_PRIORITY_DIRECTLY_CONNECTED = 23000;
// have, if they are subject to this VPN, their traffic has to go through it. Allows the traffic to
// bypass the VPN if the protectedFromVpn bit is set.
WARN_UNUSED_RESULT int modifyVpnUidRangeRule(uint32_t table, uid_t uidStart, uid_t uidEnd,
- bool add) {
+ bool secure, bool add) {
Fwmark fwmark;
Fwmark mask;
fwmark.protectedFromVpn = false;
mask.protectedFromVpn = true;
- return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_SECURE_VPN, table,
- fwmark.intValue, mask.intValue, IIF_NONE, OIF_NONE, uidStart, uidEnd);
+ uint32_t priority;
+
+ if (secure) {
+ priority = RULE_PRIORITY_SECURE_VPN;
+ } else {
+ priority = RULE_PRIORITY_BYPASSABLE_VPN;
+
+ fwmark.explicitlySelected = false;
+ mask.explicitlySelected = true;
+ }
+
+ return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, priority, table, fwmark.intValue,
+ mask.intValue, IIF_NONE, OIF_NONE, uidStart, uidEnd);
}
// A rule to allow system apps to send traffic over this VPN even if they are not part of the target
//
// This is needed for DnsProxyListener to correctly resolve a request for a user who is in the
// target set, but where the DnsProxyListener itself is not.
-WARN_UNUSED_RESULT int modifyVpnSystemPermissionRule(unsigned netId, uint32_t table, bool add) {
+WARN_UNUSED_RESULT int modifyVpnSystemPermissionRule(unsigned netId, uint32_t table, bool secure,
+ bool add) {
Fwmark fwmark;
Fwmark mask;
fwmark.permission = PERMISSION_SYSTEM;
mask.permission = PERMISSION_SYSTEM;
- return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_SECURE_VPN, table,
- fwmark.intValue, mask.intValue);
+ uint32_t priority = secure ? RULE_PRIORITY_SECURE_VPN : RULE_PRIORITY_BYPASSABLE_VPN;
+
+ return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, priority, table, fwmark.intValue,
+ mask.intValue);
}
// A rule to route traffic based on an explicitly chosen network.
}
WARN_UNUSED_RESULT int modifyVirtualNetwork(unsigned netId, const char* interface,
- const UidRanges& uidRanges, bool add,
+ const UidRanges& uidRanges, bool secure, bool add,
bool modifyNonUidBasedRules) {
uint32_t table = getRouteTableForInterface(interface);
if (table == RT_TABLE_UNSPEC) {
}
for (const UidRanges::Range& range : uidRanges.getRanges()) {
- if (int ret = modifyVpnUidRangeRule(table, range.first, range.second, add)) {
+ if (int ret = modifyVpnUidRangeRule(table, range.first, range.second, secure, add)) {
return ret;
}
if (int ret = modifyExplicitNetworkRule(netId, table, PERMISSION_NONE, range.first,
if (int ret = modifyVpnOutputToLocalRule(interface, add)) {
return ret;
}
- if (int ret = modifyVpnSystemPermissionRule(netId, table, add)) {
+ if (int ret = modifyVpnSystemPermissionRule(netId, table, secure, add)) {
return ret;
}
return modifyExplicitNetworkRule(netId, table, PERMISSION_NONE, UID_ROOT, UID_ROOT, add);
}
int RouteController::addInterfaceToVirtualNetwork(unsigned netId, const char* interface,
- const UidRanges& uidRanges) {
- if (int ret = modifyVirtualNetwork(netId, interface, uidRanges, ACTION_ADD,
+ bool secure, const UidRanges& uidRanges) {
+ if (int ret = modifyVirtualNetwork(netId, interface, uidRanges, secure, ACTION_ADD,
MODIFY_NON_UID_BASED_RULES)) {
return ret;
}
}
int RouteController::removeInterfaceFromVirtualNetwork(unsigned netId, const char* interface,
- const UidRanges& uidRanges) {
- if (int ret = modifyVirtualNetwork(netId, interface, uidRanges, ACTION_DEL,
+ bool secure, const UidRanges& uidRanges) {
+ if (int ret = modifyVirtualNetwork(netId, interface, uidRanges, secure, ACTION_DEL,
MODIFY_NON_UID_BASED_RULES)) {
return ret;
}
return modifyPhysicalNetwork(netId, interface, oldPermission, ACTION_DEL);
}
-int RouteController::addUsersToVirtualNetwork(unsigned netId, const char* interface,
+int RouteController::addUsersToVirtualNetwork(unsigned netId, const char* interface, bool secure,
const UidRanges& uidRanges) {
- return modifyVirtualNetwork(netId, interface, uidRanges, ACTION_ADD,
+ return modifyVirtualNetwork(netId, interface, uidRanges, secure, ACTION_ADD,
!MODIFY_NON_UID_BASED_RULES);
}
int RouteController::removeUsersFromVirtualNetwork(unsigned netId, const char* interface,
- const UidRanges& uidRanges) {
- return modifyVirtualNetwork(netId, interface, uidRanges, ACTION_DEL,
+ bool secure, const UidRanges& uidRanges) {
+ return modifyVirtualNetwork(netId, interface, uidRanges, secure, ACTION_DEL,
!MODIFY_NON_UID_BASED_RULES);
}
static int removeInterfaceFromPhysicalNetwork(unsigned netId, const char* interface,
Permission permission) WARN_UNUSED_RESULT;
- static int addInterfaceToVirtualNetwork(unsigned netId, const char* interface,
+ static int addInterfaceToVirtualNetwork(unsigned netId, const char* interface, bool secure,
const UidRanges& uidRanges) WARN_UNUSED_RESULT;
- static int removeInterfaceFromVirtualNetwork(unsigned netId, const char* interface,
+ static int removeInterfaceFromVirtualNetwork(unsigned netId, const char* interface, bool secure,
const UidRanges& uidRanges) WARN_UNUSED_RESULT;
static int modifyPhysicalNetworkPermission(unsigned netId, const char* interface,
Permission oldPermission,
Permission newPermission) WARN_UNUSED_RESULT;
- static int addUsersToVirtualNetwork(unsigned netId, const char* interface,
+ static int addUsersToVirtualNetwork(unsigned netId, const char* interface, bool secure,
const UidRanges& uidRanges) WARN_UNUSED_RESULT;
- static int removeUsersFromVirtualNetwork(unsigned netId, const char* interface,
+ static int removeUsersFromVirtualNetwork(unsigned netId, const char* interface, bool secure,
const UidRanges& uidRanges) WARN_UNUSED_RESULT;
static int addInterfaceToDefaultNetwork(const char* interface,
#define LOG_TAG "Netd"
#include "log/log.h"
-VirtualNetwork::VirtualNetwork(unsigned netId, bool hasDns): Network(netId), mHasDns(hasDns) {
+VirtualNetwork::VirtualNetwork(unsigned netId, bool hasDns, bool secure) :
+ Network(netId), mHasDns(hasDns), mSecure(secure) {
}
VirtualNetwork::~VirtualNetwork() {
return mHasDns;
}
+bool VirtualNetwork::isSecure() const {
+ return mSecure;
+}
+
bool VirtualNetwork::appliesToUser(uid_t uid) const {
return mUidRanges.hasUid(uid);
}
int VirtualNetwork::addUsers(const UidRanges& uidRanges) {
for (const std::string& interface : mInterfaces) {
- if (int ret = RouteController::addUsersToVirtualNetwork(mNetId, interface.c_str(),
+ if (int ret = RouteController::addUsersToVirtualNetwork(mNetId, interface.c_str(), mSecure,
uidRanges)) {
ALOGE("failed to add users on interface %s of netId %u", interface.c_str(), mNetId);
return ret;
int VirtualNetwork::removeUsers(const UidRanges& uidRanges) {
for (const std::string& interface : mInterfaces) {
if (int ret = RouteController::removeUsersFromVirtualNetwork(mNetId, interface.c_str(),
- uidRanges)) {
+ mSecure, uidRanges)) {
ALOGE("failed to remove users on interface %s of netId %u", interface.c_str(), mNetId);
return ret;
}
if (hasInterface(interface)) {
return 0;
}
- if (int ret = RouteController::addInterfaceToVirtualNetwork(mNetId, interface.c_str(),
+ if (int ret = RouteController::addInterfaceToVirtualNetwork(mNetId, interface.c_str(), mSecure,
mUidRanges)) {
ALOGE("failed to add interface %s to VPN netId %u", interface.c_str(), mNetId);
return ret;
return 0;
}
if (int ret = RouteController::removeInterfaceFromVirtualNetwork(mNetId, interface.c_str(),
- mUidRanges)) {
+ mSecure, mUidRanges)) {
ALOGE("failed to remove interface %s from VPN netId %u", interface.c_str(), mNetId);
return ret;
}