RouteController.cpp revision 7619e1bbebdfe643c35ee6be4ac054f5255f0706
15c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran/*
25c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran * Copyright (C) 2014 The Android Open Source Project
35c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran *
45c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran * Licensed under the Apache License, Version 2.0 (the "License");
55c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran * you may not use this file except in compliance with the License.
65c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran * You may obtain a copy of the License at
75c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran *
85c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran *      http://www.apache.org/licenses/LICENSE-2.0
95c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran *
105c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran * Unless required by applicable law or agreed to in writing, software
115c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran * distributed under the License is distributed on an "AS IS" BASIS,
125c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran * See the License for the specific language governing permissions and
145c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran * limitations under the License.
155c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran */
165c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
175c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include "RouteController.h"
185c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
195c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include "Fwmark.h"
205c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include "NetdConstants.h"
215c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
225c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include <logwrap/logwrap.h>
235c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include <net/if.h>
245c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
255c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandrannamespace {
265c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
279c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandranconst uint32_t RULE_PRIORITY_PER_NETWORK_EXPLICIT  =  300;
289c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandranconst uint32_t RULE_PRIORITY_PER_NETWORK_INTERFACE =  400;
299c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandranconst uint32_t RULE_PRIORITY_PER_NETWORK_NORMAL    =  700;
309c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandranconst uint32_t RULE_PRIORITY_DEFAULT_NETWORK       =  900;
315c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
329c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandranconst bool FWMARK_USE_NET_ID   = true;
335c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandranconst bool FWMARK_USE_EXPLICIT = true;
349c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandranconst bool FWMARK_USE_PROTECT  = true;
355c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
365c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandranuint32_t getRouteTableForInterface(const char* interface) {
37a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran    uint32_t index = if_nametoindex(interface);
38a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran    return index ? index + RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX : 0;
395c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
405c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
41a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colittibool runIpRuleCommand(const char* action, uint32_t priority, uint32_t table,
429c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran                      uint32_t fwmark, uint32_t mask, const char* interface) {
43a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti    char priorityString[UINT32_STRLEN];
44a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti    snprintf(priorityString, sizeof(priorityString), "%u", priority);
457619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
467619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    char tableString[UINT32_STRLEN];
47a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti    snprintf(tableString, sizeof(tableString), "%u", table);
48a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti
49a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti    char fwmarkString[sizeof("0x12345678/0x12345678")];
50a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti    snprintf(fwmarkString, sizeof(fwmarkString), "0x%x/0x%x", fwmark, mask);
51a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti
525c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    const char* version[] = {"-4", "-6"};
535c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    for (size_t i = 0; i < ARRAY_SIZE(version); ++i) {
545c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        int argc = 0;
555c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        const char* argv[16];
565c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
575c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        argv[argc++] = IP_PATH;
585c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        argv[argc++] = version[i];
595c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        argv[argc++] = "rule";
605c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        argv[argc++] = action;
615c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        argv[argc++] = "priority";
62a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti        argv[argc++] = priorityString;
635c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        argv[argc++] = "table";
64a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti        argv[argc++] = tableString;
65a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti        if (mask) {
665c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran            argv[argc++] = "fwmark";
67a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti            argv[argc++] = fwmarkString;
685c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
699c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran        if (interface) {
705c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran            argv[argc++] = "oif";
719c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran            argv[argc++] = interface;
725c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
735c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        if (android_fork_execvp(argc, const_cast<char**>(argv), NULL, false, false)) {
745c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran            return false;
755c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
765c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    }
775c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
785c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    return true;
795c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
805c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
817619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandranbool runIpRouteCommand(const char* action, uint32_t table, const char* interface,
827619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran                       const char* destination, const char* nexthop) {
837619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    char tableString[UINT32_STRLEN];
847619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    snprintf(tableString, sizeof(tableString), "%u", table);
857619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
867619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    int argc = 0;
877619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    const char* argv[16];
887619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
897619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    argv[argc++] = IP_PATH;
907619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    argv[argc++] = "route";
917619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    argv[argc++] = action;
927619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    argv[argc++] = "table";
937619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    argv[argc++] = tableString;
947619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    if (destination) {
957619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran        argv[argc++] = destination;
967619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran        argv[argc++] = "dev";
977619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran        argv[argc++] = interface;
987619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran        if (nexthop) {
997619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran            argv[argc++] = "via";
1007619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran            argv[argc++] = nexthop;
1017619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran        }
1027619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    }
1037619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
1047619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    return android_fork_execvp(argc, const_cast<char**>(argv), NULL, false, false);
1057619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran}
1067619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
1079c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandranbool modifyPerNetworkRules(unsigned netId, const char* interface, Permission permission, bool add,
1089c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran                           bool modifyIptables) {
1095c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    uint32_t table = getRouteTableForInterface(interface);
1105c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    if (!table) {
1115c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        return false;
1125c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    }
1135c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1145c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    const char* action = add ? ADD : DEL;
1155c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1165c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // A rule to route traffic based on an explicitly chosen network.
1175c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    //
1185c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // Supports apps that use the multinetwork APIs to restrict their traffic to a network.
1195c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    //
1205c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // We don't really need to check the permission bits of the fwmark here, as they would've been
1215c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // checked at the time the netId was set into the fwmark, but we do so to be consistent.
1225c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    uint32_t fwmark = getFwmark(netId, FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
1235c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    uint32_t mask = getFwmarkMask(FWMARK_USE_NET_ID, FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT,
1245c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran                                  permission);
125a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti    if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_EXPLICIT, table, fwmark, mask, NULL)) {
1265c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        return false;
1275c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    }
1285c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1295c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // A rule to route traffic based on a chosen outgoing interface.
1305c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    //
1315c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // Supports apps that use SO_BINDTODEVICE or IP_PKTINFO options and the kernel that already
1325c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // knows the outgoing interface (typically for link-local communications).
1335c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    fwmark = getFwmark(0, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
1345c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    mask = getFwmark(!FWMARK_USE_NET_ID, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
1359c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_INTERFACE, table, fwmark, mask,
1369c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran                          interface)) {
1375c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        return false;
1385c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    }
1395c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1405c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // A rule to route traffic based on the chosen network.
1415c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    //
1425c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // This is for sockets that have not explicitly requested a particular network, but have been
1435c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // bound to one when they called connect(). This ensures that sockets connected on a particular
1445c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // network stay on that network even if the default network changes.
1455c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    fwmark = getFwmark(netId, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
1465c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    mask = getFwmarkMask(FWMARK_USE_NET_ID, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
147a10ac3214f6a582b7fdb66acc43c702731e53d81Lorenzo Colitti    if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_NORMAL, table, fwmark, mask, NULL)) {
1485c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        return false;
1495c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    }
1505c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1515c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // An iptables rule to mark incoming packets on a network with the netId of the network.
1525c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    //
1535c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // This is so that the kernel can:
1545c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // + Use the right fwmark for (and thus correctly route) replies (e.g.: TCP RST, ICMP errors,
155a48118062412f16ae712bfc8c8a539d3b6a85e47Sreeram Ramachandran    //   ping replies).
1565c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    // + Mark sockets that accept connections from this interface so that the connection stays on
1575c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    //   the same interface.
158379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran    if (modifyIptables) {
159379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        action = add ? "-A" : "-D";
160379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        char markString[UINT32_HEX_STRLEN];
161379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        snprintf(markString, sizeof(markString), "0x%x", netId);
162379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        if (execIptables(V4V6, "-t", "mangle", action, "INPUT", "-i", interface, "-j", "MARK",
163379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran                         "--set-mark", markString, NULL)) {
164379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            return false;
165379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
1665c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    }
1675c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1685c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    return true;
1695c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
1705c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1719c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandranbool modifyDefaultNetworkRules(const char* interface, Permission permission, const char* action) {
1729c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    uint32_t table = getRouteTableForInterface(interface);
1739c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    if (!table) {
1749c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran        return false;
1759c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    }
1769c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran
1779c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    uint32_t fwmark = getFwmark(0, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT, permission);
1789c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    uint32_t mask = getFwmarkMask(FWMARK_USE_NET_ID, !FWMARK_USE_EXPLICIT, !FWMARK_USE_PROTECT,
1799c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran                                  permission);
1809c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran
1817619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    return runIpRuleCommand(action, RULE_PRIORITY_DEFAULT_NETWORK, table, fwmark, mask, NULL);
1827619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran}
1837619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
1847619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandranbool modifyRoute(const char* interface, const char* destination, const char* nexthop, bool add) {
1857619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    uint32_t table = getRouteTableForInterface(interface);
1867619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    if (!table) {
1879c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran        return false;
1889c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    }
1899c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran
1907619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    return runIpRouteCommand(add ? ADD : DEL, table, interface, destination, nexthop);
1919c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran}
1929c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran
1935c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}  // namespace
1945c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1955c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandranbool RouteController::createNetwork(unsigned netId, const char* interface, Permission permission) {
1969c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    return modifyPerNetworkRules(netId, interface, permission, true, true);
1975c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
1985c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1995c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandranbool RouteController::destroyNetwork(unsigned netId, const char* interface, Permission permission) {
2009c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    return modifyPerNetworkRules(netId, interface, permission, false, true);
201379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran    // TODO: Flush the routing table.
202379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran}
203379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
204379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandranbool RouteController::modifyNetworkPermission(unsigned netId, const char* interface,
205379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran                                              Permission oldPermission, Permission newPermission) {
206379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran    // Add the new rules before deleting the old ones, to avoid race conditions.
2079c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    return modifyPerNetworkRules(netId, interface, newPermission, true, false) &&
2089c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran           modifyPerNetworkRules(netId, interface, oldPermission, false, false);
2099c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran}
2109c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran
2119c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandranbool RouteController::addDefaultNetwork(const char* interface, Permission permission) {
2129c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    return modifyDefaultNetworkRules(interface, permission, ADD);
2139c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran}
2149c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran
2159c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandranbool RouteController::removeDefaultNetwork(const char* interface, Permission permission) {
2169c0d313de6a3157fadd3b52a9927c77216ca435eSreeram Ramachandran    return modifyDefaultNetworkRules(interface, permission, DEL);
2175c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
2187619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
2197619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandranbool RouteController::addRoute(const char* interface, const char* destination,
2207619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran                               const char* nexthop) {
2217619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    return modifyRoute(interface, destination, nexthop, true);
2227619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran}
2237619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran
2247619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandranbool RouteController::removeRoute(const char* interface, const char* destination,
2257619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran                                  const char* nexthop) {
2267619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran    return modifyRoute(interface, destination, nexthop, false);
2277619e1bbebdfe643c35ee6be4ac054f5255f0706Sreeram Ramachandran}
228