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