blob: 398edd1c2146554f21deb0031a176c90ea319494 [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";
JP Abgrall9440e7f2013-11-20 17:27:01 -080041const char* SecondaryTableController::LOCAL_MANGLE_POSTROUTING = "st_mangle_POSTROUTING";
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -070042const char* SecondaryTableController::LOCAL_NAT_POSTROUTING = "st_nat_POSTROUTING";
Chad Brubaker9a508892013-05-31 20:51:46 -070043
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050044SecondaryTableController::SecondaryTableController(NetworkController* controller) :
45 mNetCtrl(controller) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -070046}
47
48SecondaryTableController::~SecondaryTableController() {
49}
50
Chad Brubaker2251c0f2013-06-27 17:20:39 -070051int SecondaryTableController::setupIptablesHooks() {
52 int res = execIptables(V4V6,
53 "-t",
54 "mangle",
55 "-F",
56 LOCAL_MANGLE_OUTPUT,
57 NULL);
Chad Brubaker797ec702014-02-06 13:38:41 -080058 // Do not mark sockets that have already been marked elsewhere(for example in DNS or protect).
Chad Brubaker2251c0f2013-06-27 17:20:39 -070059 res |= execIptables(V4V6,
60 "-t",
61 "mangle",
62 "-A",
63 LOCAL_MANGLE_OUTPUT,
64 "-m",
65 "mark",
Chad Brubaker797ec702014-02-06 13:38:41 -080066 "!",
Chad Brubaker2251c0f2013-06-27 17:20:39 -070067 "--mark",
Chad Brubaker797ec702014-02-06 13:38:41 -080068 "0",
Chad Brubaker2251c0f2013-06-27 17:20:39 -070069 "-j",
70 "RETURN",
71 NULL);
72
Chad Brubaker2349aa62013-07-15 15:28:59 -070073 // protect the legacy VPN daemons from routes.
74 // TODO: Remove this when legacy VPN's are removed.
Chad Brubaker2251c0f2013-06-27 17:20:39 -070075 res |= execIptables(V4V6,
76 "-t",
77 "mangle",
78 "-A",
79 LOCAL_MANGLE_OUTPUT,
80 "-m",
81 "owner",
82 "--uid-owner",
83 "vpn",
84 "-j",
85 "RETURN",
86 NULL);
87 return res;
Chad Brubaker2251c0f2013-06-27 17:20:39 -070088}
89
Robert Greenwaltfc97b822011-11-02 16:48:36 -070090int SecondaryTableController::addRoute(SocketClient *cli, char *iface, char *dest, int prefix,
91 char *gateway) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050092 return modifyRoute(cli, ADD, iface, dest, prefix, gateway, mNetCtrl->getNetworkId(iface));
Robert Greenwalt063af322011-11-18 15:32:13 -080093}
94
Robert Greenwaltc4621772012-01-31 12:46:45 -080095int SecondaryTableController::modifyRoute(SocketClient *cli, const char *action, char *iface,
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -050096 char *dest, int prefix, char *gateway, unsigned netId) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -080097 char dest_str[44]; // enough to store an IPv6 address + 3 character bitmask
98 char tableIndex_str[11];
99 int ret;
100
101 // IP tool doesn't like "::" - the equiv of 0.0.0.0 that it accepts for ipv4
102 snprintf(dest_str, sizeof(dest_str), "%s/%d", dest, prefix);
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500103 snprintf(tableIndex_str, sizeof(tableIndex_str), "%u", netId + BASE_TABLE_NUMBER);
Robert Greenwalt063af322011-11-18 15:32:13 -0800104
105 if (strcmp("::", gateway) == 0) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800106 const char *cmd[] = {
107 IP_PATH,
108 "route",
109 action,
110 dest_str,
111 "dev",
112 iface,
113 "table",
114 tableIndex_str
115 };
116 ret = runCmd(ARRAY_SIZE(cmd), cmd);
Robert Greenwalt063af322011-11-18 15:32:13 -0800117 } else {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800118 const char *cmd[] = {
119 IP_PATH,
120 "route",
121 action,
122 dest_str,
123 "via",
124 gateway,
125 "dev",
126 iface,
127 "table",
128 tableIndex_str
129 };
130 ret = runCmd(ARRAY_SIZE(cmd), cmd);
Robert Greenwalt063af322011-11-18 15:32:13 -0800131 }
132
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800133 if (ret) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500134 ALOGE("ip route %s failed: %s route %s %s/%d via %s dev %s table %u", action,
135 IP_PATH, action, dest, prefix, gateway, iface, netId + BASE_TABLE_NUMBER);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700136 errno = ENODEV;
Robert Greenwalt063af322011-11-18 15:32:13 -0800137 cli->sendMsg(ResponseCode::OperationFailed, "ip route modification failed", true);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700138 return -1;
139 }
Robert Greenwalt063af322011-11-18 15:32:13 -0800140
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500141 modifyRuleCount(netId, action);
Robert Greenwalt063af322011-11-18 15:32:13 -0800142 cli->sendMsg(ResponseCode::CommandOkay, "Route modified", false);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700143 return 0;
144}
145
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500146void SecondaryTableController::modifyRuleCount(unsigned netId, const char *action) {
Robert Greenwaltc4621772012-01-31 12:46:45 -0800147 if (strcmp(action, ADD) == 0) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500148 if (mNetIdRuleCount.count(netId) == 0)
149 mNetIdRuleCount[netId] = 0;
150 mNetIdRuleCount[netId]++;
Robert Greenwaltc4621772012-01-31 12:46:45 -0800151 } else {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500152 if (mNetIdRuleCount.count(netId) > 0) {
153 if (--mNetIdRuleCount[netId] < 1) {
154 mNetIdRuleCount.erase(mNetIdRuleCount.find(netId));
155 }
Robert Greenwaltc4621772012-01-31 12:46:45 -0800156 }
157 }
158}
159
Robert Greenwaltc4621772012-01-31 12:46:45 -0800160const char *SecondaryTableController::getVersion(const char *addr) {
161 if (strchr(addr, ':') != NULL) {
162 return "-6";
163 } else {
164 return "-4";
165 }
166}
167
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700168IptablesTarget SecondaryTableController::getIptablesTarget(const char *addr) {
169 if (strchr(addr, ':') != NULL) {
170 return V6;
171 } else {
172 return V4;
173 }
174}
175
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700176int SecondaryTableController::removeRoute(SocketClient *cli, char *iface, char *dest, int prefix,
177 char *gateway) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500178 return modifyRoute(cli, DEL, iface, dest, prefix, gateway, mNetCtrl->getNetworkId(iface));
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700179}
180
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500181int SecondaryTableController::modifyFromRule(unsigned netId, const char *action,
Robert Greenwaltc4621772012-01-31 12:46:45 -0800182 const char *addr) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800183 char tableIndex_str[11];
Robert Greenwaltc4621772012-01-31 12:46:45 -0800184
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500185 snprintf(tableIndex_str, sizeof(tableIndex_str), "%u", netId + BASE_TABLE_NUMBER);
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800186 const char *cmd[] = {
187 IP_PATH,
188 getVersion(addr),
189 "rule",
190 action,
191 "from",
192 addr,
193 "table",
194 tableIndex_str
195 };
196 if (runCmd(ARRAY_SIZE(cmd), cmd)) {
Robert Greenwaltc4621772012-01-31 12:46:45 -0800197 return -1;
198 }
199
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500200 modifyRuleCount(netId, action);
Robert Greenwaltc4621772012-01-31 12:46:45 -0800201 return 0;
202}
203
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500204int SecondaryTableController::modifyLocalRoute(unsigned netId, const char *action,
Robert Greenwaltc4621772012-01-31 12:46:45 -0800205 const char *iface, const char *addr) {
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800206 char tableIndex_str[11];
Robert Greenwaltc4621772012-01-31 12:46:45 -0800207
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500208 modifyRuleCount(netId, action); // some del's will fail as the iface is already gone.
209 snprintf(tableIndex_str, sizeof(tableIndex_str), "%u", netId + BASE_TABLE_NUMBER);
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800210 const char *cmd[] = {
211 IP_PATH,
212 "route",
213 action,
214 addr,
215 "dev",
216 iface,
217 "table",
218 tableIndex_str
219 };
220
221 return runCmd(ARRAY_SIZE(cmd), cmd);
Robert Greenwaltc4621772012-01-31 12:46:45 -0800222}
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700223int SecondaryTableController::addFwmarkRule(const char *iface) {
224 return setFwmarkRule(iface, true);
225}
226
227int SecondaryTableController::removeFwmarkRule(const char *iface) {
228 return setFwmarkRule(iface, false);
229}
230
231int SecondaryTableController::setFwmarkRule(const char *iface, bool add) {
JP Abgrall69261cb2014-06-19 18:35:24 -0700232 if (!isIfaceName(iface)) {
233 errno = ENOENT;
234 return -1;
235 }
236
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500237 unsigned netId = mNetCtrl->getNetworkId(iface);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700238
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500239 // Fail fast if any rules already exist for this interface
240 if (mNetIdRuleCount.count(netId) > 0) {
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700241 errno = EBUSY;
242 return -1;
243 }
244
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500245 int ret;
246 char mark_str[11];
247 snprintf(mark_str, sizeof(mark_str), "%u", netId + BASE_TABLE_NUMBER);
Chad Brubaker797ec702014-02-06 13:38:41 -0800248 // Flush any marked routes we added
249 if (!add) {
250 // iproute2 rule del will delete anything that matches, but only one rule at a time.
251 // So clearing the rules requires a bunch of calls.
252 // ip rule del will fail once there are no remaining rules that match.
253 const char *v4_cmd[] = {
254 IP_PATH,
255 "-4",
256 "rule",
257 "del",
258 "fwmark",
259 mark_str,
260 "table",
261 mark_str
262 };
263 while(!runCmd(ARRAY_SIZE(v4_cmd), v4_cmd)) {}
264
265 const char *v6_cmd[] = {
266 IP_PATH,
267 "-6",
268 "rule",
269 "del",
270 "fwmark",
271 mark_str,
272 "table",
273 mark_str
274 };
275 while(!runCmd(ARRAY_SIZE(v6_cmd), v6_cmd)) {}
276 }
277 // Add a route to the table to send all traffic to iface.
278 // We only need a default route because this table is only selected if a packet matches an
279 // IP rule that checks both the route and the mark.
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700280 const char *route_cmd[] = {
281 IP_PATH,
282 "route",
283 add ? "add" : "del",
284 "default",
285 "dev",
286 iface,
287 "table",
288 mark_str
289 };
290 ret = runCmd(ARRAY_SIZE(route_cmd), route_cmd);
Chad Brubaker797ec702014-02-06 13:38:41 -0800291 // The command might fail during delete if the iface is gone
292 if (add && ret) return ret;
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700293
Chad Brubaker797ec702014-02-06 13:38:41 -0800294 // As above for IPv6
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700295 const char *route6_cmd[] = {
296 IP_PATH,
297 "-6",
298 "route",
299 add ? "add" : "del",
300 "default",
301 "dev",
302 iface,
303 "table",
304 mark_str
305 };
306 ret = runCmd(ARRAY_SIZE(route6_cmd), route6_cmd);
Chad Brubaker797ec702014-02-06 13:38:41 -0800307 // The command might fail during delete if the iface is gone
308 if (add && ret) return ret;
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700309
Chad Brubaker797ec702014-02-06 13:38:41 -0800310 /* Best effort, because some kernels might not have the needed TCPMSS */
311 execIptables(V4V6,
312 "-t",
313 "mangle",
314 add ? "-A" : "-D",
315 LOCAL_MANGLE_POSTROUTING,
316 "-p", "tcp", "-o", iface, "--tcp-flags", "SYN,RST", "SYN",
317 "-j",
318 "TCPMSS",
319 "--clamp-mss-to-pmtu",
320 NULL);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700321
Chad Brubaker797ec702014-02-06 13:38:41 -0800322 // Because the mark gets set after the intial routing decision the source IP address is that
323 // of the original out interface. The only way to change the source IP address to that of the
324 // VPN iface is using source NAT.
325 // TODO: Remove this when we get the mark set correctly before the first routing pass.
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700326 ret = execIptables(V4,
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700327 "-t",
328 "nat",
329 add ? "-A" : "-D",
330 LOCAL_NAT_POSTROUTING,
331 "-o",
332 iface,
333 "-m",
334 "mark",
335 "--mark",
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700336 mark_str,
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700337 "-j",
338 "MASQUERADE",
339 NULL);
340
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700341 if (ret) return ret;
342
Chad Brubaker797ec702014-02-06 13:38:41 -0800343 // Try and set up NAT for IPv6 as well. This was only added in Linux 3.7 so this may fail.
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700344 ret = execIptables(V6,
345 "-t",
346 "nat",
347 add ? "-A" : "-D",
348 LOCAL_NAT_POSTROUTING,
349 "-o",
350 iface,
351 "-m",
352 "mark",
353 "--mark",
354 mark_str,
355 "-j",
356 "MASQUERADE",
357 NULL);
358 if (ret) {
Chad Brubaker797ec702014-02-06 13:38:41 -0800359 // Without V6 NAT we can't do V6 over VPNs. If an IPv6 packet matches a VPN rule, then it
360 // will go out on the VPN interface, but without NAT, it will have the wrong source
361 // address. So reject all these packets.
362 // Due to rule application by the time the connection hits the output filter chain the
363 // routing pass based on the new mark has not yet happened. Reject in ip instead.
364 // TODO: Make the VPN code refuse to install IPv6 routes until we don't need IPv6 NAT.
365 const char *reject_cmd[] = {
366 IP_PATH,
367 "-6",
368 "route",
369 add ? "replace" : "del",
370 "unreachable",
371 "default",
372 "table",
373 mark_str
374 };
375 ret = runCmd(ARRAY_SIZE(reject_cmd), reject_cmd);
376 // The command might fail during delete if the iface is gone
377 if (add && ret) return ret;
378
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700379 }
Chad Brubaker797ec702014-02-06 13:38:41 -0800380 return 0;
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700381
382}
383
384int SecondaryTableController::addFwmarkRoute(const char* iface, const char *dest, int prefix) {
385 return setFwmarkRoute(iface, dest, prefix, true);
386}
387
388int SecondaryTableController::removeFwmarkRoute(const char* iface, const char *dest, int prefix) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500389 return setFwmarkRoute(iface, dest, prefix, false);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700390}
391
392int SecondaryTableController::setFwmarkRoute(const char* iface, const char *dest, int prefix,
393 bool add) {
JP Abgrall69261cb2014-06-19 18:35:24 -0700394 if (!isIfaceName(iface)) {
395 errno = ENOENT;
396 return -1;
397 }
398
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500399 unsigned netId = mNetCtrl->getNetworkId(iface);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700400 char mark_str[11] = {0};
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700401 char dest_str[44]; // enough to store an IPv6 address + 3 character bitmask
402
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500403 snprintf(mark_str, sizeof(mark_str), "%u", netId + BASE_TABLE_NUMBER);
Chad Brubaker2251c0f2013-06-27 17:20:39 -0700404 snprintf(dest_str, sizeof(dest_str), "%s/%d", dest, prefix);
Chad Brubaker797ec702014-02-06 13:38:41 -0800405 const char *rule_cmd[] = {
406 IP_PATH,
407 getVersion(dest_str),
408 "rule",
409 add ? "add" : "del",
410 "prio",
411 RULE_PRIO,
412 "to",
413 dest_str,
414 "fwmark",
415 mark_str,
416 "table",
417 mark_str
418 };
419 return runCmd(ARRAY_SIZE(rule_cmd), rule_cmd);
Chad Brubaker7a6ce4b2013-06-06 21:42:53 -0700420}
Robert Greenwaltc4621772012-01-31 12:46:45 -0800421
Paul Jensen35c77e32014-04-10 14:57:54 -0400422int SecondaryTableController::addUidRule(const char *iface, int uid_start, int uid_end,
423 bool forward_dns) {
424 return setUidRule(iface, uid_start, uid_end, true, forward_dns);
Chad Brubaker9a508892013-05-31 20:51:46 -0700425}
426
Chad Brubaker8830b942013-06-12 10:51:55 -0700427int SecondaryTableController::removeUidRule(const char *iface, int uid_start, int uid_end) {
Paul Jensen35c77e32014-04-10 14:57:54 -0400428 return setUidRule(iface, uid_start, uid_end, false, false);
Chad Brubaker9a508892013-05-31 20:51:46 -0700429}
430
Paul Jensen35c77e32014-04-10 14:57:54 -0400431int SecondaryTableController::setUidRule(const char *iface, int uid_start, int uid_end, bool add,
432 bool forward_dns) {
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500433 unsigned netId = mNetCtrl->getNetworkId(iface);
Paul Jensen35c77e32014-04-10 14:57:54 -0400434 if (add) {
435 if (!mNetCtrl->setNetworkForUidRange(uid_start, uid_end, netId, forward_dns)) {
Lorenzo Colittice8f5832014-05-29 12:20:55 +0900436 // errno is set by setNetworkForUidRange.
Paul Jensen35c77e32014-04-10 14:57:54 -0400437 return -1;
438 }
439 } else {
440 if (!mNetCtrl->clearNetworkForUidRange(uid_start, uid_end, netId)) {
Lorenzo Colittice8f5832014-05-29 12:20:55 +0900441 // errno is set by clearNetworkForUidRange.
Paul Jensen35c77e32014-04-10 14:57:54 -0400442 return -1;
443 }
Chad Brubaker9a508892013-05-31 20:51:46 -0700444 }
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500445
Chad Brubaker8830b942013-06-12 10:51:55 -0700446 char uid_str[24] = {0};
447 snprintf(uid_str, sizeof(uid_str), "%d-%d", uid_start, uid_end);
Chad Brubaker797ec702014-02-06 13:38:41 -0800448 char mark_str[11] = {0};
Paul Jensen5b49ab92014-04-03 19:06:00 -0400449 snprintf(mark_str, sizeof(mark_str), "%u", netId + BASE_TABLE_NUMBER);
Chad Brubaker9a508892013-05-31 20:51:46 -0700450 return execIptables(V4V6,
451 "-t",
452 "mangle",
453 add ? "-A" : "-D",
454 LOCAL_MANGLE_OUTPUT,
455 "-m",
456 "owner",
457 "--uid-owner",
Chad Brubaker8830b942013-06-12 10:51:55 -0700458 uid_str,
Chad Brubaker797ec702014-02-06 13:38:41 -0800459 "-j",
460 "MARK",
461 "--set-mark",
462 mark_str,
Chad Brubaker9a508892013-05-31 20:51:46 -0700463 NULL);
464}
465
Chad Brubaker4a946092013-07-10 12:08:08 -0700466int SecondaryTableController::addHostExemption(const char *host) {
467 return setHostExemption(host, true);
468}
469
470int SecondaryTableController::removeHostExemption(const char *host) {
471 return setHostExemption(host, false);
472}
473
474int SecondaryTableController::setHostExemption(const char *host, bool add) {
Chad Brubaker2349aa62013-07-15 15:28:59 -0700475 const char *cmd[] = {
476 IP_PATH,
477 getVersion(host),
478 "rule",
479 add ? "add" : "del",
480 "prio",
481 EXEMPT_PRIO,
482 "to",
483 host,
484 "table",
485 "main"
486 };
Chad Brubaker797ec702014-02-06 13:38:41 -0800487 return runCmd(ARRAY_SIZE(cmd), cmd);
Chad Brubaker4a946092013-07-10 12:08:08 -0700488}
489
Chad Brubakerda7df7c2013-07-11 12:05:39 -0700490void SecondaryTableController::getUidMark(SocketClient *cli, int uid) {
Paul Jensen35c77e32014-04-10 14:57:54 -0400491 unsigned netId = mNetCtrl->getNetwork(uid, NETID_UNSET, false);
Chad Brubakerda7df7c2013-07-11 12:05:39 -0700492 char mark_str[11];
Szymon Jakubczaka0efaec2014-02-14 17:09:43 -0500493 snprintf(mark_str, sizeof(mark_str), "%u", netId + BASE_TABLE_NUMBER);
Chad Brubakerda7df7c2013-07-11 12:05:39 -0700494 cli->sendMsg(ResponseCode::GetMarkResult, mark_str, false);
495}
496
497void SecondaryTableController::getProtectMark(SocketClient *cli) {
498 char protect_mark_str[11];
499 snprintf(protect_mark_str, sizeof(protect_mark_str), "%d", PROTECT_MARK);
500 cli->sendMsg(ResponseCode::GetMarkResult, protect_mark_str, false);
501}
502
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800503int SecondaryTableController::runCmd(int argc, const char **argv) {
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700504 int ret = 0;
Rom Lemarchand001f0a42013-01-31 12:41:03 -0800505
506 ret = android_fork_execvp(argc, (char **)argv, NULL, false, false);
Robert Greenwaltfc97b822011-11-02 16:48:36 -0700507 return ret;
508}