14a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall/*
24a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Copyright (C) 2011 The Android Open Source Project
34a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
44a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Licensed under the Apache License, Version 2.0 (the "License");
54a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * you may not use this file except in compliance with the License.
64a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * You may obtain a copy of the License at
74a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
84a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *      http://www.apache.org/licenses/LICENSE-2.0
94a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
104a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Unless required by applicable law or agreed to in writing, software
114a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * distributed under the License is distributed on an "AS IS" BASIS,
124a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * See the License for the specific language governing permissions and
144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * limitations under the License.
154a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */
164a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
17db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall// #define LOG_NDEBUG 0
18db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
19db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/*
20db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * The CommandListener, FrameworkListener don't allow for
21db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * multiple calls in parallel to reach the BandwidthController.
22db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * If they ever were to allow it, then netd/ would need some tweaking.
23db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */
24db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <errno.h>
264a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <fcntl.h>
27db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall#include <stdio.h>
288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <stdlib.h>
294a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <string.h>
304a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
314a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/socket.h>
324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/stat.h>
334a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/types.h>
344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/wait.h>
354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
364a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/netlink.h>
374a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/rtnetlink.h>
384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/pkt_sched.h>
394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#define LOG_TAG "BandwidthController"
414a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/log.h>
424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/properties.h>
4314150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand#include <logwrap/logwrap.h>
444a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "NetdConstants.h"
464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include "BandwidthController.h"
474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
48db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* Alphabetical */
4992009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall#define ALERT_IPT_TEMPLATE "%s %s -m quota2 ! --quota %lld --name %s"
50c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallconst char BandwidthController::ALERT_GLOBAL_NAME[] = "globalAlert";
518e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_INPUT = "bw_INPUT";
528e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_FORWARD = "bw_FORWARD";
538e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_OUTPUT = "bw_OUTPUT";
548e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_RAW_PREROUTING = "bw_raw_PREROUTING";
558e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_MANGLE_POSTROUTING = "bw_mangle_POSTROUTING";
56db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_CMD_ARGS = 32;
57db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_CMD_LEN = 1024;
58db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_IFACENAME_LEN = 64;
59db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_IPT_OUTPUT_LINE_LEN = 256;
60db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
614a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall/**
624a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Some comments about the rules:
634a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *  * Ordering
644a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    - when an interface is marked as costly it should be INSERTED into the INPUT/OUTPUT chains.
6529e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      E.g. "-I bw_INPUT -i rmnet0 --jump costly"
664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    - quota'd rules in the costly chain should be before penalty_box lookups.
6729e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *    - the qtaguid counting is done at the end of the bw_INPUT/bw_OUTPUT user chains.
684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * global quota vs per interface quota
704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *   - global quota for all costly interfaces uses a single costly chain:
714a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    . initial rules
72bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -N costly_shared
7329e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_INPUT -i iface0 --jump costly_shared
7429e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_OUTPUT -o iface0 --jump costly_shared
75bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -I costly_shared -m quota \! --quota 500000 \
76bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *          --jump REJECT --reject-with icmp-net-prohibited
77bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -A costly_shared --jump penalty_box
788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *
794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    . adding a new iface to this, E.g.:
8029e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_INPUT -i iface1 --jump costly_shared
8129e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_OUTPUT -o iface1 --jump costly_shared
824a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
834a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *   - quota per interface. This is achieve by having "costly" chains per quota.
844a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *     E.g. adding a new costly interface iface0 with its own quota:
854a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *      iptables -N costly_iface0
8629e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_INPUT -i iface0 --jump costly_iface0
8729e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_OUTPUT -o iface0 --jump costly_iface0
88bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -A costly_iface0 -m quota \! --quota 500000 \
89bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *          --jump REJECT --reject-with icmp-net-prohibited
90bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -A costly_iface0 --jump penalty_box
914a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
924a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * penalty_box handling:
934a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *  - only one penalty_box for all interfaces
944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *   E.g  Adding an app:
95bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *    iptables -A penalty_box -m owner --uid-owner app_3 \
96bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *        --jump REJECT --reject-with icmp-net-prohibited
974a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */
980031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char *BandwidthController::IPT_FLUSH_COMMANDS[] = {
990031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /*
1000031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Cleanup rules.
1010031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Should normally include costly_<iface>, but we rely on the way they are setup
1020031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * to allow coexistance.
10339f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall     */
1040031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F bw_INPUT",
1050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F bw_OUTPUT",
1060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F bw_FORWARD",
1070031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F penalty_box",
1080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F costly_shared",
109f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall
110f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall    "-t raw -F bw_raw_PREROUTING",
111f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall    "-t mangle -F bw_mangle_POSTROUTING",
1120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall};
1130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall/* The cleanup commands assume flushing has been done. */
1150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char *BandwidthController::IPT_CLEANUP_COMMANDS[] = {
1160031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-X penalty_box",
1170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-X costly_shared",
1180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall};
1194a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
120db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_SETUP_COMMANDS[] = {
121bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    "-N costly_shared",
1220dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    "-N penalty_box",
1230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall};
1240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
125db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_BASIC_ACCOUNTING_COMMANDS[] = {
1260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_INPUT -m owner --socket-exists", /* This is a tracking rule. */
1270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
1280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_OUTPUT -m owner --socket-exists", /* This is a tracking rule. */
1290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
130bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    "-A costly_shared --jump penalty_box",
131f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall
13292009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall    "-t raw -A bw_raw_PREROUTING -m owner --socket-exists", /* This is a tracking rule. */
13392009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall    "-t mangle -A bw_mangle_POSTROUTING -m owner --socket-exists", /* This is a tracking rule. */
1340dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall};
1354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
1364a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallBandwidthController::BandwidthController(void) {
1374a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
1384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
139ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrallint BandwidthController::runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling,
140ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall                                         IptFailureLog failureHandling) {
1410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
1428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1433fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("runIpxtablesCmd(cmd=%s)", cmd);
144ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    res |= runIptablesCmd(cmd, rejectHandling, IptIpV4, failureHandling);
145ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    res |= runIptablesCmd(cmd, rejectHandling, IptIpV6, failureHandling);
1460dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
1470dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
1480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
14926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::StrncpyAndCheck(char *buffer, const char *src, size_t buffSize) {
15026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
15126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    memset(buffer, '\0', buffSize);  // strncpy() is not filling leftover with '\0'
15226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    strncpy(buffer, src, buffSize);
15326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return buffer[buffSize - 1];
15426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall}
15526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
1568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesCmd(const char *cmd, IptRejectOp rejectHandling,
157ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall                                        IptIpVer iptVer, IptFailureLog failureHandling) {
15826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    char buffer[MAX_CMD_LEN];
1594a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    const char *argv[MAX_CMD_ARGS];
16026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    int argc = 0;
1614a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char *next = buffer;
1624a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char *tmp;
16311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    int res;
16414150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    int status = 0;
1654a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
1660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::string fullCmd = cmd;
16726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
16826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    if (rejectHandling == IptRejectAdd) {
1690dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        fullCmd += " --jump REJECT --reject-with";
17026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        switch (iptVer) {
17126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        case IptIpV4:
1728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            fullCmd += " icmp-net-prohibited";
1738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
17426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        case IptIpV6:
1758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            fullCmd += " icmp6-adm-prohibited";
1768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
1770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
1780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
1790dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
18011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    fullCmd.insert(0, " ");
18111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    fullCmd.insert(0, iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH);
1824a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
18314150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) {
18414150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand        ALOGE("iptables command too long");
18514150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand        return -1;
18614150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    }
18714150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand
18814150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    argc = 0;
18914150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    while ((tmp = strsep(&next, " "))) {
19014150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand        argv[argc++] = tmp;
19114150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand        if (argc >= MAX_CMD_ARGS) {
19214150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand            ALOGE("iptables argument overflow");
1934a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            return -1;
1944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall        }
19514150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    }
196fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
19714150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    argv[argc] = NULL;
19814150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    res = android_fork_execvp(argc, (char **)argv, &status, false,
19914150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand            failureHandling == IptFailShow);
200c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall    res = res || !WIFEXITED(status) || WEXITSTATUS(status);
201c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall    if (res && failureHandling == IptFailShow) {
202c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall      ALOGE("runIptablesCmd(): res=%d status=%d failed %s", res, status,
203c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall            fullCmd.c_str());
20411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    }
20511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    return res;
2064a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
2074a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint BandwidthController::setupIptablesHooks(void) {
2090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /* Some of the initialCommands are allowed to fail */
2110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*),
2120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_FLUSH_COMMANDS, RunCmdFailureOk);
2130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_CLEANUP_COMMANDS) / sizeof(char*),
2150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_CLEANUP_COMMANDS, RunCmdFailureOk);
2160031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_SETUP_COMMANDS) / sizeof(char*),
2180031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_SETUP_COMMANDS, RunCmdFailureBad);
2190031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
2210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
2220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2230031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint BandwidthController::enableBandwidthControl(bool force) {
224fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res;
2250031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    char value[PROPERTY_VALUE_MAX];
2260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!force) {
2280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            property_get("persist.bandwidth.enable", value, "1");
2290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            if (!strcmp(value, "0"))
2300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall                    return 0;
2310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
2328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
233db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /* Let's pretend we started from scratch ... */
2348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    sharedQuotaIfaces.clear();
2358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    quotaIfaces.clear();
2368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    naughtyAppUids.clear();
237db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    globalAlertBytes = 0;
238c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    globalAlertTetherCount = 0;
239db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    sharedQuotaBytes = sharedAlertBytes = 0;
240db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
2410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    res = runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*),
2420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_FLUSH_COMMANDS, RunCmdFailureOk);
243db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
2440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    res |= runCommands(sizeof(IPT_BASIC_ACCOUNTING_COMMANDS) / sizeof(char*),
245db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            IPT_BASIC_ACCOUNTING_COMMANDS, RunCmdFailureBad);
2468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
247fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return res;
2484a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
2504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::disableBandwidthControl(void) {
2520031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*),
2530031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_FLUSH_COMMANDS, RunCmdFailureOk);
254fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return 0;
2554a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
2564a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runCommands(int numCommands, const char *commands[],
2588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall                                     RunCmdErrHandling cmdErrHandling) {
259fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res = 0;
260ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    IptFailureLog failureLogging = IptFailShow;
261ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    if (cmdErrHandling == RunCmdFailureOk) {
262ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall        failureLogging = IptFailHide;
263ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    }
2643fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("runCommands(): %d commands", numCommands);
265fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) {
266ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall        res = runIpxtablesCmd(commands[cmdNum], IptRejectNoAdd, failureLogging);
2670031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        if (res && cmdErrHandling != RunCmdFailureOk)
268fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return res;
269fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
2700031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
271fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
272fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
2730dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallstd::string BandwidthController::makeIptablesNaughtyCmd(IptOp op, int uid) {
274fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    std::string res;
2758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *buff;
2768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    const char *opFlag;
277fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
278fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    switch (op) {
2798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpInsert:
2808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-I";
2818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
282109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall    case IptOpAppend:
283109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        opFlag = "-A";
284109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        break;
2858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpReplace:
2868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-R";
2878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
2888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    default:
2898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpDelete:
2908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-D";
2918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
292fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
2938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&buff, "%s penalty_box -m owner --uid-owner %d", opFlag, uid);
2948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res = buff;
2958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(buff);
296fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return res;
297fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
298fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
299fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::addNaughtyApps(int numUids, char *appUids[]) {
30026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpAdd);
301fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
302fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
303fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeNaughtyApps(int numUids, char *appUids[]) {
30426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpRemove);
305fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
306fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
30726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::maninpulateNaughtyApps(int numUids, char *appStrUids[], NaughtyAppOp appOp) {
308fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    char cmd[MAX_CMD_LEN];
309fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int uidNum;
31026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    const char *failLogTemplate;
31126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    IptOp op;
312fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int appUids[numUids];
31326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string naughtyCmd;
314b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall    std::list<int /*uid*/>::iterator it;
3158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
31626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    switch (appOp) {
31726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case NaughtyAppOpAdd:
3188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        op = IptOpInsert;
3198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        failLogTemplate = "Failed to add app uid %d to penalty box.";
3208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
32126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case NaughtyAppOpRemove:
3228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        op = IptOpDelete;
3238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        failLogTemplate = "Failed to delete app uid %d from penalty box.";
3248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
3250031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    default:
3260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("Unexpected app Op %d", appOp);
3270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
32826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
32926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
330fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (uidNum = 0; uidNum < numUids; uidNum++) {
331fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        appUids[uidNum] = atol(appStrUids[uidNum]);
332fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (appUids[uidNum] == 0) {
3335ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE(failLogTemplate, appUids[uidNum]);
334fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            goto fail_parse;
335fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
336fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
337fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
338fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (uidNum = 0; uidNum < numUids; uidNum++) {
339b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall        int uid = appUids[uidNum];
340b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall        for (it = naughtyAppUids.begin(); it != naughtyAppUids.end(); it++) {
341b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall            if (*it == uid)
342b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall                break;
343b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall        }
344b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall        bool found = (it != naughtyAppUids.end());
345b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall
346b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall        if (appOp == NaughtyAppOpRemove) {
347b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall            if (!found) {
348b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall                ALOGE("No such appUid %d to remove", uid);
349b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall                return -1;
350b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall            }
351b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall            naughtyAppUids.erase(it);
352b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall        } else {
353b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall            if (found) {
354b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall                ALOGE("appUid %d exists already", uid);
355b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall                return -1;
356b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall            }
357b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall            naughtyAppUids.push_front(uid);
358b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall        }
359b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall
360b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall        naughtyCmd = makeIptablesNaughtyCmd(op, uid);
36126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        if (runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd)) {
362b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall            ALOGE(failLogTemplate, uid);
363fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            goto fail_with_uidNum;
364fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
365fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
366fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return 0;
367fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
36826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_with_uidNum:
369fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    /* Try to remove the uid that failed in any case*/
37026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    naughtyCmd = makeIptablesNaughtyCmd(IptOpDelete, appUids[uidNum]);
37126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd);
37226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_parse:
37326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return -1;
3744a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
3754a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
37626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallstd::string BandwidthController::makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota) {
377fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    std::string res;
3788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *buff;
3798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    const char *opFlag;
3800dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
3813fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("makeIptablesQuotaCmd(%d, %lld)", op, quota);
3820dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
383fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    switch (op) {
3848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpInsert:
3858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-I";
3868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
387109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall    case IptOpAppend:
388109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        opFlag = "-A";
389109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        break;
3908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpReplace:
3918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-R";
3928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
3938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    default:
3948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpDelete:
3958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-D";
3968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
397fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
3988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
399bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    // The requried IP version specific --jump REJECT ... will be added later.
4008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&buff, "%s costly_%s -m quota2 ! --quota %lld --name %s", opFlag, costName, quota,
4018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall             costName);
4028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res = buff;
4038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(buff);
4040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
4050dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
4060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
40726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::prepCostlyIface(const char *ifn, QuotaType quotaType) {
4080dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char cmd[MAX_CMD_LEN];
4090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    int res = 0, res1, res2;
4108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int ruleInsertPos = 1;
4110dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::string costString;
4120dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    const char *costCString;
4130dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
4140dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /* The "-N costly" is created upfront, no need to handle it here. */
41526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    switch (quotaType) {
41626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaUnique:
417bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        costString = "costly_";
4180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costString += ifn;
4190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costCString = costString.c_str();
4200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        /*
4210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         * Flush the costly_<iface> is allowed to fail in case it didn't exist.
4220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         * Creating a new one is allowed to fail in case it existed.
4230031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         * This helps with netd restarts.
4240031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         */
4250031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        snprintf(cmd, sizeof(cmd), "-F %s", costCString);
426ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall        res1 = runIpxtablesCmd(cmd, IptRejectNoAdd, IptFailHide);
4270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        snprintf(cmd, sizeof(cmd), "-N %s", costCString);
428ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall        res2 = runIpxtablesCmd(cmd, IptRejectNoAdd, IptFailHide);
4290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        res = (res1 && res2) || (!res1 && !res2);
4300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4310dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        snprintf(cmd, sizeof(cmd), "-A %s -j penalty_box", costCString);
43226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
43326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
43426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaShared:
435bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        costCString = "costly_shared";
43626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
4370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    default:
4380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("Unexpected quotatype %d", quotaType);
4390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
4400dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
4410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
4428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (globalAlertBytes) {
4438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        /* The alert rule comes 1st */
4448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        ruleInsertPos = 2;
4458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
4460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_INPUT -i %s --jump %s", ifn, costCString);
448ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    runIpxtablesCmd(cmd, IptRejectNoAdd, IptFailHide);
4490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4500031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-I bw_INPUT %d -i %s --jump %s", ruleInsertPos, ifn, costCString);
45126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
4520031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4530031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_OUTPUT -o %s --jump %s", ifn, costCString);
454ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    runIpxtablesCmd(cmd, IptRejectNoAdd, IptFailHide);
4550031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4560031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-I bw_OUTPUT %d -o %s --jump %s", ruleInsertPos, ifn, costCString);
45726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
4580dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
4590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
4600dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
46126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::cleanupCostlyIface(const char *ifn, QuotaType quotaType) {
4620dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char cmd[MAX_CMD_LEN];
4630dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
4640dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::string costString;
4650dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    const char *costCString;
4660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
46726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    switch (quotaType) {
46826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaUnique:
469bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        costString = "costly_";
4700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costString += ifn;
4710dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costCString = costString.c_str();
47226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
47326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaShared:
474bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        costCString = "costly_shared";
47526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
4760031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    default:
4770031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("Unexpected quotatype %d", quotaType);
4780031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
4790dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
4800dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
4810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_INPUT -i %s --jump %s", ifn, costCString);
48226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
4830031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_OUTPUT -o %s --jump %s", ifn, costCString);
48426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
4850dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
486bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    /* The "-N costly_shared" is created upfront, no need to handle it here. */
48726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    if (quotaType == QuotaUnique) {
4880dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        snprintf(cmd, sizeof(cmd), "-F %s", costCString);
48926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
490a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall        snprintf(cmd, sizeof(cmd), "-X %s", costCString);
491a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
492fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
493fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return res;
494fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
4954a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
4960dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceSharedQuota(const char *iface, int64_t maxBytes) {
4974a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char cmd[MAX_CMD_LEN];
4984a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char ifn[MAX_IFACENAME_LEN];
499fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res = 0;
50026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string quotaCmd;
5018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    std::string ifaceName;
5028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    ;
503bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    const char *costName = "shared";
50426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::list<std::string>::iterator it;
5054a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!maxBytes) {
5078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        /* Don't talk about -1, deprecate it. */
5085ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
5098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
5108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
51126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
5125ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
51326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
51426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
51526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    ifaceName = ifn;
5164a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5174a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    if (maxBytes == -1) {
518fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        return removeInterfaceSharedQuota(ifn);
5194a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
5204a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5214a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    /* Insert ingress quota. */
5220dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) {
5230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (*it == ifaceName)
524fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            break;
5254a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
526fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
5270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == sharedQuotaIfaces.end()) {
52826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= prepCostlyIface(ifn, QuotaShared);
5290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (sharedQuotaIfaces.empty()) {
5300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes);
53126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall            res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
5324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            if (res) {
5335ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block                ALOGE("Failed set quota rule");
534fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall                goto fail;
5354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            }
536fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            sharedQuotaBytes = maxBytes;
537fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
5380dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        sharedQuotaIfaces.push_front(ifaceName);
539fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
540fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
541fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
542fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    if (maxBytes != sharedQuotaBytes) {
5438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res |= updateQuota(costName, maxBytes);
544fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (res) {
5455ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed update quota for %s", costName);
546fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            goto fail;
547fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
548fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        sharedQuotaBytes = maxBytes;
5494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
5504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return 0;
551fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
552fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    fail:
5534a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    /*
5544a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall     * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse
5554a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall     * rules in the kernel to see which ones need cleaning up.
556fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall     * For now callers needs to choose if they want to "ndc bandwidth enable"
557fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall     * which resets everything.
5584a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall     */
559fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    removeInterfaceSharedQuota(ifn);
5604a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return -1;
5614a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
5624a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall/* It will also cleanup any shared alerts */
564fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeInterfaceSharedQuota(const char *iface) {
5654a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char ifn[MAX_IFACENAME_LEN];
566fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res = 0;
56726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string ifaceName;
5680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::list<std::string>::iterator it;
569bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    const char *costName = "shared";
5704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
5725ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
57326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
57426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
5758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    ifaceName = ifn;
57626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
5770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) {
5780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (*it == ifaceName)
579fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            break;
5804a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
5810dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == sharedQuotaIfaces.end()) {
5825ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No such iface %s to delete", ifn);
583fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        return -1;
5844a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
585fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
58626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= cleanupCostlyIface(ifn, QuotaShared);
5870dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    sharedQuotaIfaces.erase(it);
588fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
5890dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (sharedQuotaIfaces.empty()) {
590fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        std::string quotaCmd;
591bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, sharedQuotaBytes);
59226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
5938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        sharedQuotaBytes = 0;
5948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (sharedAlertBytes) {
5958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            removeSharedAlert();
5968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            sharedAlertBytes = 0;
5978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
598fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
5994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return res;
6004a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
6010dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceQuota(const char *iface, int64_t maxBytes) {
6030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char ifn[MAX_IFACENAME_LEN];
6040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
60526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string ifaceName;
60626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    const char *costName;
60726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::list<QuotaInfo>::iterator it;
60826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string quotaCmd;
6090dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!maxBytes) {
6118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        /* Don't talk about -1, deprecate it. */
6125ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
6138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
6148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
6150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (maxBytes == -1) {
61626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return removeInterfaceQuota(iface);
6170dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
6180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
6205ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
62126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
62226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
62326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    ifaceName = ifn;
62426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    costName = iface;
62526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
6260dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /* Insert ingress quota. */
6270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
6288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == ifaceName)
6290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            break;
6300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
6310dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6320dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == quotaIfaces.end()) {
633109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        /* Preparing the iface adds a penalty_box check */
63426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= prepCostlyIface(ifn, QuotaUnique);
635109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall	/*
636109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall	 * The rejecting quota limit should go after the penalty box checks
637109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall	 * or else a naughty app could just eat up the quota.
638109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall	 * So we append here.
639109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall	 */
640109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        quotaCmd = makeIptablesQuotaCmd(IptOpAppend, costName, maxBytes);
64126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
6420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (res) {
6435ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed set quota rule");
6440dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            goto fail;
6450dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
6460dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        quotaIfaces.push_front(QuotaInfo(ifaceName, maxBytes, 0));
6480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    } else {
6508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res |= updateQuota(costName, maxBytes);
6510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (res) {
6525ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed update quota for %s", iface);
6530dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            goto fail;
6540dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
6558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        it->quota = maxBytes;
6560dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
6570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return 0;
6580dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    fail:
6600dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /*
6610dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse
6620dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * rules in the kernel to see which ones need cleaning up.
6630dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * For now callers needs to choose if they want to "ndc bandwidth enable"
6640dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * which resets everything.
6650dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     */
6660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    removeInterfaceSharedQuota(ifn);
6670dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return -1;
6680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
6690dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceSharedQuota(int64_t *bytes) {
6718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return getInterfaceQuota("shared", bytes);
6728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
6738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
6748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceQuota(const char *costName, int64_t *bytes) {
6758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    FILE *fp;
6768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *fname;
6778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int scanRes;
6788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
6798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&fname, "/proc/net/xt_quota/%s", costName);
6808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fp = fopen(fname, "r");
6818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(fname);
6828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!fp) {
6835ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Reading quota %s failed (%s)", costName, strerror(errno));
6848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
6858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
6868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    scanRes = fscanf(fp, "%lld", bytes);
6873fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("Read quota res=%d bytes=%lld", scanRes, *bytes);
6888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fclose(fp);
6898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return scanRes == 1 ? 0 : -1;
6908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
6918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
6920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::removeInterfaceQuota(const char *iface) {
6930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6940dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char ifn[MAX_IFACENAME_LEN];
6950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
69626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string ifaceName;
69726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    const char *costName;
69826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::list<QuotaInfo>::iterator it;
6990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
7015ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
70226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
70326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
70426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    ifaceName = ifn;
70526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    costName = iface;
7060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7070dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
7088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == ifaceName)
7090dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            break;
7100dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
7110dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7120dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == quotaIfaces.end()) {
7135ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No such iface %s to delete", ifn);
7140dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        return -1;
7150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
7160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7170dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /* This also removes the quota command of CostlyIface chain. */
71826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= cleanupCostlyIface(ifn, QuotaUnique);
7190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7200dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    quotaIfaces.erase(it);
7210dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7220dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
7230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
7248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::updateQuota(const char *quotaName, int64_t bytes) {
7268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    FILE *fp;
7278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *fname;
7288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&fname, "/proc/net/xt_quota/%s", quotaName);
7308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fp = fopen(fname, "w");
7318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(fname);
7328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!fp) {
7335ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Updating quota %s failed (%s)", quotaName, strerror(errno));
7348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
7358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
7368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fprintf(fp, "%lld\n", bytes);
7378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fclose(fp);
7388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return 0;
7398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
7408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesAlertCmd(IptOp op, const char *alertName, int64_t bytes) {
7428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
7438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    const char *opFlag;
7448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
7458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    switch (op) {
7478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpInsert:
7488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-I";
7498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
750109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall    case IptOpAppend:
751109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        opFlag = "-A";
752109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        break;
7538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpReplace:
7548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-R";
7558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
7568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    default:
7578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpDelete:
7588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-D";
7598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
7608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
7618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
76292009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_INPUT",
763c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich        bytes, alertName);
7648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
7658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertQuotaCmd);
76692009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_OUTPUT",
767c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich        bytes, alertName);
7688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
7698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertQuotaCmd);
7708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
7718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
7728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
773c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::runIptablesAlertFwdCmd(IptOp op, const char *alertName, int64_t bytes) {
774c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    int res = 0;
775c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *opFlag;
7768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
777c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
778c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    switch (op) {
779c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    case IptOpInsert:
780c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        opFlag = "-I";
781c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        break;
782109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall    case IptOpAppend:
783109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        opFlag = "-A";
784109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        break;
785c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    case IptOpReplace:
786c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        opFlag = "-R";
787c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        break;
788c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    default:
789c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    case IptOpDelete:
790c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        opFlag = "-D";
791c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        break;
792c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
793c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
79492009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_FORWARD",
795c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich        bytes, alertName);
796c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    res = runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
797c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    free(alertQuotaCmd);
798c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    return res;
799c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall}
800c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
801c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlert(int64_t bytes) {
802c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
8038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
8048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
8065ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
8078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (globalAlertBytes) {
8108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res = updateQuota(alertName, bytes);
8118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    } else {
8128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res = runIptablesAlertCmd(IptOpInsert, alertName, bytes);
813c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        if (globalAlertTetherCount) {
8143fb42e026ffebab2c8f282e42501040121e32d83Steve Block            ALOGV("setGlobalAlert for %d tether", globalAlertTetherCount);
815c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            res |= runIptablesAlertFwdCmd(IptOpInsert, alertName, bytes);
816c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        }
8178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    globalAlertBytes = bytes;
8198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
8208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
8218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
822c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlertInForwardChain(void) {
823c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
824c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    int res = 0;
825c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
826c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    globalAlertTetherCount++;
8273fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("setGlobalAlertInForwardChain(): %d tether", globalAlertTetherCount);
828c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
829c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /*
830c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is no globalAlert active we are done.
831c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is an active globalAlert but this is not the 1st
832c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * tether, we are also done.
833c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     */
834c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!globalAlertBytes || globalAlertTetherCount != 1) {
835c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return 0;
836c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
837c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
838c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /* We only add the rule if this was the 1st tether added. */
839c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    res = runIptablesAlertFwdCmd(IptOpInsert, alertName, globalAlertBytes);
840c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    return res;
841c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall}
842c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
8438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeGlobalAlert(void) {
8448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
845c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
8468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
8478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!globalAlertBytes) {
8495ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set");
8508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res = runIptablesAlertCmd(IptOpDelete, alertName, globalAlertBytes);
853c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (globalAlertTetherCount) {
854c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        res |= runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes);
855c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
8568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    globalAlertBytes = 0;
8578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
8588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
8598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
860c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::removeGlobalAlertInForwardChain(void) {
861c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    int res = 0;
862c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
863c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
864c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!globalAlertTetherCount) {
8655ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set");
866c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return -1;
867c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
868c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
869c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    globalAlertTetherCount--;
870c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /*
871c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is no globalAlert active we are done.
872c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is an active globalAlert but there are more
873c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * tethers, we are also done.
874c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     */
875c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!globalAlertBytes || globalAlertTetherCount >= 1) {
876c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return 0;
877c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
878c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
879c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /* We only detete the rule if this was the last tether removed. */
880c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    res = runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes);
881c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    return res;
882c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall}
883c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
8848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setSharedAlert(int64_t bytes) {
8858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!sharedQuotaBytes) {
8865ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Need to have a prior shared quota set to set an alert");
8878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
8905ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
8918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return setCostlyAlert("shared", bytes, &sharedAlertBytes);
8948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
8958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeSharedAlert(void) {
8978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return removeCostlyAlert("shared", &sharedAlertBytes);
8988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
8998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setInterfaceAlert(const char *iface, int64_t bytes) {
9018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    std::list<QuotaInfo>::iterator it;
9028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
9045ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
9058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
9088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == iface)
9098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
9108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (it == quotaIfaces.end()) {
9135ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Need to have a prior interface quota set to set an alert");
9148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return setCostlyAlert(iface, bytes, &it->alert);
9188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
9198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeInterfaceAlert(const char *iface) {
9218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    std::list<QuotaInfo>::iterator it;
9228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
9248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == iface)
9258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
9268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (it == quotaIfaces.end()) {
9295ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set for interface %s", iface);
9308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return removeCostlyAlert(iface, &it->alert);
9348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
9358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes) {
9378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
938109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall    char *chainName;
9398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
9408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertName;
9418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
9435ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
9448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&alertName, "%sAlert", costName);
9478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (*alertBytes) {
9488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res = updateQuota(alertName, *alertBytes);
9498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    } else {
950109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        asprintf(&chainName, "costly_%s", costName);
951109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-A", chainName, bytes, alertName);
9528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
9538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        free(alertQuotaCmd);
954109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        free(chainName);
9558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    *alertBytes = bytes;
9578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertName);
9588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
9598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
9608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeCostlyAlert(const char *costName, int64_t *alertBytes) {
9628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
9638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *chainName;
9648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertName;
9658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
9668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&alertName, "%sAlert", costName);
9688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!*alertBytes) {
9695ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set for %s alert", costName);
9708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&chainName, "costly_%s", costName);
97492009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-D", chainName, *alertBytes, alertName);
9758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
9768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertQuotaCmd);
9778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(chainName);
9788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    *alertBytes = 0;
9808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertName);
9818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
9828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
983db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
984db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/*
985db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Parse the ptks and bytes out of:
9860031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Chain FORWARD (policy RETURN 0 packets, 0 bytes)
987db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall *     pkts      bytes target     prot opt in     out     source               destination
9880031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *        0        0 RETURN     all  --  rmnet0 wlan0   0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
989db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall *        0        0 DROP       all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0            state INVALID
9900031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *        0        0 RETURN     all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0
991db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall *
992db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */
993a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrallint BandwidthController::parseForwardChainStats(TetherStats &stats, FILE *fp,
994a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall                                                std::string &extraProcessingInfo) {
995db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    int res;
996db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN];
997db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char iface0[MAX_IPT_OUTPUT_LINE_LEN];
998db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char iface1[MAX_IPT_OUTPUT_LINE_LEN];
999db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char rest[MAX_IPT_OUTPUT_LINE_LEN];
1000db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1001db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char *buffPtr;
1002db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    int64_t packets, bytes;
1003db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1004db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) {
1005db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        /* Clean up, so a failed parse can still print info */
1006db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        iface0[0] = iface1[0] = rest[0] = packets = bytes = 0;
10070031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        res = sscanf(buffPtr, "%lld %lld RETURN all -- %s %s 0.%s",
1008db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall                &packets, &bytes, iface0, iface1, rest);
10093fb42e026ffebab2c8f282e42501040121e32d83Steve Block        ALOGV("parse res=%d iface0=<%s> iface1=<%s> pkts=%lld bytes=%lld rest=<%s> orig line=<%s>", res,
1010db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall             iface0, iface1, packets, bytes, rest, buffPtr);
1011a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall        extraProcessingInfo += buffPtr;
1012a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall
1013db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        if (res != 5) {
1014db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            continue;
1015db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        }
1016db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        if ((stats.ifaceIn == iface0) && (stats.ifaceOut == iface1)) {
10173fb42e026ffebab2c8f282e42501040121e32d83Steve Block            ALOGV("iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets);
1018db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            stats.rxPackets = packets;
1019db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            stats.rxBytes = bytes;
1020db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        } else if ((stats.ifaceOut == iface0) && (stats.ifaceIn == iface1)) {
10213fb42e026ffebab2c8f282e42501040121e32d83Steve Block            ALOGV("iface_in=%s iface_out=%s tx_bytes=%lld tx_packets=%lld ", iface1, iface0, bytes, packets);
1022db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            stats.txPackets = packets;
1023db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            stats.txBytes = bytes;
1024db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        }
1025db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1026db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /* Failure if rx or tx was not found */
1027db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    return (stats.rxBytes == -1 || stats.txBytes == -1) ? -1 : 0;
1028db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
1029db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1030db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1031db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallchar *BandwidthController::TetherStats::getStatsLine(void) {
1032db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char *msg;
1033db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    asprintf(&msg, "%s %s %lld %lld %lld %lld", ifaceIn.c_str(), ifaceOut.c_str(),
1034db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            rxBytes, rxPackets, txBytes, txPackets);
1035db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    return msg;
1036db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
1037db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1038a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrallint BandwidthController::getTetherStats(TetherStats &stats, std::string &extraProcessingInfo) {
1039db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    int res;
1040db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    std::string fullCmd;
1041db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    FILE *iptOutput;
1042db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    const char *cmd;
1043db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1044db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (stats.rxBytes != -1 || stats.txBytes != -1) {
10455ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Unexpected input stats. Byte counts should be -1.");
1046db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return -1;
1047db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1048db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1049db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /*
1050db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * Why not use some kind of lib to talk to iptables?
1051db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * Because the only libs are libiptc and libip6tc in iptables, and they are
1052db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * not easy to use. They require the known iptables match modules to be
1053db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * preloaded/linked, and require apparently a lot of wrapper code to get
1054db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * the wanted info.
1055db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     */
1056db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    fullCmd = IPTABLES_PATH;
10570031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    fullCmd += " -nvx -L natctrl_FORWARD";
1058db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    iptOutput = popen(fullCmd.c_str(), "r");
1059db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!iptOutput) {
10605ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno));
1061a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall            extraProcessingInfo += "Failed to run iptables.";
1062db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return -1;
1063db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1064a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall    res = parseForwardChainStats(stats, iptOutput, extraProcessingInfo);
1065db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    pclose(iptOutput);
1066db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1067db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /* Currently NatController doesn't do ipv6 tethering, so we are done. */
1068db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    return res;
1069db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
1070