blob: fa096e0a4d536918dba4ae5b2536ac21e0b7eb9d [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>
29
30#define LOG_TAG "SecondaryTablController"
31#include <cutils/log.h>
32#include <cutils/properties.h>
Rom Lemarchand001f0a42013-01-31 12:41:03 -080033#include <logwrap/logwrap.h>
JP Abgrall9e5e0ce2011-12-14 15:20:59 -080034
Robert Greenwaltfc97b822011-11-02 16:48:36 -070035#include "ResponseCode.h"
Robert Greenwaltc4621772012-01-31 12:46:45 -080036#include "NetdConstants.h"
Robert Greenwaltfc97b822011-11-02 16:48:36 -070037#include "SecondaryTableController.h"
38
Chad Brubaker9a508892013-05-31 20:51:46 -070039const char* SecondaryTableController::LOCAL_MANGLE_OUTPUT = "st_mangle_OUTPUT";
Chad Brubaker4a946092013-07-10 12:08:08 -070040const char* SecondaryTableController::LOCAL_MANGLE_EXEMPT = "st_mangle_EXEMPT";
Chad Brubaker2251c0f2013-06-27 17:20:39 -070041const char* SecondaryTableController::LOCAL_MANGLE_IFACE_FORMAT = "st_mangle_%s_OUTPUT";
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -070042const char* SecondaryTableController::LOCAL_NAT_POSTROUTING = "st_nat_POSTROUTING";
Chad Brubaker2251c0f2013-06-27 17:20:39 -070043const char* SecondaryTableController::LOCAL_FILTER_OUTPUT = "st_filter_OUTPUT";
Chad Brubaker9a508892013-05-31 20:51:46 -070044
Chad Brubakerd2617932013-06-21 15:26:35 -070045SecondaryTableController::SecondaryTableController(UidMarkMap *map) : mUidMarkMap(map) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -070046 int i;
47 for (i=0; i < INTERFACES_TRACKED; i++) {
48 mInterfaceTable[i][0] = 0;
49 // TODO - use a hashtable or other prebuilt container class
50 mInterfaceRuleCount[i] = 0;
51 }
52}
53
54SecondaryTableController::~SecondaryTableController() {
55}
56
Chad Brubaker2251c0f2013-06-27 17:20:39 -070057int SecondaryTableController::setupIptablesHooks() {
58 int res = execIptables(V4V6,
59 "-t",
60 "mangle",
61 "-F",
62 LOCAL_MANGLE_OUTPUT,
63 NULL);
Chad Brubaker4a946092013-07-10 12:08:08 -070064 res |= execIptables(V4V6,
65 "-t",
66 "mangle",
67 "-F",
68 LOCAL_MANGLE_EXEMPT,
69 NULL);
Chad Brubaker2251c0f2013-06-27 17:20:39 -070070 //rule for skipping anything marked with the PROTECT_MARK
71 char protect_mark_str[11];
72 snprintf(protect_mark_str, sizeof(protect_mark_str), "%d", PROTECT_MARK);
73 res |= execIptables(V4V6,
74 "-t",
75 "mangle",
76 "-A",
77 LOCAL_MANGLE_OUTPUT,
78 "-m",
79 "mark",
80 "--mark",
81 protect_mark_str,
82 "-j",
83 "RETURN",
84 NULL);
85
86 //protect the legacy VPN daemons from routes.
87 //TODO: Remove this when legacy VPN's are removed.
88 res |= execIptables(V4V6,
89 "-t",
90 "mangle",
91 "-A",
92 LOCAL_MANGLE_OUTPUT,
93 "-m",
94 "owner",
95 "--uid-owner",
96 "vpn",
97 "-j",
98 "RETURN",
99 NULL);
100 return res;
101
102}
103
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700104int SecondaryTableController::findTableNumber(const char *iface) {
105 int i;
106 for (i = 0; i < INTERFACES_TRACKED; i++) {
Jaime A Lopez-Sollano3c207872012-01-11 16:29:28 -0800107 // compare through the final null, hence +1
108 if (strncmp(iface, mInterfaceTable[i], IFNAMSIZ + 1) == 0) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700109 return i;
110 }
111 }
112 return -1;
113}
114
115int SecondaryTableController::addRoute(SocketClient *cli, char *iface, char *dest, int prefix,
116 char *gateway) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700117 int tableIndex = findTableNumber(iface);
118 if (tableIndex == -1) {
119 tableIndex = findTableNumber(""); // look for an empty slot
120 if (tableIndex == -1) {
Steve Block5ea0c052012-01-06 19:18:11 +0000121 ALOGE("Max number of NATed interfaces reached");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700122 errno = ENODEV;
123 cli->sendMsg(ResponseCode::OperationFailed, "Max number NATed", true);
124 return -1;
125 }
Jaime A Lopez-Sollanod14fd4f2012-01-11 16:29:28 -0800126 strncpy(mInterfaceTable[tableIndex], iface, IFNAMSIZ);
127 // Ensure null termination even if truncation happened
128 mInterfaceTable[tableIndex][IFNAMSIZ] = 0;
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700129 }
130
Robert Greenwalt063af322011-11-18 15:32:13 -0800131 return modifyRoute(cli, ADD, iface, dest, prefix, gateway, tableIndex);
132}
133
Robert Greenwaltc4621772012-01-31 12:46:45 -0800134int SecondaryTableController::modifyRoute(SocketClient *cli, const char *action, char *iface,
135 char *dest, int prefix, char *gateway, int tableIndex) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800136 char dest_str[44]; // enough to store an IPv6 address + 3 character bitmask
137 char tableIndex_str[11];
138 int ret;
139
140 // IP tool doesn't like "::" - the equiv of 0.0.0.0 that it accepts for ipv4
141 snprintf(dest_str, sizeof(dest_str), "%s/%d", dest, prefix);
142 snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex + BASE_TABLE_NUMBER);
Robert Greenwalt063af322011-11-18 15:32:13 -0800143
144 if (strcmp("::", gateway) == 0) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800145 const char *cmd[] = {
146 IP_PATH,
147 "route",
148 action,
149 dest_str,
150 "dev",
151 iface,
152 "table",
153 tableIndex_str
154 };
155 ret = runCmd(ARRAY_SIZE(cmd), cmd);
Robert Greenwalt063af322011-11-18 15:32:13 -0800156 } else {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800157 const char *cmd[] = {
158 IP_PATH,
159 "route",
160 action,
161 dest_str,
162 "via",
163 gateway,
164 "dev",
165 iface,
166 "table",
167 tableIndex_str
168 };
169 ret = runCmd(ARRAY_SIZE(cmd), cmd);
Robert Greenwalt063af322011-11-18 15:32:13 -0800170 }
171
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800172 if (ret) {
Steve Block5ea0c052012-01-06 19:18:11 +0000173 ALOGE("ip route %s failed: %s route %s %s/%d via %s dev %s table %d", action,
Robert Greenwalt063af322011-11-18 15:32:13 -0800174 IP_PATH, action, dest, prefix, gateway, iface, tableIndex+BASE_TABLE_NUMBER);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700175 errno = ENODEV;
Robert Greenwalt063af322011-11-18 15:32:13 -0800176 cli->sendMsg(ResponseCode::OperationFailed, "ip route modification failed", true);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700177 return -1;
178 }
Robert Greenwalt063af322011-11-18 15:32:13 -0800179
180 if (strcmp(action, ADD) == 0) {
181 mInterfaceRuleCount[tableIndex]++;
182 } else {
183 if (--mInterfaceRuleCount[tableIndex] < 1) {
184 mInterfaceRuleCount[tableIndex] = 0;
185 mInterfaceTable[tableIndex][0] = 0;
186 }
187 }
Robert Greenwaltc4621772012-01-31 12:46:45 -0800188 modifyRuleCount(tableIndex, action);
Robert Greenwalt063af322011-11-18 15:32:13 -0800189 cli->sendMsg(ResponseCode::CommandOkay, "Route modified", false);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700190 return 0;
191}
192
Robert Greenwaltc4621772012-01-31 12:46:45 -0800193void SecondaryTableController::modifyRuleCount(int tableIndex, const char *action) {
194 if (strcmp(action, ADD) == 0) {
195 mInterfaceRuleCount[tableIndex]++;
196 } else {
197 if (--mInterfaceRuleCount[tableIndex] < 1) {
198 mInterfaceRuleCount[tableIndex] = 0;
199 mInterfaceTable[tableIndex][0] = 0;
200 }
201 }
202}
203
204int SecondaryTableController::verifyTableIndex(int tableIndex) {
205 if ((tableIndex < 0) ||
206 (tableIndex >= INTERFACES_TRACKED) ||
207 (mInterfaceTable[tableIndex][0] == 0)) {
208 return -1;
209 } else {
210 return 0;
211 }
212}
213
214const char *SecondaryTableController::getVersion(const char *addr) {
215 if (strchr(addr, ':') != NULL) {
216 return "-6";
217 } else {
218 return "-4";
219 }
220}
221
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700222IptablesTarget SecondaryTableController::getIptablesTarget(const char *addr) {
223 if (strchr(addr, ':') != NULL) {
224 return V6;
225 } else {
226 return V4;
227 }
228}
229
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700230int SecondaryTableController::removeRoute(SocketClient *cli, char *iface, char *dest, int prefix,
231 char *gateway) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700232 int tableIndex = findTableNumber(iface);
233 if (tableIndex == -1) {
Steve Block5ea0c052012-01-06 19:18:11 +0000234 ALOGE("Interface not found");
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700235 errno = ENODEV;
236 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
237 return -1;
238 }
239
Robert Greenwalt063af322011-11-18 15:32:13 -0800240 return modifyRoute(cli, DEL, iface, dest, prefix, gateway, tableIndex);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700241}
242
Robert Greenwaltc4621772012-01-31 12:46:45 -0800243int SecondaryTableController::modifyFromRule(int tableIndex, const char *action,
244 const char *addr) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800245 char tableIndex_str[11];
Robert Greenwaltc4621772012-01-31 12:46:45 -0800246
247 if (verifyTableIndex(tableIndex)) {
248 return -1;
249 }
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800250
251 snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex +
252 BASE_TABLE_NUMBER);
253 const char *cmd[] = {
254 IP_PATH,
255 getVersion(addr),
256 "rule",
257 action,
258 "from",
259 addr,
260 "table",
261 tableIndex_str
262 };
263 if (runCmd(ARRAY_SIZE(cmd), cmd)) {
Robert Greenwaltc4621772012-01-31 12:46:45 -0800264 return -1;
265 }
266
267 modifyRuleCount(tableIndex, action);
268 return 0;
269}
270
271int SecondaryTableController::modifyLocalRoute(int tableIndex, const char *action,
272 const char *iface, const char *addr) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800273 char tableIndex_str[11];
Robert Greenwaltc4621772012-01-31 12:46:45 -0800274
275 if (verifyTableIndex(tableIndex)) {
276 return -1;
277 }
278
279 modifyRuleCount(tableIndex, action); // some del's will fail as the iface is already gone.
280
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800281 snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex +
282 BASE_TABLE_NUMBER);
283 const char *cmd[] = {
284 IP_PATH,
285 "route",
286 action,
287 addr,
288 "dev",
289 iface,
290 "table",
291 tableIndex_str
292 };
293
294 return runCmd(ARRAY_SIZE(cmd), cmd);
Robert Greenwaltc4621772012-01-31 12:46:45 -0800295}
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700296int SecondaryTableController::addFwmarkRule(const char *iface) {
297 return setFwmarkRule(iface, true);
298}
299
300int SecondaryTableController::removeFwmarkRule(const char *iface) {
301 return setFwmarkRule(iface, false);
302}
303
304int SecondaryTableController::setFwmarkRule(const char *iface, bool add) {
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700305 int tableIndex = findTableNumber(iface);
306 if (tableIndex == -1) {
307 tableIndex = findTableNumber(""); // look for an empty slot
308 if (tableIndex == -1) {
309 ALOGE("Max number of NATed interfaces reached");
310 errno = ENODEV;
311 return -1;
312 }
313 strncpy(mInterfaceTable[tableIndex], iface, IFNAMSIZ);
314 // Ensure null termination even if truncation happened
315 mInterfaceTable[tableIndex][IFNAMSIZ] = 0;
316 }
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700317 int mark = tableIndex + BASE_TABLE_NUMBER;
318 char mark_str[11];
319 int ret;
320
321 //fail fast if any rules already exist for this interface
322 if (mUidMarkMap->anyRulesForMark(mark)) {
323 errno = EBUSY;
324 return -1;
325 }
326
327 snprintf(mark_str, sizeof(mark_str), "%d", mark);
328 //add the catch all route to the tun. Route rules will make sure the right packets hit the table
329 const char *route_cmd[] = {
330 IP_PATH,
331 "route",
332 add ? "add" : "del",
333 "default",
334 "dev",
335 iface,
336 "table",
337 mark_str
338 };
339 ret = runCmd(ARRAY_SIZE(route_cmd), route_cmd);
340
341 const char *fwmark_cmd[] = {
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700342 IP_PATH,
343 "rule",
344 add ? "add" : "del",
345 "fwmark",
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700346 mark_str,
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700347 "table",
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700348 mark_str
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700349 };
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700350 ret = runCmd(ARRAY_SIZE(fwmark_cmd), fwmark_cmd);
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700351 if (ret) return ret;
352
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700353 //add rules for v6
354 const char *route6_cmd[] = {
355 IP_PATH,
356 "-6",
357 "route",
358 add ? "add" : "del",
359 "default",
360 "dev",
361 iface,
362 "table",
363 mark_str
364 };
365 ret = runCmd(ARRAY_SIZE(route6_cmd), route6_cmd);
366
367 const char *fwmark6_cmd[] = {
368 IP_PATH,
369 "-6",
370 "rule",
371 add ? "add" : "del",
372 "fwmark",
373 mark_str,
374 "table",
375 mark_str
376 };
377 ret = runCmd(ARRAY_SIZE(fwmark6_cmd), fwmark6_cmd);
378
379
380 if (ret) return ret;
381
382 //create the route rule chain
383 char chain_str[IFNAMSIZ + 18];
384 snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
385 //code split due to ordering requirements
386 if (add) {
387 ret = execIptables(V4V6,
388 "-t",
389 "mangle",
390 "-N",
391 chain_str,
392 NULL);
393 //set up the rule for sending premarked packets to the VPN chain
394 //Insert these at the top of the chain so they trigger before any UID rules
395 ret |= execIptables(V4V6,
396 "-t",
397 "mangle",
398 "-I",
399 LOCAL_MANGLE_OUTPUT,
400 "3",
401 "-m",
402 "mark",
403 "--mark",
404 mark_str,
405 "-g",
406 chain_str,
407 NULL);
408 //add a rule to clear the mark in the VPN chain
409 //packets marked with SO_MARK already have the iface's mark set but unless they match a
410 //route they should hit the network instead of the VPN
411 ret |= execIptables(V4V6,
412 "-t",
413 "mangle",
414 "-A",
415 chain_str,
416 "-j",
417 "MARK",
418 "--set-mark",
419 "0",
420 NULL);
421
422 } else {
423 ret = execIptables(V4V6,
424 "-t",
425 "mangle",
426 "-D",
427 LOCAL_MANGLE_OUTPUT,
428 "-m",
429 "mark",
430 "--mark",
431 mark_str,
432 "-g",
433 chain_str,
434 NULL);
435
436 //clear and delete the chain
437 ret |= execIptables(V4V6,
438 "-t",
439 "mangle",
440 "-F",
441 chain_str,
442 NULL);
443
444 ret |= execIptables(V4V6,
445 "-t",
446 "mangle",
447 "-X",
448 chain_str,
449 NULL);
450 }
451
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700452 //set up the needed source IP rewriting
453 //NOTE: Without ipv6 NAT in the kernel <3.7 only support V4 NAT
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700454 ret = execIptables(V4,
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700455 "-t",
456 "nat",
457 add ? "-A" : "-D",
458 LOCAL_NAT_POSTROUTING,
459 "-o",
460 iface,
461 "-m",
462 "mark",
463 "--mark",
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700464 mark_str,
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700465 "-j",
466 "MASQUERADE",
467 NULL);
468
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700469 if (ret) return ret;
470
471 //try and set up for ipv6. ipv6 nat came in the kernel only in 3.7, so this can fail
472 ret = execIptables(V6,
473 "-t",
474 "nat",
475 add ? "-A" : "-D",
476 LOCAL_NAT_POSTROUTING,
477 "-o",
478 iface,
479 "-m",
480 "mark",
481 "--mark",
482 mark_str,
483 "-j",
484 "MASQUERADE",
485 NULL);
486 if (ret) {
487 //Without V6 NAT we can't do V6 over VPNs.
488 ret = execIptables(V6,
489 "-t",
490 "filter",
491 add ? "-A" : "-D",
492 LOCAL_FILTER_OUTPUT,
493 "-m",
494 "mark",
495 "--mark",
496 mark_str,
497 "-j",
498 "REJECT",
499 NULL);
500 }
501 return ret;
502
503}
504
505int SecondaryTableController::addFwmarkRoute(const char* iface, const char *dest, int prefix) {
506 return setFwmarkRoute(iface, dest, prefix, true);
507}
508
509int SecondaryTableController::removeFwmarkRoute(const char* iface, const char *dest, int prefix) {
510 return setFwmarkRoute(iface, dest, prefix, true);
511}
512
513int SecondaryTableController::setFwmarkRoute(const char* iface, const char *dest, int prefix,
514 bool add) {
515 int tableIndex = findTableNumber(iface);
516 if (tableIndex == -1) {
517 errno = EINVAL;
518 return -1;
519 }
520 int mark = tableIndex + BASE_TABLE_NUMBER;
521 char mark_str[11] = {0};
522 char chain_str[IFNAMSIZ + 18];
523 char dest_str[44]; // enough to store an IPv6 address + 3 character bitmask
524
525 snprintf(mark_str, sizeof(mark_str), "%d", mark);
526 snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
527 snprintf(dest_str, sizeof(dest_str), "%s/%d", dest, prefix);
528 return execIptables(getIptablesTarget(dest),
529 "-t",
530 "mangle",
531 add ? "-A" : "-D",
532 chain_str,
533 "-d",
534 dest_str,
535 "-j",
536 "MARK",
537 "--set-mark",
538 mark_str,
539 NULL);
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700540}
Robert Greenwaltc4621772012-01-31 12:46:45 -0800541
Chad Brubaker8830b942013-06-12 10:51:55 -0700542int SecondaryTableController::addUidRule(const char *iface, int uid_start, int uid_end) {
543 return setUidRule(iface, uid_start, uid_end, true);
Chad Brubaker9a508892013-05-31 20:51:46 -0700544}
545
Chad Brubaker8830b942013-06-12 10:51:55 -0700546int SecondaryTableController::removeUidRule(const char *iface, int uid_start, int uid_end) {
547 return setUidRule(iface, uid_start, uid_end, false);
Chad Brubaker9a508892013-05-31 20:51:46 -0700548}
549
Chad Brubaker8830b942013-06-12 10:51:55 -0700550int SecondaryTableController::setUidRule(const char *iface, int uid_start, int uid_end, bool add) {
Chad Brubaker9a508892013-05-31 20:51:46 -0700551 int tableIndex = findTableNumber(iface);
552 if (tableIndex == -1) {
Chad Brubakerd2617932013-06-21 15:26:35 -0700553 errno = EINVAL;
Chad Brubaker9a508892013-05-31 20:51:46 -0700554 return -1;
555 }
Chad Brubakerd2617932013-06-21 15:26:35 -0700556 int mark = tableIndex + BASE_TABLE_NUMBER;
557 if (add) {
558 if (!mUidMarkMap->add(uid_start, uid_end, mark)) {
559 errno = EINVAL;
560 return -1;
561 }
562 } else {
563 if (!mUidMarkMap->remove(uid_start, uid_end, mark)) {
564 errno = EINVAL;
565 return -1;
566 }
567 }
Chad Brubaker8830b942013-06-12 10:51:55 -0700568 char uid_str[24] = {0};
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700569 char chain_str[IFNAMSIZ + 18];
Chad Brubaker8830b942013-06-12 10:51:55 -0700570 snprintf(uid_str, sizeof(uid_str), "%d-%d", uid_start, uid_end);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700571 snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
Chad Brubaker9a508892013-05-31 20:51:46 -0700572 return execIptables(V4V6,
573 "-t",
574 "mangle",
575 add ? "-A" : "-D",
576 LOCAL_MANGLE_OUTPUT,
577 "-m",
578 "owner",
579 "--uid-owner",
Chad Brubaker8830b942013-06-12 10:51:55 -0700580 uid_str,
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700581 "-g",
582 chain_str,
Chad Brubaker9a508892013-05-31 20:51:46 -0700583 NULL);
584}
585
Chad Brubaker4a946092013-07-10 12:08:08 -0700586int SecondaryTableController::addHostExemption(const char *host) {
587 return setHostExemption(host, true);
588}
589
590int SecondaryTableController::removeHostExemption(const char *host) {
591 return setHostExemption(host, false);
592}
593
594int SecondaryTableController::setHostExemption(const char *host, bool add) {
595 IptablesTarget target = !strcmp(getVersion(host), "-4") ? V4 : V6;
596 char protect_mark_str[11];
597 snprintf(protect_mark_str, sizeof(protect_mark_str), "%d", PROTECT_MARK);
598 return execIptables(target,
599 "-t",
600 "mangle",
601 add ? "-A" : "-D",
602 LOCAL_MANGLE_EXEMPT,
603 "-d",
604 host,
605 "-j",
606 "MARK",
607 "--set-mark",
608 protect_mark_str,
609 NULL);
610}
611
Chad Brubakerda7df7c2013-07-11 12:05:39 -0700612void SecondaryTableController::getUidMark(SocketClient *cli, int uid) {
613 int mark = mUidMarkMap->getMark(uid);
614 char mark_str[11];
615 snprintf(mark_str, sizeof(mark_str), "%d", mark);
616 cli->sendMsg(ResponseCode::GetMarkResult, mark_str, false);
617}
618
619void SecondaryTableController::getProtectMark(SocketClient *cli) {
620 char protect_mark_str[11];
621 snprintf(protect_mark_str, sizeof(protect_mark_str), "%d", PROTECT_MARK);
622 cli->sendMsg(ResponseCode::GetMarkResult, protect_mark_str, false);
623}
624
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800625int SecondaryTableController::runCmd(int argc, const char **argv) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700626 int ret = 0;
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800627
628 ret = android_fork_execvp(argc, (char **)argv, NULL, false, false);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700629 return ret;
630}