blob: 3590a9f6d61ac44597d1ba2d01416b049f4e0f12 [file] [log] [blame]
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "RouteController.h"
18
19#include "Fwmark.h"
20#include "NetdConstants.h"
21
Lorenzo Colittiba25df92014-06-18 00:22:17 +090022#include <arpa/inet.h>
23#include <errno.h>
24#include <linux/netlink.h>
Sreeram Ramachandran8fe9c8e2014-04-16 12:08:05 -070025#include <linux/rtnetlink.h>
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070026#include <logwrap/logwrap.h>
Paul Jensena561e122014-06-12 16:46:37 -040027#include <map>
Lorenzo Colittiba25df92014-06-18 00:22:17 +090028#include <netinet/in.h>
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070029#include <net/if.h>
Lorenzo Colittiba25df92014-06-18 00:22:17 +090030#include <sys/socket.h>
31#include <sys/uio.h>
32#include <unistd.h>
33
34// Avoids "non-constant-expression cannot be narrowed from type 'unsigned int' to 'unsigned short'"
35// warnings when using RTA_LENGTH(x) inside static initializers (even when x is already uint16_t).
36#define U16_RTA_LENGTH(x) static_cast<uint16_t>(RTA_LENGTH((x)))
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070037
38namespace {
39
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -070040const uint32_t RULE_PRIORITY_PRIVILEGED_LEGACY = 11000;
Sreeram Ramachandran8fe9c8e2014-04-16 12:08:05 -070041const uint32_t RULE_PRIORITY_PER_NETWORK_EXPLICIT = 13000;
42const uint32_t RULE_PRIORITY_PER_NETWORK_INTERFACE = 14000;
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -070043const uint32_t RULE_PRIORITY_LEGACY = 16000;
Sreeram Ramachandran8fe9c8e2014-04-16 12:08:05 -070044const uint32_t RULE_PRIORITY_PER_NETWORK_NORMAL = 17000;
45const uint32_t RULE_PRIORITY_DEFAULT_NETWORK = 19000;
46const uint32_t RULE_PRIORITY_MAIN = 20000;
Sreeram Ramachandran56afacf2014-05-28 15:07:00 -070047// TODO: Uncomment once we are sure everything works.
48#if 0
Sreeram Ramachandran8fe9c8e2014-04-16 12:08:05 -070049const uint32_t RULE_PRIORITY_UNREACHABLE = 21000;
Sreeram Ramachandran56afacf2014-05-28 15:07:00 -070050#endif
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070051
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -070052// TODO: These should be turned into per-UID tables once the kernel supports UID-based routing.
53const int ROUTE_TABLE_PRIVILEGED_LEGACY = RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX - 901;
54const int ROUTE_TABLE_LEGACY = RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX - 902;
55
Paul Jensena561e122014-06-12 16:46:37 -040056std::map<std::string, uint32_t> interfaceToIndex;
57
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070058uint32_t getRouteTableForInterface(const char* interface) {
Sreeram Ramachandrana4811802014-04-10 12:10:24 -070059 uint32_t index = if_nametoindex(interface);
Paul Jensena561e122014-06-12 16:46:37 -040060 if (index) {
61 interfaceToIndex[interface] = index;
62 } else {
63 // If the interface goes away if_nametoindex() will return 0 but we still need to know
64 // the index so we can remove the rules and routes.
65 std::map<std::string, uint32_t>::iterator it = interfaceToIndex.find(interface);
66 if (it != interfaceToIndex.end())
67 index = it->second;
68 }
Sreeram Ramachandrana4811802014-04-10 12:10:24 -070069 return index ? index + RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX : 0;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070070}
71
Sreeram Ramachandran8fe9c8e2014-04-16 12:08:05 -070072// Adds or removes a routing rule for IPv4 and IPv6.
73//
74// + If |table| is non-zero, the rule points at the specified routing table. Otherwise, the rule
75// returns ENETUNREACH.
76// + If |mask| is non-zero, the rule matches the specified fwmark and mask. Otherwise, |fwmark| is
77// ignored.
78// + If |interface| is non-NULL, the rule matches the specified outgoing interface.
79bool runIpRuleCommand(const char* action, uint32_t priority, uint32_t table, uint32_t fwmark,
80 uint32_t mask, const char* interface) {
Lorenzo Colittia10ac322014-04-11 18:26:17 +090081 char priorityString[UINT32_STRLEN];
Lorenzo Colittia10ac322014-04-11 18:26:17 +090082 snprintf(priorityString, sizeof(priorityString), "%u", priority);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -070083
84 char tableString[UINT32_STRLEN];
Lorenzo Colittia10ac322014-04-11 18:26:17 +090085 snprintf(tableString, sizeof(tableString), "%u", table);
86
87 char fwmarkString[sizeof("0x12345678/0x12345678")];
88 snprintf(fwmarkString, sizeof(fwmarkString), "0x%x/0x%x", fwmark, mask);
89
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -070090 const char* version[] = {"-4", "-6"};
91 for (size_t i = 0; i < ARRAY_SIZE(version); ++i) {
92 int argc = 0;
93 const char* argv[16];
94
95 argv[argc++] = IP_PATH;
96 argv[argc++] = version[i];
97 argv[argc++] = "rule";
98 argv[argc++] = action;
99 argv[argc++] = "priority";
Lorenzo Colittia10ac322014-04-11 18:26:17 +0900100 argv[argc++] = priorityString;
Sreeram Ramachandran8fe9c8e2014-04-16 12:08:05 -0700101 if (table) {
102 argv[argc++] = "table";
103 argv[argc++] = tableString;
104 } else {
105 argv[argc++] = "unreachable";
106 }
Lorenzo Colittia10ac322014-04-11 18:26:17 +0900107 if (mask) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700108 argv[argc++] = "fwmark";
Lorenzo Colittia10ac322014-04-11 18:26:17 +0900109 argv[argc++] = fwmarkString;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700110 }
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700111 if (interface) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700112 argv[argc++] = "oif";
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700113 argv[argc++] = interface;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700114 }
115 if (android_fork_execvp(argc, const_cast<char**>(argv), NULL, false, false)) {
116 return false;
117 }
118 }
119
120 return true;
121}
122
Sreeram Ramachandranab359fe2014-06-24 15:03:52 -0700123#if 0
124
Lorenzo Colittiba25df92014-06-18 00:22:17 +0900125// Adds or deletes an IPv4 or IPv6 route.
126// Returns 0 on success or negative errno on failure.
127int modifyIpRoute(uint16_t action, uint32_t table, const char* interface, const char* destination,
128 const char* nexthop) {
129 // At least the destination must be non-null.
130 if (!destination) {
131 return -EFAULT;
132 }
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700133
Lorenzo Colittiba25df92014-06-18 00:22:17 +0900134 // Parse the prefix.
135 uint8_t rawAddress[sizeof(in6_addr)];
136 uint8_t family, prefixLength;
137 int rawLength = parsePrefix(destination, &family, rawAddress, sizeof(rawAddress),
138 &prefixLength);
139 if (rawLength < 0) {
140 return rawLength;
141 }
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700142
Lorenzo Colittiba25df92014-06-18 00:22:17 +0900143 if (static_cast<size_t>(rawLength) > sizeof(rawAddress)) {
144 return -ENOBUFS; // Cannot happen; parsePrefix only supports IPv4 and IPv6.
145 }
146
147 // If an interface was specified, find the ifindex.
148 uint32_t ifindex;
149 if (interface) {
150 ifindex = if_nametoindex(interface);
151 if (!ifindex) {
152 return -ENODEV;
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700153 }
154 }
155
Lorenzo Colittiba25df92014-06-18 00:22:17 +0900156 // If a nexthop was specified, parse it as the same family as the prefix.
157 uint8_t rawNexthop[sizeof(in6_addr)];
158 if (nexthop && !inet_pton(family, nexthop, rawNexthop)) {
159 return -EINVAL;
160 }
161
162 // Assemble a netlink request and put it in an array of iovec structures.
163 nlmsghdr nlmsg = {
164 .nlmsg_type = action,
165 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
166 };
167 rtmsg rtmsg = {
168 .rtm_protocol = RTPROT_STATIC,
169 .rtm_type = RTN_UNICAST,
170 .rtm_family = family,
171 .rtm_dst_len = prefixLength,
172 };
173 rtattr rta_table = { U16_RTA_LENGTH(sizeof(table)), RTA_TABLE };
174 rtattr rta_oif = { U16_RTA_LENGTH(sizeof(ifindex)), RTA_OIF };
175 rtattr rta_dst = { U16_RTA_LENGTH(rawLength), RTA_DST };
176 rtattr rta_gateway = { U16_RTA_LENGTH(rawLength), RTA_GATEWAY };
177 if (action == RTM_NEWROUTE) {
178 nlmsg.nlmsg_flags |= (NLM_F_CREATE | NLM_F_EXCL);
179 }
180
181 iovec iov[] = {
182 { &nlmsg, sizeof(nlmsg) },
183 { &rtmsg, sizeof(rtmsg) },
184 { &rta_table, sizeof(rta_table) },
185 { &table, sizeof(table) },
186 { &rta_dst, sizeof(rta_dst) },
187 { rawAddress, static_cast<size_t>(rawLength) },
188 { &rta_oif, interface ? sizeof(rta_oif) : 0 },
189 { &ifindex, interface ? sizeof(interface) : 0 },
190 { &rta_gateway, nexthop ? sizeof(rta_gateway) : 0 },
191 { rawNexthop, nexthop ? static_cast<size_t>(rawLength) : 0 },
192 };
193 int iovlen = ARRAY_SIZE(iov);
194
195 for (int i = 0; i < iovlen; ++i) {
196 nlmsg.nlmsg_len += iov[i].iov_len;
197 }
198
199 int ret;
200 struct {
201 nlmsghdr msg;
202 nlmsgerr err;
203 } response;
204
205 sockaddr_nl kernel = {AF_NETLINK, 0, 0, 0};
206 int sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
207 if (sock != -1 &&
208 connect(sock, reinterpret_cast<sockaddr *>(&kernel), sizeof(kernel)) != -1 &&
209 writev(sock, iov, iovlen) != -1 &&
210 (ret = recv(sock, &response, sizeof(response), 0)) != -1) {
211 if (ret == sizeof(response)) {
212 ret = response.err.error; // Netlink errors are negative errno.
213 } else {
214 ret = -EBADMSG;
215 }
216 } else {
217 ret = -errno;
218 }
219
220 if (sock != -1) {
221 close(sock);
222 }
223
224 return ret;
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700225}
226
Sreeram Ramachandranab359fe2014-06-24 15:03:52 -0700227#else
228
229int modifyIpRoute(int action, uint32_t table, const char* interface, const char* destination,
230 const char* nexthop) {
231 char tableString[UINT32_STRLEN];
232 snprintf(tableString, sizeof(tableString), "%u", table);
233
234 int argc = 0;
235 const char* argv[16];
236
237 argv[argc++] = IP_PATH;
238 argv[argc++] = "route";
239 argv[argc++] = action == RTM_NEWROUTE ? ADD : DEL;
240 argv[argc++] = "table";
241 argv[argc++] = tableString;
242 if (destination) {
243 argv[argc++] = destination;
244 argv[argc++] = "dev";
245 argv[argc++] = interface;
246 if (nexthop) {
247 argv[argc++] = "via";
248 argv[argc++] = nexthop;
249 }
250 }
251 return android_fork_execvp(argc, const_cast<char**>(argv), NULL, false, false);
252}
253
254#endif
255
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700256bool modifyPerNetworkRules(unsigned netId, const char* interface, Permission permission, bool add,
257 bool modifyIptables) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700258 uint32_t table = getRouteTableForInterface(interface);
259 if (!table) {
260 return false;
261 }
262
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700263 const char* action = add ? ADD : DEL;
264
Sreeram Ramachandran122f5812014-05-11 20:29:49 -0700265 Fwmark fwmark;
266 fwmark.permission = permission;
267
268 Fwmark mask;
269 mask.permission = permission;
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700270
271 // A rule to route traffic based on a chosen outgoing interface.
272 //
273 // Supports apps that use SO_BINDTODEVICE or IP_PKTINFO options and the kernel that already
274 // knows the outgoing interface (typically for link-local communications).
Sreeram Ramachandran122f5812014-05-11 20:29:49 -0700275 if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_INTERFACE, table, fwmark.intValue,
276 mask.intValue, interface)) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700277 return false;
278 }
279
280 // A rule to route traffic based on the chosen network.
281 //
282 // This is for sockets that have not explicitly requested a particular network, but have been
283 // bound to one when they called connect(). This ensures that sockets connected on a particular
284 // network stay on that network even if the default network changes.
Sreeram Ramachandran122f5812014-05-11 20:29:49 -0700285 fwmark.netId = netId;
286 mask.netId = FWMARK_NET_ID_MASK;
287 if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_NORMAL, table, fwmark.intValue,
288 mask.intValue, NULL)) {
289 return false;
290 }
291
292 // A rule to route traffic based on an explicitly chosen network.
293 //
294 // Supports apps that use the multinetwork APIs to restrict their traffic to a network.
295 //
296 // We don't really need to check the permission bits of the fwmark here, as they would've been
297 // checked at the time the netId was set into the fwmark, but we do so to be consistent.
298 fwmark.explicitlySelected = true;
299 mask.explicitlySelected = true;
300 if (!runIpRuleCommand(action, RULE_PRIORITY_PER_NETWORK_EXPLICIT, table, fwmark.intValue,
301 mask.intValue, NULL)) {
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700302 return false;
303 }
304
305 // An iptables rule to mark incoming packets on a network with the netId of the network.
306 //
307 // This is so that the kernel can:
308 // + Use the right fwmark for (and thus correctly route) replies (e.g.: TCP RST, ICMP errors,
Sreeram Ramachandrana4811802014-04-10 12:10:24 -0700309 // ping replies).
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700310 // + Mark sockets that accept connections from this interface so that the connection stays on
311 // the same interface.
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700312 if (modifyIptables) {
313 action = add ? "-A" : "-D";
314 char markString[UINT32_HEX_STRLEN];
315 snprintf(markString, sizeof(markString), "0x%x", netId);
316 if (execIptables(V4V6, "-t", "mangle", action, "INPUT", "-i", interface, "-j", "MARK",
317 "--set-mark", markString, NULL)) {
318 return false;
319 }
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700320 }
321
322 return true;
323}
324
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700325bool modifyDefaultNetworkRules(const char* interface, Permission permission, const char* action) {
326 uint32_t table = getRouteTableForInterface(interface);
327 if (!table) {
328 return false;
329 }
330
Sreeram Ramachandran122f5812014-05-11 20:29:49 -0700331 Fwmark fwmark;
332 fwmark.netId = 0;
333 fwmark.permission = permission;
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700334
Sreeram Ramachandran122f5812014-05-11 20:29:49 -0700335 Fwmark mask;
336 mask.netId = FWMARK_NET_ID_MASK;
337 mask.permission = permission;
338
339 return runIpRuleCommand(action, RULE_PRIORITY_DEFAULT_NETWORK, table, fwmark.intValue,
340 mask.intValue, NULL);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700341}
342
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900343// Adds or removes an IPv4 or IPv6 route to the specified table and, if it's directly-connected
344// route, to the main table as well.
345// Returns 0 on success or negative errno on failure.
346int modifyRoute(const char* interface, const char* destination, const char* nexthop,
Sreeram Ramachandranab359fe2014-06-24 15:03:52 -0700347 int action, RouteController::TableType tableType, unsigned /* uid */) {
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700348 uint32_t table = 0;
349 switch (tableType) {
350 case RouteController::INTERFACE: {
351 table = getRouteTableForInterface(interface);
352 break;
353 }
354 case RouteController::LEGACY: {
355 // TODO: Use the UID to assign a unique table per UID instead of this fixed table.
356 table = ROUTE_TABLE_LEGACY;
357 break;
358 }
359 case RouteController::PRIVILEGED_LEGACY: {
360 // TODO: Use the UID to assign a unique table per UID instead of this fixed table.
361 table = ROUTE_TABLE_PRIVILEGED_LEGACY;
362 break;
363 }
364 }
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700365 if (!table) {
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900366 return -ESRCH;
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700367 }
368
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900369 int ret = modifyIpRoute(action, table, interface, destination, nexthop);
370 if (ret != 0) {
371 return ret;
Sreeram Ramachandranc9213372014-04-16 12:32:18 -0700372 }
373
374 // If there's no nexthop, this is a directly connected route. Add it to the main table also, to
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900375 // let the kernel find it when validating nexthops when global routes are added.
376 if (!nexthop) {
377 ret = modifyIpRoute(action, RT_TABLE_MAIN, interface, destination, NULL);
378 // A failure with action == ADD && errno == EEXIST means that the route already exists in
379 // the main table, perhaps because the kernel added it automatically as part of adding the
380 // IP address to the interface. Ignore this, but complain about everything else.
381 if (ret != 0 && !(action == RTM_NEWROUTE && ret == -EEXIST)) {
382 return ret;
383 }
Sreeram Ramachandranc9213372014-04-16 12:32:18 -0700384 }
385
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900386 return 0;
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700387}
388
Sreeram Ramachandran92b66c42014-04-15 14:28:55 -0700389bool flushRoutes(const char* interface) {
390 uint32_t table = getRouteTableForInterface(interface);
391 if (!table) {
392 return false;
393 }
Paul Jensena561e122014-06-12 16:46:37 -0400394 interfaceToIndex.erase(interface);
Sreeram Ramachandran92b66c42014-04-15 14:28:55 -0700395
Lorenzo Colitti357e5622014-06-17 16:14:17 +0900396 char tableString[UINT32_STRLEN];
397 snprintf(tableString, sizeof(tableString), "%u", table);
398
399 const char* version[] = {"-4", "-6"};
400 for (size_t i = 0; i < ARRAY_SIZE(version); ++i) {
401 const char* argv[] = {
402 IP_PATH,
403 version[i],
404 "route"
405 "flush",
406 "table",
407 tableString,
408 };
409 int argc = ARRAY_SIZE(argv);
410
411 if (!android_fork_execvp(argc, const_cast<char**>(argv), NULL, false, false)) {
412 return false;
413 }
414 }
415
416 return true;
Sreeram Ramachandran92b66c42014-04-15 14:28:55 -0700417}
418
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700419} // namespace
420
Sreeram Ramachandran8fe9c8e2014-04-16 12:08:05 -0700421void RouteController::Init() {
422 // Add a new rule to look up the 'main' table, with the same selectors as the "default network"
423 // rule, but with a lower priority. Since the default network rule points to a table with a
424 // default route, the rule we're adding will never be used for normal routing lookups. However,
425 // the kernel may fall-through to it to find directly-connected routes when it validates that a
426 // nexthop (in a route being added) is reachable.
Sreeram Ramachandran122f5812014-05-11 20:29:49 -0700427 Fwmark fwmark;
428 fwmark.netId = 0;
429
430 Fwmark mask;
431 mask.netId = FWMARK_NET_ID_MASK;
432
433 runIpRuleCommand(ADD, RULE_PRIORITY_MAIN, RT_TABLE_MAIN, fwmark.intValue, mask.intValue, NULL);
Sreeram Ramachandran8fe9c8e2014-04-16 12:08:05 -0700434
Sreeram Ramachandran38b7af12014-05-22 14:21:49 -0700435 // Add rules to allow lookup of legacy routes.
436 //
437 // TODO: Remove these once the kernel supports UID-based routing. Instead, add them on demand
438 // when routes are added.
439 fwmark.netId = 0;
440 mask.netId = 0;
441
442 fwmark.explicitlySelected = false;
443 mask.explicitlySelected = true;
444
445 runIpRuleCommand(ADD, RULE_PRIORITY_LEGACY, ROUTE_TABLE_LEGACY, fwmark.intValue, mask.intValue,
446 NULL);
447
448 fwmark.permission = PERMISSION_CONNECTIVITY_INTERNAL;
449 mask.permission = PERMISSION_CONNECTIVITY_INTERNAL;
450
451 runIpRuleCommand(ADD, RULE_PRIORITY_PRIVILEGED_LEGACY, ROUTE_TABLE_PRIVILEGED_LEGACY,
452 fwmark.intValue, mask.intValue, NULL);
453
Sreeram Ramachandran8fe9c8e2014-04-16 12:08:05 -0700454// TODO: Uncomment once we are sure everything works.
455#if 0
456 // Add a rule to preempt the pre-defined "from all lookup main" rule. This ensures that packets
457 // that are already marked with a specific NetId don't fall-through to the main table.
458 runIpRuleCommand(ADD, RULE_PRIORITY_UNREACHABLE, 0, 0, 0, NULL);
459#endif
460}
461
Paul Jensenae37e8a2014-04-28 10:35:51 -0400462bool RouteController::addInterfaceToNetwork(unsigned netId, const char* interface,
463 Permission permission) {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700464 return modifyPerNetworkRules(netId, interface, permission, true, true);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700465}
466
Paul Jensenae37e8a2014-04-28 10:35:51 -0400467bool RouteController::removeInterfaceFromNetwork(unsigned netId, const char* interface,
468 Permission permission) {
Sreeram Ramachandran92b66c42014-04-15 14:28:55 -0700469 return modifyPerNetworkRules(netId, interface, permission, false, true) &&
470 flushRoutes(interface);
Sreeram Ramachandran379bd332014-04-10 19:58:06 -0700471}
472
473bool RouteController::modifyNetworkPermission(unsigned netId, const char* interface,
474 Permission oldPermission, Permission newPermission) {
475 // Add the new rules before deleting the old ones, to avoid race conditions.
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700476 return modifyPerNetworkRules(netId, interface, newPermission, true, false) &&
477 modifyPerNetworkRules(netId, interface, oldPermission, false, false);
478}
479
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700480bool RouteController::addToDefaultNetwork(const char* interface, Permission permission) {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700481 return modifyDefaultNetworkRules(interface, permission, ADD);
482}
483
Sreeram Ramachandran72604072014-05-21 13:19:43 -0700484bool RouteController::removeFromDefaultNetwork(const char* interface, Permission permission) {
Sreeram Ramachandran9c0d3132014-04-10 20:35:04 -0700485 return modifyDefaultNetworkRules(interface, permission, DEL);
Sreeram Ramachandran5c181bf2014-04-07 14:10:04 -0700486}
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700487
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900488int RouteController::addRoute(const char* interface, const char* destination,
489 const char* nexthop, TableType tableType, unsigned uid) {
Lorenzo Colittiba25df92014-06-18 00:22:17 +0900490 return modifyRoute(interface, destination, nexthop, RTM_NEWROUTE, tableType, uid);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700491}
492
Lorenzo Colittif7fc8ec2014-06-18 00:41:58 +0900493int RouteController::removeRoute(const char* interface, const char* destination,
494 const char* nexthop, TableType tableType, unsigned uid) {
Lorenzo Colittiba25df92014-06-18 00:22:17 +0900495 return modifyRoute(interface, destination, nexthop, RTM_DELROUTE, tableType, uid);
Sreeram Ramachandran7619e1b2014-04-15 14:23:08 -0700496}