1fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt/*
2fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * Copyright (C) 2008 The Android Open Source Project
3fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt *
4fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
5fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * you may not use this file except in compliance with the License.
6fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * You may obtain a copy of the License at
7fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt *
8fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt *      http://www.apache.org/licenses/LICENSE-2.0
9fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt *
10fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * Unless required by applicable law or agreed to in writing, software
11fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
12fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * See the License for the specific language governing permissions and
14fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * limitations under the License.
15fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt */
16fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
17fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <stdlib.h>
18fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <errno.h>
19fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <fcntl.h>
20fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <string.h>
21fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
22fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <sys/socket.h>
23fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <sys/stat.h>
24fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <sys/types.h>
25fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <sys/wait.h>
26fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
27fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <netinet/in.h>
28fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <arpa/inet.h>
29fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
30fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#define LOG_TAG "SecondaryTablController"
31fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <cutils/log.h>
32fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <cutils/properties.h>
33001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand#include <logwrap/logwrap.h>
349e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall
35fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include "ResponseCode.h"
36c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt#include "NetdConstants.h"
37fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include "SecondaryTableController.h"
38fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
399a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubakerconst char* SecondaryTableController::LOCAL_MANGLE_OUTPUT = "st_mangle_OUTPUT";
40ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrallconst char* SecondaryTableController::LOCAL_MANGLE_POSTROUTING = "st_mangle_POSTROUTING";
414a946095dad15548ae399665be111be9cb1d9aa6Chad Brubakerconst char* SecondaryTableController::LOCAL_MANGLE_EXEMPT = "st_mangle_EXEMPT";
422251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubakerconst char* SecondaryTableController::LOCAL_MANGLE_IFACE_FORMAT = "st_mangle_%s_OUTPUT";
437a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubakerconst char* SecondaryTableController::LOCAL_NAT_POSTROUTING = "st_nat_POSTROUTING";
442251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubakerconst char* SecondaryTableController::LOCAL_FILTER_OUTPUT = "st_filter_OUTPUT";
459a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker
46d2617936acc15567fc5111bbdb4dde20845c3cbaChad BrubakerSecondaryTableController::SecondaryTableController(UidMarkMap *map) : mUidMarkMap(map) {
47fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int i;
48fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    for (i=0; i < INTERFACES_TRACKED; i++) {
49fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        mInterfaceTable[i][0] = 0;
50fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        // TODO - use a hashtable or other prebuilt container class
51fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        mInterfaceRuleCount[i] = 0;
52fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
53fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
54fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
55fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert GreenwaltSecondaryTableController::~SecondaryTableController() {
56fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
57fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
582251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubakerint SecondaryTableController::setupIptablesHooks() {
592251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    int res = execIptables(V4V6,
602251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-t",
612251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "mangle",
622251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-F",
632251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            LOCAL_MANGLE_OUTPUT,
642251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            NULL);
654a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker    res |= execIptables(V4V6,
664a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            "-t",
674a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            "mangle",
684a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            "-F",
694a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            LOCAL_MANGLE_EXEMPT,
704a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            NULL);
712349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker    // rule for skipping anything marked with the PROTECT_MARK
722251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    char protect_mark_str[11];
732251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    snprintf(protect_mark_str, sizeof(protect_mark_str), "%d", PROTECT_MARK);
742251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    res |= execIptables(V4V6,
752251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-t",
762251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "mangle",
772251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-A",
782251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            LOCAL_MANGLE_OUTPUT,
792251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-m",
802251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "mark",
812251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "--mark",
822251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            protect_mark_str,
832251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-j",
842251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "RETURN",
852251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            NULL);
862251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
872349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker    // protect the legacy VPN daemons from routes.
882349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker    // TODO: Remove this when legacy VPN's are removed.
892251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    res |= execIptables(V4V6,
902251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-t",
912251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "mangle",
922251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-A",
932251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            LOCAL_MANGLE_OUTPUT,
942251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-m",
952251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "owner",
962251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "--uid-owner",
972251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "vpn",
982251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-j",
992251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "RETURN",
1002251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            NULL);
1012251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    return res;
1022251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker}
1032251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
104fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::findTableNumber(const char *iface) {
105fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int i;
106fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    for (i = 0; i < INTERFACES_TRACKED; i++) {
1073c20787d7935c2016e8e3cc49d8f15647c12c41cJaime A Lopez-Sollano        // compare through the final null, hence +1
1083c20787d7935c2016e8e3cc49d8f15647c12c41cJaime A Lopez-Sollano        if (strncmp(iface, mInterfaceTable[i], IFNAMSIZ + 1) == 0) {
109fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            return i;
110fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
111fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
112fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return -1;
113fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
114fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
115fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::addRoute(SocketClient *cli, char *iface, char *dest, int prefix,
116fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        char *gateway) {
117fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int tableIndex = findTableNumber(iface);
118fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (tableIndex == -1) {
119fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        tableIndex = findTableNumber(""); // look for an empty slot
120fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        if (tableIndex == -1) {
1215ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Max number of NATed interfaces reached");
122fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            errno = ENODEV;
123fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            cli->sendMsg(ResponseCode::OperationFailed, "Max number NATed", true);
124fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            return -1;
125fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
126d14fd4f83ffeea4ad1cd559a41f775f6814565ccJaime A Lopez-Sollano        strncpy(mInterfaceTable[tableIndex], iface, IFNAMSIZ);
127d14fd4f83ffeea4ad1cd559a41f775f6814565ccJaime A Lopez-Sollano        // Ensure null termination even if truncation happened
128d14fd4f83ffeea4ad1cd559a41f775f6814565ccJaime A Lopez-Sollano        mInterfaceTable[tableIndex][IFNAMSIZ] = 0;
129fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
130fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
131063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    return modifyRoute(cli, ADD, iface, dest, prefix, gateway, tableIndex);
132063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt}
133063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
134c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltint SecondaryTableController::modifyRoute(SocketClient *cli, const char *action, char *iface,
135c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        char *dest, int prefix, char *gateway, int tableIndex) {
136001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    char dest_str[44]; // enough to store an IPv6 address + 3 character bitmask
137001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    char tableIndex_str[11];
138001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    int ret;
139001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
140001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    //  IP tool doesn't like "::" - the equiv of 0.0.0.0 that it accepts for ipv4
141001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    snprintf(dest_str, sizeof(dest_str), "%s/%d", dest, prefix);
142001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex + BASE_TABLE_NUMBER);
143063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
144063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    if (strcmp("::", gateway) == 0) {
145001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        const char *cmd[] = {
146001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                IP_PATH,
147001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "route",
148001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                action,
149001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                dest_str,
150001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "dev",
151001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                iface,
152001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "table",
153001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                tableIndex_str
154001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        };
155001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        ret = runCmd(ARRAY_SIZE(cmd), cmd);
156063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    } else {
157001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        const char *cmd[] = {
158001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                IP_PATH,
159001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "route",
160001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                action,
161001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                dest_str,
162001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "via",
163001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                gateway,
164001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "dev",
165001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                iface,
166001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "table",
167001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                tableIndex_str
168001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        };
169001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        ret = runCmd(ARRAY_SIZE(cmd), cmd);
170063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    }
171063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
172001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    if (ret) {
1735ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("ip route %s failed: %s route %s %s/%d via %s dev %s table %d", action,
174063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt                IP_PATH, action, dest, prefix, gateway, iface, tableIndex+BASE_TABLE_NUMBER);
175fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
176063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        cli->sendMsg(ResponseCode::OperationFailed, "ip route modification failed", true);
177fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
178fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
179063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
180063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    if (strcmp(action, ADD) == 0) {
181063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        mInterfaceRuleCount[tableIndex]++;
182063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    } else {
183063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        if (--mInterfaceRuleCount[tableIndex] < 1) {
184063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            mInterfaceRuleCount[tableIndex] = 0;
185063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            mInterfaceTable[tableIndex][0] = 0;
186063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        }
187063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    }
188c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    modifyRuleCount(tableIndex, action);
189063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    cli->sendMsg(ResponseCode::CommandOkay, "Route modified", false);
190fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
191fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
192fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
193c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltvoid SecondaryTableController::modifyRuleCount(int tableIndex, const char *action) {
194c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    if (strcmp(action, ADD) == 0) {
195c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        mInterfaceRuleCount[tableIndex]++;
196c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    } else {
197c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        if (--mInterfaceRuleCount[tableIndex] < 1) {
198c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt            mInterfaceRuleCount[tableIndex] = 0;
199c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt            mInterfaceTable[tableIndex][0] = 0;
200c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        }
201c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    }
202c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt}
203c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
204c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltint SecondaryTableController::verifyTableIndex(int tableIndex) {
205c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    if ((tableIndex < 0) ||
206c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt            (tableIndex >= INTERFACES_TRACKED) ||
207c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt            (mInterfaceTable[tableIndex][0] == 0)) {
208c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        return -1;
209c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    } else {
210c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        return 0;
211c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    }
212c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt}
213c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
214c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltconst char *SecondaryTableController::getVersion(const char *addr) {
215c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    if (strchr(addr, ':') != NULL) {
216c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        return "-6";
217c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    } else {
218c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        return "-4";
219c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    }
220c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt}
221c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
2222251c0fbcf24a9c8fd77b23851f60304087bab2bChad BrubakerIptablesTarget SecondaryTableController::getIptablesTarget(const char *addr) {
2232251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    if (strchr(addr, ':') != NULL) {
2242251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        return V6;
2252251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    } else {
2262251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        return V4;
2272251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    }
2282251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker}
2292251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
230fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::removeRoute(SocketClient *cli, char *iface, char *dest, int prefix,
231fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        char *gateway) {
232fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int tableIndex = findTableNumber(iface);
233fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (tableIndex == -1) {
2345ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface not found");
235fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
236fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
237fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
238fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
239fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
240063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    return modifyRoute(cli, DEL, iface, dest, prefix, gateway, tableIndex);
241fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
242fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
243c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltint SecondaryTableController::modifyFromRule(int tableIndex, const char *action,
244c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        const char *addr) {
245001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    char tableIndex_str[11];
246c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
247c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    if (verifyTableIndex(tableIndex)) {
248c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        return -1;
249c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    }
250001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
251001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex +
252001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            BASE_TABLE_NUMBER);
253001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    const char *cmd[] = {
254001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            IP_PATH,
255001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            getVersion(addr),
256001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "rule",
257001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            action,
258001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "from",
259001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            addr,
260001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "table",
261001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            tableIndex_str
262001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    };
263001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    if (runCmd(ARRAY_SIZE(cmd), cmd)) {
264c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        return -1;
265c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    }
266c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
267c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    modifyRuleCount(tableIndex, action);
268c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    return 0;
269c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt}
270c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
271c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltint SecondaryTableController::modifyLocalRoute(int tableIndex, const char *action,
272c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        const char *iface, const char *addr) {
273001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    char tableIndex_str[11];
274c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
275c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    if (verifyTableIndex(tableIndex)) {
276c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        return -1;
277c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    }
278c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
279c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt    modifyRuleCount(tableIndex, action); // some del's will fail as the iface is already gone.
280c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
281001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex +
282001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            BASE_TABLE_NUMBER);
283001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    const char *cmd[] = {
284001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            IP_PATH,
285001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "route",
286001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            action,
287001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            addr,
288001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "dev",
289001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            iface,
290001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "table",
291001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            tableIndex_str
292001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    };
293001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
294001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    return runCmd(ARRAY_SIZE(cmd), cmd);
295c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt}
2967a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubakerint SecondaryTableController::addFwmarkRule(const char *iface) {
2977a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker    return setFwmarkRule(iface, true);
2987a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker}
2997a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker
3007a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubakerint SecondaryTableController::removeFwmarkRule(const char *iface) {
3017a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker    return setFwmarkRule(iface, false);
3027a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker}
3037a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker
3047a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubakerint SecondaryTableController::setFwmarkRule(const char *iface, bool add) {
3057a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker    int tableIndex = findTableNumber(iface);
3067a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker    if (tableIndex == -1) {
3077a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        tableIndex = findTableNumber(""); // look for an empty slot
3087a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        if (tableIndex == -1) {
3097a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            ALOGE("Max number of NATed interfaces reached");
3107a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            errno = ENODEV;
3117a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            return -1;
3127a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        }
3137a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        strncpy(mInterfaceTable[tableIndex], iface, IFNAMSIZ);
3147a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        // Ensure null termination even if truncation happened
3157a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        mInterfaceTable[tableIndex][IFNAMSIZ] = 0;
3167a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker    }
3172251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    int mark = tableIndex + BASE_TABLE_NUMBER;
3182251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    char mark_str[11];
3192251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    int ret;
3202251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
3212251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    //fail fast if any rules already exist for this interface
3222251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    if (mUidMarkMap->anyRulesForMark(mark)) {
3232251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        errno = EBUSY;
3242251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        return -1;
3252251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    }
3262251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
3272251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    snprintf(mark_str, sizeof(mark_str), "%d", mark);
3282251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    //add the catch all route to the tun. Route rules will make sure the right packets hit the table
3292251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    const char *route_cmd[] = {
3302251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        IP_PATH,
3312251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "route",
3322251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        add ? "add" : "del",
3332251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "default",
3342251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "dev",
3352251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        iface,
3362251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "table",
3372251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        mark_str
3382251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    };
3392251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    ret = runCmd(ARRAY_SIZE(route_cmd), route_cmd);
3402251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
3412251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    const char *fwmark_cmd[] = {
3422251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        IP_PATH,
3432251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "rule",
3442251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        add ? "add" : "del",
3452349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        "prio",
3462349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        RULE_PRIO,
3472251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "fwmark",
3482251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        mark_str,
3492251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "table",
3502251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        mark_str
3512251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    };
3522251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    ret = runCmd(ARRAY_SIZE(fwmark_cmd), fwmark_cmd);
3532251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    if (ret) return ret;
3542251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
3552251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    //add rules for v6
3562251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    const char *route6_cmd[] = {
3572251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        IP_PATH,
3582251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "-6",
3592251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "route",
3602251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        add ? "add" : "del",
3612251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "default",
3622251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "dev",
3632251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        iface,
3642251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "table",
3652251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        mark_str
3662251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    };
3672251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    ret = runCmd(ARRAY_SIZE(route6_cmd), route6_cmd);
3682251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
3692251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    const char *fwmark6_cmd[] = {
3707a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        IP_PATH,
3712251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        "-6",
3727a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        "rule",
3737a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        add ? "add" : "del",
3742349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        "prio",
3752349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        RULE_PRIO,
3767a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        "fwmark",
3772251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        mark_str,
3787a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker        "table",
3792251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        mark_str
3807a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker    };
3812251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    ret = runCmd(ARRAY_SIZE(fwmark6_cmd), fwmark6_cmd);
3822251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
3832251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
3847a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker    if (ret) return ret;
3857a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker
3862251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    //create the route rule chain
3872251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    char chain_str[IFNAMSIZ + 18];
3882251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
3892251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    //code split due to ordering requirements
3902251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    if (add) {
3912251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        ret = execIptables(V4V6,
3922251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-t",
3932251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "mangle",
3942251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-N",
3952251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                chain_str,
3962251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                NULL);
3972251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        //set up the rule for sending premarked packets to the VPN chain
3982251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        //Insert these at the top of the chain so they trigger before any UID rules
3992251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        ret |= execIptables(V4V6,
4002251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-t",
4012251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "mangle",
4022251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-I",
4032251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                LOCAL_MANGLE_OUTPUT,
4042251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "3",
4052251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-m",
4062251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "mark",
4072251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "--mark",
4082251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                mark_str,
4092251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-g",
4102251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                chain_str,
4112251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                NULL);
4122251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        //add a rule to clear the mark in the VPN chain
4132251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        //packets marked with SO_MARK already have the iface's mark set but unless they match a
4142251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        //route they should hit the network instead of the VPN
4152251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        ret |= execIptables(V4V6,
4162251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-t",
4172251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "mangle",
4182251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-A",
4192251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                chain_str,
4202251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-j",
4212251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "MARK",
4222251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "--set-mark",
4232251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "0",
4242251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                NULL);
4252251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
426ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall        /* Best effort, because some kernels might not have the needed TCPMSS */
427ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall        execIptables(V4V6,
428ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "-t",
429ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "mangle",
430ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "-A",
431ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                LOCAL_MANGLE_POSTROUTING,
432ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "-p", "tcp", "-o", iface, "--tcp-flags", "SYN,RST", "SYN",
433ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "-j",
434ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "TCPMSS",
435ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "--clamp-mss-to-pmtu",
436ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                NULL);
437ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall
4382251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    } else {
4392251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        ret = execIptables(V4V6,
4402251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-t",
4412251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "mangle",
4422251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-D",
4432251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                LOCAL_MANGLE_OUTPUT,
4442251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-m",
4452251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "mark",
4462251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "--mark",
4472251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                mark_str,
4482251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-g",
4492251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                chain_str,
4502251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                NULL);
4512251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
4522251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        //clear and delete the chain
4532251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        ret |= execIptables(V4V6,
4542251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-t",
4552251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "mangle",
4562251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-F",
4572251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                chain_str,
4582251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                NULL);
4592251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
4602251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        ret |= execIptables(V4V6,
4612251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-t",
4622251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "mangle",
4632251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-X",
4642251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                chain_str,
4652251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                NULL);
466ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall
467ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall        /* Best effort, because some kernels might not have the needed TCPMSS */
468ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall        execIptables(V4V6,
469ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "-t",
470ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "mangle",
471ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "-D",
472ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                LOCAL_MANGLE_POSTROUTING,
473ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "-p", "tcp", "-o", iface, "--tcp-flags", "SYN,RST", "SYN",
474ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "-j",
475ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "TCPMSS",
476ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                "--clamp-mss-to-pmtu",
477ca5b4e8d0d8219273ecf0961ed6e8c47ab5d798aJP Abgrall                NULL);
4782251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    }
4792251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
4807a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker    //set up the needed source IP rewriting
4817a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker    //NOTE: Without ipv6 NAT in the kernel <3.7 only support V4 NAT
4822251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    ret = execIptables(V4,
4837a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            "-t",
4847a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            "nat",
4857a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            add ? "-A" : "-D",
4867a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            LOCAL_NAT_POSTROUTING,
4877a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            "-o",
4887a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            iface,
4897a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            "-m",
4907a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            "mark",
4917a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            "--mark",
4922251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            mark_str,
4937a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            "-j",
4947a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            "MASQUERADE",
4957a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker            NULL);
4967a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker
4972251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    if (ret) return ret;
4982251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
4992251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    //try and set up for ipv6. ipv6 nat came in the kernel only in 3.7, so this can fail
5002251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    ret = execIptables(V6,
5012251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-t",
5022251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "nat",
5032251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            add ? "-A" : "-D",
5042251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            LOCAL_NAT_POSTROUTING,
5052251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-o",
5062251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            iface,
5072251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-m",
5082251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "mark",
5092251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "--mark",
5102251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            mark_str,
5112251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-j",
5122251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "MASQUERADE",
5132251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            NULL);
5142251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    if (ret) {
5152251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        //Without V6 NAT we can't do V6 over VPNs.
5162251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        ret = execIptables(V6,
5172251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-t",
5182251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "filter",
5192251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                add ? "-A" : "-D",
5202251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                LOCAL_FILTER_OUTPUT,
5212251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-m",
5222251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "mark",
5232251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "--mark",
5242251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                mark_str,
5252251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "-j",
5262251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                "REJECT",
5272251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                NULL);
5282251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    }
5292251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    return ret;
5302251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
5312251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker}
5322251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
5332251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubakerint SecondaryTableController::addFwmarkRoute(const char* iface, const char *dest, int prefix) {
5342251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    return setFwmarkRoute(iface, dest, prefix, true);
5352251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker}
5362251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
5372251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubakerint SecondaryTableController::removeFwmarkRoute(const char* iface, const char *dest, int prefix) {
5382251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    return setFwmarkRoute(iface, dest, prefix, true);
5392251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker}
5402251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
5412251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubakerint SecondaryTableController::setFwmarkRoute(const char* iface, const char *dest, int prefix,
5422251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker                                             bool add) {
5432251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    int tableIndex = findTableNumber(iface);
5442251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    if (tableIndex == -1) {
5452251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        errno = EINVAL;
5462251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker        return -1;
5472251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    }
5482251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    int mark = tableIndex + BASE_TABLE_NUMBER;
5492251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    char mark_str[11] = {0};
5502251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    char chain_str[IFNAMSIZ + 18];
5512251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    char dest_str[44]; // enough to store an IPv6 address + 3 character bitmask
5522251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
5532251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    snprintf(mark_str, sizeof(mark_str), "%d", mark);
5542251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
5552251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    snprintf(dest_str, sizeof(dest_str), "%s/%d", dest, prefix);
5562251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    return execIptables(getIptablesTarget(dest),
5572251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-t",
5582251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "mangle",
5592251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            add ? "-A" : "-D",
5602251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            chain_str,
5612251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-d",
5622251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            dest_str,
5632251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-j",
5642251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "MARK",
5652251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "--set-mark",
5662251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            mark_str,
5672251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            NULL);
5687a6ce4bed8569745798bcc26f51d6f306ebdba94Chad Brubaker}
569c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
5708830b94cf4824e5a6c738d39d3015c8eec976352Chad Brubakerint SecondaryTableController::addUidRule(const char *iface, int uid_start, int uid_end) {
5718830b94cf4824e5a6c738d39d3015c8eec976352Chad Brubaker    return setUidRule(iface, uid_start, uid_end, true);
5729a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker}
5739a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker
5748830b94cf4824e5a6c738d39d3015c8eec976352Chad Brubakerint SecondaryTableController::removeUidRule(const char *iface, int uid_start, int uid_end) {
5758830b94cf4824e5a6c738d39d3015c8eec976352Chad Brubaker    return setUidRule(iface, uid_start, uid_end, false);
5769a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker}
5779a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker
5788830b94cf4824e5a6c738d39d3015c8eec976352Chad Brubakerint SecondaryTableController::setUidRule(const char *iface, int uid_start, int uid_end, bool add) {
5799a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker    int tableIndex = findTableNumber(iface);
5809a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker    if (tableIndex == -1) {
581d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker        errno = EINVAL;
5829a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker        return -1;
5839a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker    }
584d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker    int mark = tableIndex + BASE_TABLE_NUMBER;
585d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker    if (add) {
586d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker        if (!mUidMarkMap->add(uid_start, uid_end, mark)) {
587d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker            errno = EINVAL;
588d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker            return -1;
589d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker        }
590d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker    } else {
591d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker        if (!mUidMarkMap->remove(uid_start, uid_end, mark)) {
592d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker            errno = EINVAL;
593d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker            return -1;
594d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker        }
595d2617936acc15567fc5111bbdb4dde20845c3cbaChad Brubaker    }
5968830b94cf4824e5a6c738d39d3015c8eec976352Chad Brubaker    char uid_str[24] = {0};
5972251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    char chain_str[IFNAMSIZ + 18];
5988830b94cf4824e5a6c738d39d3015c8eec976352Chad Brubaker    snprintf(uid_str, sizeof(uid_str), "%d-%d", uid_start, uid_end);
5992251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker    snprintf(chain_str, sizeof(chain_str), LOCAL_MANGLE_IFACE_FORMAT, iface);
6009a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker    return execIptables(V4V6,
6019a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker            "-t",
6029a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker            "mangle",
6039a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker            add ? "-A" : "-D",
6049a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker            LOCAL_MANGLE_OUTPUT,
6059a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker            "-m",
6069a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker            "owner",
6079a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker            "--uid-owner",
6088830b94cf4824e5a6c738d39d3015c8eec976352Chad Brubaker            uid_str,
6092251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            "-g",
6102251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker            chain_str,
6119a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker            NULL);
6129a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker}
6139a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker
6144a946095dad15548ae399665be111be9cb1d9aa6Chad Brubakerint SecondaryTableController::addHostExemption(const char *host) {
6154a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker    return setHostExemption(host, true);
6164a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker}
6174a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker
6184a946095dad15548ae399665be111be9cb1d9aa6Chad Brubakerint SecondaryTableController::removeHostExemption(const char *host) {
6194a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker    return setHostExemption(host, false);
6204a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker}
6214a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker
6224a946095dad15548ae399665be111be9cb1d9aa6Chad Brubakerint SecondaryTableController::setHostExemption(const char *host, bool add) {
6234a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker    IptablesTarget target = !strcmp(getVersion(host), "-4") ? V4 : V6;
6244a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker    char protect_mark_str[11];
6254a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker    snprintf(protect_mark_str, sizeof(protect_mark_str), "%d", PROTECT_MARK);
6262349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker    int ret = execIptables(target,
6274a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            "-t",
6284a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            "mangle",
6294a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            add ? "-A" : "-D",
6304a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            LOCAL_MANGLE_EXEMPT,
6314a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            "-d",
6324a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            host,
6334a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            "-j",
6344a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            "MARK",
6354a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            "--set-mark",
6364a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            protect_mark_str,
6374a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker            NULL);
6382349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker    const char *cmd[] = {
6392349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        IP_PATH,
6402349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        getVersion(host),
6412349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        "rule",
6422349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        add ? "add" : "del",
6432349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        "prio",
6442349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        EXEMPT_PRIO,
6452349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        "to",
6462349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        host,
6472349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        "table",
6482349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker        "main"
6492349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker    };
6502349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker    ret |= runCmd(ARRAY_SIZE(cmd), cmd);
6512349aa60771baae85b1f5fc96e653ac2ef95034bChad Brubaker    return ret;
6524a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker}
6534a946095dad15548ae399665be111be9cb1d9aa6Chad Brubaker
654da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubakervoid SecondaryTableController::getUidMark(SocketClient *cli, int uid) {
655da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker    int mark = mUidMarkMap->getMark(uid);
656da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker    char mark_str[11];
657da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker    snprintf(mark_str, sizeof(mark_str), "%d", mark);
658da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker    cli->sendMsg(ResponseCode::GetMarkResult, mark_str, false);
659da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker}
660da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker
661da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubakervoid SecondaryTableController::getProtectMark(SocketClient *cli) {
662da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker    char protect_mark_str[11];
663da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker    snprintf(protect_mark_str, sizeof(protect_mark_str), "%d", PROTECT_MARK);
664da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker    cli->sendMsg(ResponseCode::GetMarkResult, protect_mark_str, false);
665da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker}
666da7df7c8f009f014486343cfbbaaae2a766f3a2bChad Brubaker
667001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchandint SecondaryTableController::runCmd(int argc, const char **argv) {
668fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int ret = 0;
669001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
670001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    ret = android_fork_execvp(argc, (char **)argv, NULL, false, false);
671fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return ret;
672fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
673