+// Add rules to allow legacy routes added through the requestRouteToHost() API.
+WARN_UNUSED_RESULT int AddLegacyRouteRules() {
+ Fwmark fwmark;
+ Fwmark mask;
+
+ fwmark.explicitlySelected = false;
+ mask.explicitlySelected = true;
+
+ // Rules to allow legacy routes to override the default network.
+ if (int ret = modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_LEGACY_SYSTEM,
+ RouteController::ROUTE_TABLE_LEGACY_SYSTEM, fwmark.intValue,
+ mask.intValue, OIF_NONE, INVALID_UID, INVALID_UID)) {
+ return ret;
+ }
+ if (int ret = modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_LEGACY_NETWORK,
+ RouteController::ROUTE_TABLE_LEGACY_NETWORK, fwmark.intValue,
+ mask.intValue, OIF_NONE, INVALID_UID, INVALID_UID)) {
+ return ret;
+ }
+
+ fwmark.permission = PERMISSION_SYSTEM;
+ mask.permission = PERMISSION_SYSTEM;
+
+ // A rule to allow legacy routes from system apps to override VPNs.
+ return modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_VPN_OVERRIDE_SYSTEM,
+ RouteController::ROUTE_TABLE_LEGACY_SYSTEM, fwmark.intValue, mask.intValue,
+ OIF_NONE, INVALID_UID, INVALID_UID);
+}
+
+// Add a new rule to look up the 'main' table, with the same selectors as the "default network"
+// rule, but with a lower priority. Since the default network rule points to a table with a default
+// route, the rule we're adding will never be used for normal routing lookups. However, the kernel
+// may fall-through to it to find directly-connected routes when it validates that a nexthop (in a
+// route being added) is reachable.
+WARN_UNUSED_RESULT int AddDirectlyConnectedRule() {
+ Fwmark fwmark;
+ Fwmark mask;
+
+ fwmark.netId = NETID_UNSET;
+ mask.netId = FWMARK_NET_ID_MASK;
+
+ return modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_DIRECTLY_CONNECTED, RT_TABLE_MAIN,
+ fwmark.intValue, mask.intValue, OIF_NONE, UID_ROOT, UID_ROOT);
+}
+
+// Add a rule to preempt the pre-defined "from all lookup main" rule. Packets that reach this rule
+// will be null-routed, and won't fall-through to the main table.
+WARN_UNUSED_RESULT int AddUnreachableRule() {
+ return modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_UNREACHABLE, RT_TABLE_UNSPEC, MARK_UNSET,
+ MARK_UNSET, OIF_NONE, INVALID_UID, INVALID_UID);
+}
+
+// An iptables rule to mark incoming packets on a network with the netId of the network.
+//
+// This is so that the kernel can:
+// + Use the right fwmark for (and thus correctly route) replies (e.g.: TCP RST, ICMP errors, ping
+// replies, SYN-ACKs, etc).
+// + Mark sockets that accept connections from this interface so that the connection stays on the
+// same interface.
+WARN_UNUSED_RESULT int modifyIncomingPacketMark(unsigned netId, const char* interface,
+ Permission permission, bool add) {
+ Fwmark fwmark;
+
+ fwmark.netId = netId;
+ fwmark.explicitlySelected = true;
+ fwmark.protectedFromVpn = true;
+ fwmark.permission = permission;
+