blob: dba801e5994f2aa0a29b2a53b7860900d6ad580c [file] [log] [blame]
Robert Greenwaltfc97b822011-11-02 16:48:36 -07001/*
2 * Copyright (C) 2008 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 <stdlib.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <string.h>
21
22#include <sys/socket.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <sys/wait.h>
26
27#include <netinet/in.h>
28#include <arpa/inet.h>
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050029#include <resolv_netid.h>
Robert Greenwaltfc97b822011-11-02 16:48:36 -070030
31#define LOG_TAG "SecondaryTablController"
32#include <cutils/log.h>
33#include <cutils/properties.h>
Rom Lemarchand001f0a42013-01-31 12:41:03 -080034#include <logwrap/logwrap.h>
JP Abgrall9e5e0ce2011-12-14 15:20:59 -080035
Robert Greenwaltfc97b822011-11-02 16:48:36 -070036#include "ResponseCode.h"
Robert Greenwaltc4621772012-01-31 12:46:45 -080037#include "NetdConstants.h"
Robert Greenwaltfc97b822011-11-02 16:48:36 -070038#include "SecondaryTableController.h"
39
Chad Brubaker9a508892013-05-31 20:51:46 -070040const char* SecondaryTableController::LOCAL_MANGLE_OUTPUT = "st_mangle_OUTPUT";
Chad Brubaker4a946092013-07-10 12:08:08 -070041const char* SecondaryTableController::LOCAL_MANGLE_EXEMPT = "st_mangle_EXEMPT";
Chad Brubaker2251c0f2013-06-27 17:20:39 -070042const char* SecondaryTableController::LOCAL_MANGLE_IFACE_FORMAT = "st_mangle_%s_OUTPUT";
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -070043const char* SecondaryTableController::LOCAL_NAT_POSTROUTING = "st_nat_POSTROUTING";
Chad Brubaker2251c0f2013-06-27 17:20:39 -070044const char* SecondaryTableController::LOCAL_FILTER_OUTPUT = "st_filter_OUTPUT";
Chad Brubaker9a508892013-05-31 20:51:46 -070045
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050046SecondaryTableController::SecondaryTableController(NetworkController* controller) :
47 mNetCtrl(controller) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -070048}
49
50SecondaryTableController::~SecondaryTableController() {
51}
52
Chad Brubaker2251c0f2013-06-27 17:20:39 -070053int SecondaryTableController::setupIptablesHooks() {
54 int res = execIptables(V4V6,
55 "-t",
56 "mangle",
57 "-F",
58 LOCAL_MANGLE_OUTPUT,
59 NULL);
Chad Brubaker4a946092013-07-10 12:08:08 -070060 res |= execIptables(V4V6,
61 "-t",
62 "mangle",
63 "-F",
64 LOCAL_MANGLE_EXEMPT,
65 NULL);
Chad Brubaker2349aa62013-07-15 15:28:59 -070066 // rule for skipping anything marked with the PROTECT_MARK
Chad Brubaker2251c0f2013-06-27 17:20:39 -070067 char protect_mark_str[11];
68 snprintf(protect_mark_str, sizeof(protect_mark_str), "%d", PROTECT_MARK);
69 res |= execIptables(V4V6,
70 "-t",
71 "mangle",
72 "-A",
73 LOCAL_MANGLE_OUTPUT,
74 "-m",
75 "mark",
76 "--mark",
77 protect_mark_str,
78 "-j",
79 "RETURN",
80 NULL);
81
Chad Brubaker2349aa62013-07-15 15:28:59 -070082 // protect the legacy VPN daemons from routes.
83 // TODO: Remove this when legacy VPN's are removed.
Chad Brubaker2251c0f2013-06-27 17:20:39 -070084 res |= execIptables(V4V6,
85 "-t",
86 "mangle",
87 "-A",
88 LOCAL_MANGLE_OUTPUT,
89 "-m",
90 "owner",
91 "--uid-owner",
92 "vpn",
93 "-j",
94 "RETURN",
95 NULL);
96 return res;
Chad Brubaker2251c0f2013-06-27 17:20:39 -070097}
98
Robert Greenwaltfc97b822011-11-02 16:48:36 -070099int SecondaryTableController::addRoute(SocketClient *cli, char *iface, char *dest, int prefix,
100 char *gateway) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500101 return modifyRoute(cli, ADD, iface, dest, prefix, gateway, mNetCtrl->getNetworkId(iface));
Robert Greenwalt063af322011-11-18 15:32:13 -0800102}
103
Robert Greenwaltc4621772012-01-31 12:46:45 -0800104int SecondaryTableController::modifyRoute(SocketClient *cli, const char *action, char *iface,
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500105 char *dest, int prefix, char *gateway, unsigned netId) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800106 char dest_str[44]; // enough to store an IPv6 address + 3 character bitmask
107 char tableIndex_str[11];
108 int ret;
109
110 // IP tool doesn't like "::" - the equiv of 0.0.0.0 that it accepts for ipv4
111 snprintf(dest_str, sizeof(dest_str), "%s/%d", dest, prefix);
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500112 snprintf(tableIndex_str, sizeof(tableIndex_str), "%u", netId + BASE_TABLE_NUMBER);
Robert Greenwalt063af322011-11-18 15:32:13 -0800113
114 if (strcmp("::", gateway) == 0) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800115 const char *cmd[] = {
116 IP_PATH,
117 "route",
118 action,
119 dest_str,
120 "dev",
121 iface,
122 "table",
123 tableIndex_str
124 };
125 ret = runCmd(ARRAY_SIZE(cmd), cmd);
Robert Greenwalt063af322011-11-18 15:32:13 -0800126 } else {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800127 const char *cmd[] = {
128 IP_PATH,
129 "route",
130 action,
131 dest_str,
132 "via",
133 gateway,
134 "dev",
135 iface,
136 "table",
137 tableIndex_str
138 };
139 ret = runCmd(ARRAY_SIZE(cmd), cmd);
Robert Greenwalt063af322011-11-18 15:32:13 -0800140 }
141
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800142 if (ret) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500143 ALOGE("ip route %s failed: %s route %s %s/%d via %s dev %s table %u", action,
144 IP_PATH, action, dest, prefix, gateway, iface, netId + BASE_TABLE_NUMBER);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700145 errno = ENODEV;
Robert Greenwalt063af322011-11-18 15:32:13 -0800146 cli->sendMsg(ResponseCode::OperationFailed, "ip route modification failed", true);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700147 return -1;
148 }
Robert Greenwalt063af322011-11-18 15:32:13 -0800149
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500150 modifyRuleCount(netId, action);
Robert Greenwalt063af322011-11-18 15:32:13 -0800151 cli->sendMsg(ResponseCode::CommandOkay, "Route modified", false);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700152 return 0;
153}
154
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500155void SecondaryTableController::modifyRuleCount(unsigned netId, const char *action) {
Robert Greenwaltc4621772012-01-31 12:46:45 -0800156 if (strcmp(action, ADD) == 0) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500157 if (mNetIdRuleCount.count(netId) == 0)
158 mNetIdRuleCount[netId] = 0;
159 mNetIdRuleCount[netId]++;
Robert Greenwaltc4621772012-01-31 12:46:45 -0800160 } else {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500161 if (mNetIdRuleCount.count(netId) > 0) {
162 if (--mNetIdRuleCount[netId] < 1) {
163 mNetIdRuleCount.erase(mNetIdRuleCount.find(netId));
164 }
Robert Greenwaltc4621772012-01-31 12:46:45 -0800165 }
166 }
167}
168
Robert Greenwaltc4621772012-01-31 12:46:45 -0800169const char *SecondaryTableController::getVersion(const char *addr) {
170 if (strchr(addr, ':') != NULL) {
171 return "-6";
172 } else {
173 return "-4";
174 }
175}
176
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700177IptablesTarget SecondaryTableController::getIptablesTarget(const char *addr) {
178 if (strchr(addr, ':') != NULL) {
179 return V6;
180 } else {
181 return V4;
182 }
183}
184
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700185int SecondaryTableController::removeRoute(SocketClient *cli, char *iface, char *dest, int prefix,
186 char *gateway) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500187 return modifyRoute(cli, DEL, iface, dest, prefix, gateway, mNetCtrl->getNetworkId(iface));
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700188}
189
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500190int SecondaryTableController::modifyFromRule(unsigned netId, const char *action,
Robert Greenwaltc4621772012-01-31 12:46:45 -0800191 const char *addr) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800192 char tableIndex_str[11];
Robert Greenwaltc4621772012-01-31 12:46:45 -0800193
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500194 snprintf(tableIndex_str, sizeof(tableIndex_str), "%u", netId + BASE_TABLE_NUMBER);
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800195 const char *cmd[] = {
196 IP_PATH,
197 getVersion(addr),
198 "rule",
199 action,
200 "from",
201 addr,
202 "table",
203 tableIndex_str
204 };
205 if (runCmd(ARRAY_SIZE(cmd), cmd)) {
Robert Greenwaltc4621772012-01-31 12:46:45 -0800206 return -1;
207 }
208
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500209 modifyRuleCount(netId, action);
Robert Greenwaltc4621772012-01-31 12:46:45 -0800210 return 0;
211}
212
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500213int SecondaryTableController::modifyLocalRoute(unsigned netId, const char *action,
Robert Greenwaltc4621772012-01-31 12:46:45 -0800214 const char *iface, const char *addr) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800215 char tableIndex_str[11];
Robert Greenwaltc4621772012-01-31 12:46:45 -0800216
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500217 modifyRuleCount(netId, action); // some del's will fail as the iface is already gone.
218 snprintf(tableIndex_str, sizeof(tableIndex_str), "%u", netId + BASE_TABLE_NUMBER);
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800219 const char *cmd[] = {
220 IP_PATH,
221 "route",
222 action,
223 addr,
224 "dev",
225 iface,
226 "table",
227 tableIndex_str
228 };
229
230 return runCmd(ARRAY_SIZE(cmd), cmd);
Robert Greenwaltc4621772012-01-31 12:46:45 -0800231}
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700232int SecondaryTableController::addFwmarkRule(const char *iface) {
233 return setFwmarkRule(iface, true);
234}
235
236int SecondaryTableController::removeFwmarkRule(const char *iface) {
237 return setFwmarkRule(iface, false);
238}
239
240int SecondaryTableController::setFwmarkRule(const char *iface, bool add) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500241 unsigned netId = mNetCtrl->getNetworkId(iface);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700242
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500243 // Fail fast if any rules already exist for this interface
244 if (mNetIdRuleCount.count(netId) > 0) {
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700245 errno = EBUSY;
246 return -1;
247 }
248
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500249 int ret;
250 char mark_str[11];
251 snprintf(mark_str, sizeof(mark_str), "%u", netId + BASE_TABLE_NUMBER);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700252 //add the catch all route to the tun. Route rules will make sure the right packets hit the table
253 const char *route_cmd[] = {
254 IP_PATH,
255 "route",
256 add ? "add" : "del",
257 "default",
258 "dev",
259 iface,
260 "table",
261 mark_str
262 };
263 ret = runCmd(ARRAY_SIZE(route_cmd), route_cmd);
264
265 const char *fwmark_cmd[] = {
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700266 IP_PATH,
267 "rule",
268 add ? "add" : "del",
Chad Brubaker2349aa62013-07-15 15:28:59 -0700269 "prio",
270 RULE_PRIO,
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700271 "fwmark",
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700272 mark_str,
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700273 "table",
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700274 mark_str
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700275 };
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700276 ret = runCmd(ARRAY_SIZE(fwmark_cmd), fwmark_cmd);
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700277 if (ret) return ret;
278
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700279 //add rules for v6
280 const char *route6_cmd[] = {
281 IP_PATH,
282 "-6",
283 "route",
284 add ? "add" : "del",
285 "default",
286 "dev",
287 iface,
288 "table",
289 mark_str
290 };
291 ret = runCmd(ARRAY_SIZE(route6_cmd), route6_cmd);
292
293 const char *fwmark6_cmd[] = {
294 IP_PATH,
295 "-6",
296 "rule",
297 add ? "add" : "del",
Chad Brubaker2349aa62013-07-15 15:28:59 -0700298 "prio",
299 RULE_PRIO,
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700300 "fwmark",
301 mark_str,
302 "table",
303 mark_str
304 };
305 ret = runCmd(ARRAY_SIZE(fwmark6_cmd), fwmark6_cmd);
306
307
308 if (ret) return ret;
309
310 //create the route rule chain
311 char chain_str[IFNAMSIZ + 18];
312 snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
313 //code split due to ordering requirements
314 if (add) {
315 ret = execIptables(V4V6,
316 "-t",
317 "mangle",
318 "-N",
319 chain_str,
320 NULL);
321 //set up the rule for sending premarked packets to the VPN chain
322 //Insert these at the top of the chain so they trigger before any UID rules
323 ret |= execIptables(V4V6,
324 "-t",
325 "mangle",
326 "-I",
327 LOCAL_MANGLE_OUTPUT,
328 "3",
329 "-m",
330 "mark",
331 "--mark",
332 mark_str,
333 "-g",
334 chain_str,
335 NULL);
336 //add a rule to clear the mark in the VPN chain
337 //packets marked with SO_MARK already have the iface's mark set but unless they match a
338 //route they should hit the network instead of the VPN
339 ret |= execIptables(V4V6,
340 "-t",
341 "mangle",
342 "-A",
343 chain_str,
344 "-j",
345 "MARK",
346 "--set-mark",
347 "0",
348 NULL);
349
350 } else {
351 ret = execIptables(V4V6,
352 "-t",
353 "mangle",
354 "-D",
355 LOCAL_MANGLE_OUTPUT,
356 "-m",
357 "mark",
358 "--mark",
359 mark_str,
360 "-g",
361 chain_str,
362 NULL);
363
364 //clear and delete the chain
365 ret |= execIptables(V4V6,
366 "-t",
367 "mangle",
368 "-F",
369 chain_str,
370 NULL);
371
372 ret |= execIptables(V4V6,
373 "-t",
374 "mangle",
375 "-X",
376 chain_str,
377 NULL);
378 }
379
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700380 //set up the needed source IP rewriting
381 //NOTE: Without ipv6 NAT in the kernel <3.7 only support V4 NAT
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700382 ret = execIptables(V4,
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700383 "-t",
384 "nat",
385 add ? "-A" : "-D",
386 LOCAL_NAT_POSTROUTING,
387 "-o",
388 iface,
389 "-m",
390 "mark",
391 "--mark",
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700392 mark_str,
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700393 "-j",
394 "MASQUERADE",
395 NULL);
396
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700397 if (ret) return ret;
398
399 //try and set up for ipv6. ipv6 nat came in the kernel only in 3.7, so this can fail
400 ret = execIptables(V6,
401 "-t",
402 "nat",
403 add ? "-A" : "-D",
404 LOCAL_NAT_POSTROUTING,
405 "-o",
406 iface,
407 "-m",
408 "mark",
409 "--mark",
410 mark_str,
411 "-j",
412 "MASQUERADE",
413 NULL);
414 if (ret) {
415 //Without V6 NAT we can't do V6 over VPNs.
416 ret = execIptables(V6,
417 "-t",
418 "filter",
419 add ? "-A" : "-D",
420 LOCAL_FILTER_OUTPUT,
421 "-m",
422 "mark",
423 "--mark",
424 mark_str,
425 "-j",
426 "REJECT",
427 NULL);
428 }
429 return ret;
430
431}
432
433int SecondaryTableController::addFwmarkRoute(const char* iface, const char *dest, int prefix) {
434 return setFwmarkRoute(iface, dest, prefix, true);
435}
436
437int SecondaryTableController::removeFwmarkRoute(const char* iface, const char *dest, int prefix) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500438 return setFwmarkRoute(iface, dest, prefix, false);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700439}
440
441int SecondaryTableController::setFwmarkRoute(const char* iface, const char *dest, int prefix,
442 bool add) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500443 unsigned netId = mNetCtrl->getNetworkId(iface);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700444 char mark_str[11] = {0};
445 char chain_str[IFNAMSIZ + 18];
446 char dest_str[44]; // enough to store an IPv6 address + 3 character bitmask
447
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500448 snprintf(mark_str, sizeof(mark_str), "%u", netId + BASE_TABLE_NUMBER);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700449 snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
450 snprintf(dest_str, sizeof(dest_str), "%s/%d", dest, prefix);
451 return execIptables(getIptablesTarget(dest),
452 "-t",
453 "mangle",
454 add ? "-A" : "-D",
455 chain_str,
456 "-d",
457 dest_str,
458 "-j",
459 "MARK",
460 "--set-mark",
461 mark_str,
462 NULL);
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700463}
Robert Greenwaltc4621772012-01-31 12:46:45 -0800464
Chad Brubaker8830b942013-06-12 10:51:55 -0700465int SecondaryTableController::addUidRule(const char *iface, int uid_start, int uid_end) {
466 return setUidRule(iface, uid_start, uid_end, true);
Chad Brubaker9a508892013-05-31 20:51:46 -0700467}
468
Chad Brubaker8830b942013-06-12 10:51:55 -0700469int SecondaryTableController::removeUidRule(const char *iface, int uid_start, int uid_end) {
470 return setUidRule(iface, uid_start, uid_end, false);
Chad Brubaker9a508892013-05-31 20:51:46 -0700471}
472
Chad Brubaker8830b942013-06-12 10:51:55 -0700473int SecondaryTableController::setUidRule(const char *iface, int uid_start, int uid_end, bool add) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500474 unsigned netId = mNetCtrl->getNetworkId(iface);
475 if (!mNetCtrl->setNetworkForUidRange(uid_start, uid_end, add ? netId : 0, false)) {
Chad Brubakerd2617932013-06-21 15:26:35 -0700476 errno = EINVAL;
Chad Brubaker9a508892013-05-31 20:51:46 -0700477 return -1;
478 }
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500479
Chad Brubaker8830b942013-06-12 10:51:55 -0700480 char uid_str[24] = {0};
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700481 char chain_str[IFNAMSIZ + 18];
Chad Brubaker8830b942013-06-12 10:51:55 -0700482 snprintf(uid_str, sizeof(uid_str), "%d-%d", uid_start, uid_end);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700483 snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
Chad Brubaker9a508892013-05-31 20:51:46 -0700484 return execIptables(V4V6,
485 "-t",
486 "mangle",
487 add ? "-A" : "-D",
488 LOCAL_MANGLE_OUTPUT,
489 "-m",
490 "owner",
491 "--uid-owner",
Chad Brubaker8830b942013-06-12 10:51:55 -0700492 uid_str,
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700493 "-g",
494 chain_str,
Chad Brubaker9a508892013-05-31 20:51:46 -0700495 NULL);
496}
497
Chad Brubaker4a946092013-07-10 12:08:08 -0700498int SecondaryTableController::addHostExemption(const char *host) {
499 return setHostExemption(host, true);
500}
501
502int SecondaryTableController::removeHostExemption(const char *host) {
503 return setHostExemption(host, false);
504}
505
506int SecondaryTableController::setHostExemption(const char *host, bool add) {
507 IptablesTarget target = !strcmp(getVersion(host), "-4") ? V4 : V6;
508 char protect_mark_str[11];
509 snprintf(protect_mark_str, sizeof(protect_mark_str), "%d", PROTECT_MARK);
Chad Brubaker2349aa62013-07-15 15:28:59 -0700510 int ret = execIptables(target,
Chad Brubaker4a946092013-07-10 12:08:08 -0700511 "-t",
512 "mangle",
513 add ? "-A" : "-D",
514 LOCAL_MANGLE_EXEMPT,
515 "-d",
516 host,
517 "-j",
518 "MARK",
519 "--set-mark",
520 protect_mark_str,
521 NULL);
Chad Brubaker2349aa62013-07-15 15:28:59 -0700522 const char *cmd[] = {
523 IP_PATH,
524 getVersion(host),
525 "rule",
526 add ? "add" : "del",
527 "prio",
528 EXEMPT_PRIO,
529 "to",
530 host,
531 "table",
532 "main"
533 };
534 ret |= runCmd(ARRAY_SIZE(cmd), cmd);
535 return ret;
Chad Brubaker4a946092013-07-10 12:08:08 -0700536}
537
Chad Brubakerda7df7c2013-07-11 12:05:39 -0700538void SecondaryTableController::getUidMark(SocketClient *cli, int uid) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500539 unsigned netId = mNetCtrl->getNetwork(uid, NETID_UNSET, NetworkController::PID_UNSPECIFIED,
540 false);
Chad Brubakerda7df7c2013-07-11 12:05:39 -0700541 char mark_str[11];
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500542 snprintf(mark_str, sizeof(mark_str), "%u", netId + BASE_TABLE_NUMBER);
Chad Brubakerda7df7c2013-07-11 12:05:39 -0700543 cli->sendMsg(ResponseCode::GetMarkResult, mark_str, false);
544}
545
546void SecondaryTableController::getProtectMark(SocketClient *cli) {
547 char protect_mark_str[11];
548 snprintf(protect_mark_str, sizeof(protect_mark_str), "%d", PROTECT_MARK);
549 cli->sendMsg(ResponseCode::GetMarkResult, protect_mark_str, false);
550}
551
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800552int SecondaryTableController::runCmd(int argc, const char **argv) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700553 int ret = 0;
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800554
555 ret = android_fork_execvp(argc, (char **)argv, NULL, false, false);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700556 return ret;
557}