const uint32_t RULE_PRIORITY_VPN_OVERRIDE_OIF = 10500;
const uint32_t RULE_PRIORITY_VPN_OUTPUT_TO_LOCAL = 11000;
const uint32_t RULE_PRIORITY_SECURE_VPN = 12000;
+const uint32_t RULE_PRIORITY_PROHIBIT_NON_VPN = 12500;
const uint32_t RULE_PRIORITY_EXPLICIT_NETWORK = 13000;
const uint32_t RULE_PRIORITY_OUTPUT_INTERFACE = 14000;
const uint32_t RULE_PRIORITY_LEGACY_SYSTEM = 15000;
// Adds or removes a routing rule for IPv4 and IPv6.
//
-// + If |priority| is RULE_PRIORITY_UNREACHABLE, the rule returns ENETUNREACH (i.e., specifies an
-// action of FR_ACT_UNREACHABLE). Otherwise, the rule specifies an action of FR_ACT_TO_TBL.
// + If |table| is non-zero, the rule points at the specified routing table. Otherwise, the table is
-// unspecified. An unspecified table is only allowed when deleting a rule.
+// unspecified. An unspecified table is not allowed when creating an FR_ACT_TO_TBL rule.
// + If |mask| is non-zero, the rule matches the specified fwmark and mask. Otherwise, |fwmark| is
// ignored.
// + If |iif| is non-NULL, the rule matches the specified incoming interface.
// range (inclusive). Otherwise, the rule matches packets from all UIDs.
//
// Returns 0 on success or negative errno on failure.
-WARN_UNUSED_RESULT int modifyIpRule(uint16_t action, uint32_t priority, uint32_t table,
- uint32_t fwmark, uint32_t mask, const char* iif,
+WARN_UNUSED_RESULT int modifyIpRule(uint16_t action, uint32_t priority, uint8_t ruleType,
+ uint32_t table, uint32_t fwmark, uint32_t mask, const char* iif,
const char* oif, uid_t uidStart, uid_t uidEnd) {
// Ensure that if you set a bit in the fwmark, it's not being ignored by the mask.
if (fwmark & ~mask) {
ALOGE("incompatible start and end UIDs (%u vs %u)", uidStart, uidEnd);
return -EUSERS;
}
+
bool isUidRule = (uidStart != INVALID_UID);
// Assemble a rule request and put it in an array of iovec structures.
fib_rule_hdr rule = {
- .action = static_cast<uint8_t>(priority != RULE_PRIORITY_UNREACHABLE ? FR_ACT_TO_TBL :
- FR_ACT_UNREACHABLE),
+ .action = ruleType,
// Note that here we're implicitly setting rule.table to 0. When we want to specify a
// non-zero table, we do this via the FRATTR_TABLE attribute.
};
}
WARN_UNUSED_RESULT int modifyIpRule(uint16_t action, uint32_t priority, uint32_t table,
+ uint32_t fwmark, uint32_t mask, const char* iif,
+ const char* oif, uid_t uidStart, uid_t uidEnd) {
+ return modifyIpRule(action, priority, FR_ACT_TO_TBL, table, fwmark, mask, iif, oif, uidStart,
+ uidEnd);
+}
+
+WARN_UNUSED_RESULT int modifyIpRule(uint16_t action, uint32_t priority, uint32_t table,
uint32_t fwmark, uint32_t mask) {
return modifyIpRule(action, priority, table, fwmark, mask, IIF_NONE, OIF_NONE, INVALID_UID,
INVALID_UID);
// behaviour. We do flush the kernel-default rules at startup, but having an explicit unreachable
// rule will hopefully make things even clearer.
WARN_UNUSED_RESULT int addUnreachableRule() {
- return modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_UNREACHABLE, RT_TABLE_UNSPEC, MARK_UNSET,
- MARK_UNSET);
+ return modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_UNREACHABLE, FR_ACT_UNREACHABLE, RT_TABLE_UNSPEC,
+ MARK_UNSET, MARK_UNSET, IIF_NONE, OIF_NONE, INVALID_UID, INVALID_UID);
}
WARN_UNUSED_RESULT int modifyLocalNetwork(unsigned netId, const char* interface, bool add) {
return modifyImplicitNetworkRule(netId, table, permission, add);
}
+WARN_UNUSED_RESULT int modifyRejectNonSecureNetworkRule(const UidRanges& uidRanges, bool add) {
+ Fwmark fwmark;
+ Fwmark mask;
+ fwmark.protectedFromVpn = false;
+ mask.protectedFromVpn = true;
+
+ for (const UidRanges::Range& range : uidRanges.getRanges()) {
+ if (int ret = modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE,
+ RULE_PRIORITY_PROHIBIT_NON_VPN, FR_ACT_PROHIBIT, RT_TABLE_UNSPEC,
+ fwmark.intValue, mask.intValue, IIF_LOOPBACK, OIF_NONE,
+ range.first, range.second)) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
WARN_UNUSED_RESULT int modifyVirtualNetwork(unsigned netId, const char* interface,
const UidRanges& uidRanges, bool secure, bool add,
bool modifyNonUidBasedRules) {
return modifyPhysicalNetwork(netId, interface, oldPermission, ACTION_DEL);
}
+int RouteController::addUsersToRejectNonSecureNetworkRule(const UidRanges& uidRanges) {
+ return modifyRejectNonSecureNetworkRule(uidRanges, true);
+}
+
+int RouteController::removeUsersFromRejectNonSecureNetworkRule(const UidRanges& uidRanges) {
+ return modifyRejectNonSecureNetworkRule(uidRanges, false);
+}
+
int RouteController::addUsersToVirtualNetwork(unsigned netId, const char* interface, bool secure,
const UidRanges& uidRanges) {
return modifyVirtualNetwork(netId, interface, uidRanges, secure, ACTION_ADD,