BandwidthController.cpp revision 0031cead820149e2fe3ccb3cc2fe05758a3cb5c2
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>
434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
44c4bbfa247dbe4dda17e28694d49afd3ec0b06badGlenn Kastenextern "C" int logwrap(int argc, const char **argv);
459e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrallextern "C" int system_nosh(const char *command);
464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "NetdConstants.h"
484a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include "BandwidthController.h"
494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
50db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* Alphabetical */
51c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich#define ALERT_IPT_TEMPLATE "%s %s %s -m quota2 ! --quota %lld --name %s"
52db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::ALERT_RULE_POS_IN_COSTLY_CHAIN = 4;
53c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallconst char BandwidthController::ALERT_GLOBAL_NAME[] = "globalAlert";
54db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_CMD_ARGS = 32;
55db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_CMD_LEN = 1024;
56db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_IFACENAME_LEN = 64;
57db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_IPT_OUTPUT_LINE_LEN = 256;
58db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
5911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrallbool BandwidthController::useLogwrapCall = false;
604a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP 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.
650031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *      E.g. "-I INPUT -i rmnet0 --jump costly"
664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    - quota'd rules in the costly chain should be before penalty_box lookups.
674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * global quota vs per interface quota
694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *   - global quota for all costly interfaces uses a single costly chain:
704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    . initial rules
71bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -N costly_shared
720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *      iptables -I INPUT -i iface0 --jump costly_shared
730031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *      iptables -I OUTPUT -o iface0 --jump costly_shared
74bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -I costly_shared -m quota \! --quota 500000 \
75bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *          --jump REJECT --reject-with icmp-net-prohibited
76bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -A costly_shared --jump penalty_box
77bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -A costly_shared -m owner --socket-exists
788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *
794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    . adding a new iface to this, E.g.:
800031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *      iptables -I INPUT -i iface1 --jump costly_shared
810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *      iptables -I 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
860031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *      iptables -I INPUT -i iface0 --jump costly_iface0
870031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *      iptables -I 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 *      iptables -A costly_iface0 -m owner --socket-exists
924a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
934a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * penalty_box handling:
944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *  - only one penalty_box for all interfaces
954a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *   E.g  Adding an app:
96bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *    iptables -A penalty_box -m owner --uid-owner app_3 \
97bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *        --jump REJECT --reject-with icmp-net-prohibited
984a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */
990031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char *BandwidthController::IPT_FLUSH_COMMANDS[] = {
1000031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /*
1010031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Cleanup rules.
1020031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Should normally include costly_<iface>, but we rely on the way they are setup
1030031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * to allow coexistance.
10439f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall     */
1050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F bw_INPUT",
1060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F bw_OUTPUT",
1070031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F bw_FORWARD",
1080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F penalty_box",
1090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F costly_shared",
1100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall};
1110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall/* The cleanup commands assume flushing has been done. */
1130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char *BandwidthController::IPT_CLEANUP_COMMANDS[] = {
1140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /* Delete hooks to custom chains. */
1150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-D INPUT -j bw_INPUT",
1160031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-D OUTPUT -j bw_OUTPUT",
1170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-D FORWARD -j bw_FORWARD",
1180031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-X bw_INPUT",
1190031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-X bw_OUTPUT",
1200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-X bw_FORWARD",
1210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-X penalty_box",
1220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-X costly_shared",
1230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall};
1244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
125db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_SETUP_COMMANDS[] = {
1260dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /* Created needed chains. */
1270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-N bw_INPUT",
1280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A INPUT -j bw_INPUT",
1290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-N bw_OUTPUT",
1310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A OUTPUT -j bw_OUTPUT",
1320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-N bw_FORWARD",
1340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-I FORWARD -j bw_FORWARD",
1350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
136bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    "-N costly_shared",
1370dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    "-N penalty_box",
1380dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall};
1390dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
140db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_BASIC_ACCOUNTING_COMMANDS[] = {
1410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_INPUT -i lo --jump RETURN",
1420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_INPUT -m owner --socket-exists", /* This is a tracking rule. */
1430dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
1440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_OUTPUT -o lo --jump RETURN",
1450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_OUTPUT -m owner --socket-exists", /* This is a tracking rule. */
1460dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
147bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    "-A costly_shared --jump penalty_box",
148bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    "-A costly_shared -m owner --socket-exists", /* This is a tracking rule. */
1490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall};
1504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
1514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallBandwidthController::BandwidthController(void) {
1524a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char value[PROPERTY_VALUE_MAX];
1534a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
15411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    property_get("persist.bandwidth.uselogwrap", value, "0");
15511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    useLogwrapCall = !strcmp(value, "1");
1564a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
1574a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
15826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling) {
1590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
1608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1613fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("runIpxtablesCmd(cmd=%s)", cmd);
16226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= runIptablesCmd(cmd, rejectHandling, IptIpV4);
16326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= runIptablesCmd(cmd, rejectHandling, IptIpV6);
1640dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
1650dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
1660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
16726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::StrncpyAndCheck(char *buffer, const char *src, size_t buffSize) {
16826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
16926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    memset(buffer, '\0', buffSize);  // strncpy() is not filling leftover with '\0'
17026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    strncpy(buffer, src, buffSize);
17126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return buffer[buffSize - 1];
17226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall}
17326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
1748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesCmd(const char *cmd, IptRejectOp rejectHandling,
1758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall                                        IptIpVer iptVer) {
17626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    char buffer[MAX_CMD_LEN];
1774a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    const char *argv[MAX_CMD_ARGS];
17826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    int argc = 0;
1794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char *next = buffer;
1804a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char *tmp;
18111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    int res;
1824a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
1830dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::string fullCmd = cmd;
18426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
18526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    if (rejectHandling == IptRejectAdd) {
1860dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        fullCmd += " --jump REJECT --reject-with";
18726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        switch (iptVer) {
18826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        case IptIpV4:
1898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            fullCmd += " icmp-net-prohibited";
1908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
19126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        case IptIpV6:
1928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            fullCmd += " icmp6-adm-prohibited";
1938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
1940dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
1950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
1960dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
19711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    fullCmd.insert(0, " ");
19811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    fullCmd.insert(0, iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH);
1994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
20011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    if (!useLogwrapCall) {
2019e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        res = system_nosh(fullCmd.c_str());
20211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    } else {
20311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) {
2045ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("iptables command too long");
2054a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            return -1;
2064a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall        }
207fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
20811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        argc = 0;
20911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        while ((tmp = strsep(&next, " "))) {
21011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall            argv[argc++] = tmp;
21111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall            if (argc >= MAX_CMD_ARGS) {
2125ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block                ALOGE("iptables argument overflow");
21311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall                return -1;
21411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall            }
21511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        }
21611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall
21711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        argv[argc] = NULL;
218c4bbfa247dbe4dda17e28694d49afd3ec0b06badGlenn Kasten        res = logwrap(argc, argv);
21911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    }
22011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    if (res) {
2215ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("runIptablesCmd(): failed %s res=%d", fullCmd.c_str(), res);
22211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    }
22311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    return res;
2244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
2254a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint BandwidthController::setupIptablesHooks(void) {
2270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /* Some of the initialCommands are allowed to fail */
2290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*),
2300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_FLUSH_COMMANDS, RunCmdFailureOk);
2310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_CLEANUP_COMMANDS) / sizeof(char*),
2330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_CLEANUP_COMMANDS, RunCmdFailureOk);
2340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_SETUP_COMMANDS) / sizeof(char*),
2360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_SETUP_COMMANDS, RunCmdFailureBad);
2370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
2390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2400031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
2410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint BandwidthController::enableBandwidthControl(bool force) {
243fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res;
2440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    char value[PROPERTY_VALUE_MAX];
2450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!force) {
2470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            property_get("persist.bandwidth.enable", value, "1");
2480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            if (!strcmp(value, "0"))
2490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall                    return 0;
2500031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
2518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
252db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /* Let's pretend we started from scratch ... */
2538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    sharedQuotaIfaces.clear();
2548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    quotaIfaces.clear();
2558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    naughtyAppUids.clear();
256db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    globalAlertBytes = 0;
257c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    globalAlertTetherCount = 0;
258db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    sharedQuotaBytes = sharedAlertBytes = 0;
259db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
2600031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    res = runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*),
2610031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_FLUSH_COMMANDS, RunCmdFailureOk);
262db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
2630031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    res |= runCommands(sizeof(IPT_BASIC_ACCOUNTING_COMMANDS) / sizeof(char*),
264db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            IPT_BASIC_ACCOUNTING_COMMANDS, RunCmdFailureBad);
2658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
266fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return res;
2674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
2694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::disableBandwidthControl(void) {
2710031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*),
2720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_FLUSH_COMMANDS, RunCmdFailureOk);
273fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return 0;
2744a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
2754a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runCommands(int numCommands, const char *commands[],
2778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall                                     RunCmdErrHandling cmdErrHandling) {
278fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res = 0;
2793fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("runCommands(): %d commands", numCommands);
280fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) {
28126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res = runIpxtablesCmd(commands[cmdNum], IptRejectNoAdd);
2820031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        if (res && cmdErrHandling != RunCmdFailureOk)
283fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return res;
284fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
2850031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
286fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
287fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
2880dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallstd::string BandwidthController::makeIptablesNaughtyCmd(IptOp op, int uid) {
289fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    std::string res;
2908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *buff;
2918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    const char *opFlag;
292fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
293fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    switch (op) {
2948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpInsert:
2958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-I";
2968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
2978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpReplace:
2988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-R";
2998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
3008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    default:
3018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpDelete:
3028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-D";
3038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
304fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
3058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&buff, "%s penalty_box -m owner --uid-owner %d", opFlag, uid);
3068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res = buff;
3078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(buff);
308fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return res;
309fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
310fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
311fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::addNaughtyApps(int numUids, char *appUids[]) {
31226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpAdd);
313fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
314fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
315fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeNaughtyApps(int numUids, char *appUids[]) {
31626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpRemove);
317fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
318fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
31926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::maninpulateNaughtyApps(int numUids, char *appStrUids[], NaughtyAppOp appOp) {
320fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    char cmd[MAX_CMD_LEN];
321fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int uidNum;
32226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    const char *failLogTemplate;
32326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    IptOp op;
324fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int appUids[numUids];
32526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string naughtyCmd;
3268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
32726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    switch (appOp) {
32826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case NaughtyAppOpAdd:
3298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        op = IptOpInsert;
3308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        failLogTemplate = "Failed to add app uid %d to penalty box.";
3318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
33226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case NaughtyAppOpRemove:
3338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        op = IptOpDelete;
3348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        failLogTemplate = "Failed to delete app uid %d from penalty box.";
3358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
3360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    default:
3370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("Unexpected app Op %d", appOp);
3380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
33926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
34026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
341fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (uidNum = 0; uidNum < numUids; uidNum++) {
342fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        appUids[uidNum] = atol(appStrUids[uidNum]);
343fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (appUids[uidNum] == 0) {
3445ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE(failLogTemplate, appUids[uidNum]);
345fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            goto fail_parse;
346fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
347fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
348fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
349fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (uidNum = 0; uidNum < numUids; uidNum++) {
35026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        naughtyCmd = makeIptablesNaughtyCmd(op, appUids[uidNum]);
35126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        if (runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd)) {
3525ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE(failLogTemplate, appUids[uidNum]);
353fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            goto fail_with_uidNum;
354fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
355fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
356fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return 0;
357fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
35826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_with_uidNum:
359fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    /* Try to remove the uid that failed in any case*/
36026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    naughtyCmd = makeIptablesNaughtyCmd(IptOpDelete, appUids[uidNum]);
36126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd);
36226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_parse:
36326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return -1;
3644a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
3654a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
36626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallstd::string BandwidthController::makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota) {
367fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    std::string res;
3688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *buff;
3698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    const char *opFlag;
3700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
3713fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("makeIptablesQuotaCmd(%d, %lld)", op, quota);
3720dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
373fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    switch (op) {
3748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpInsert:
3758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-I";
3768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
3778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpReplace:
3788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-R";
3798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
3808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    default:
3818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpDelete:
3828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-D";
3838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
384fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
3858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
386bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    // The requried IP version specific --jump REJECT ... will be added later.
3878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&buff, "%s costly_%s -m quota2 ! --quota %lld --name %s", opFlag, costName, quota,
3888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall             costName);
3898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res = buff;
3908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(buff);
3910dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
3920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
3930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
39426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::prepCostlyIface(const char *ifn, QuotaType quotaType) {
3950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char cmd[MAX_CMD_LEN];
3960031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    int res = 0, res1, res2;
3978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int ruleInsertPos = 1;
3980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::string costString;
3990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    const char *costCString;
4000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
4010dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /* The "-N costly" is created upfront, no need to handle it here. */
40226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    switch (quotaType) {
40326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaUnique:
404bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        costString = "costly_";
4050dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costString += ifn;
4060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costCString = costString.c_str();
4070031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        /*
4080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         * Flush the costly_<iface> is allowed to fail in case it didn't exist.
4090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         * Creating a new one is allowed to fail in case it existed.
4100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         * This helps with netd restarts.
4110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         */
4120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        snprintf(cmd, sizeof(cmd), "-F %s", costCString);
4130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        res1 = runIpxtablesCmd(cmd, IptRejectNoAdd);
4140dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        snprintf(cmd, sizeof(cmd), "-N %s", costCString);
4150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        res2 = runIpxtablesCmd(cmd, IptRejectNoAdd);
4160031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        res = (res1 && res2) || (!res1 && !res2);
4170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        snprintf(cmd, sizeof(cmd), "-A %s -j penalty_box", costCString);
41926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
4200dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        snprintf(cmd, sizeof(cmd), "-A %s -m owner --socket-exists", costCString);
42126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
42226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
42326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaShared:
424bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        costCString = "costly_shared";
42526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
4260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    default:
4270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("Unexpected quotatype %d", quotaType);
4280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
4290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
4300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
4318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (globalAlertBytes) {
4328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        /* The alert rule comes 1st */
4338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        ruleInsertPos = 2;
4348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
4350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_INPUT -i %s --jump %s", ifn, costCString);
4370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runIpxtablesCmd(cmd, IptRejectNoAdd);
4380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-I bw_INPUT %d -i %s --jump %s", ruleInsertPos, ifn, costCString);
44026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
4410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_OUTPUT -o %s --jump %s", ifn, costCString);
4430031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runIpxtablesCmd(cmd, IptRejectNoAdd);
4440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-I bw_OUTPUT %d -o %s --jump %s", ruleInsertPos, ifn, costCString);
44626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
4470dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
4480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
4490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
45026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::cleanupCostlyIface(const char *ifn, QuotaType quotaType) {
4510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char cmd[MAX_CMD_LEN];
4520dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
4530dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::string costString;
4540dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    const char *costCString;
4550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
45626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    switch (quotaType) {
45726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaUnique:
458bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        costString = "costly_";
4590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costString += ifn;
4600dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costCString = costString.c_str();
46126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
46226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaShared:
463bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        costCString = "costly_shared";
46426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
4650031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    default:
4660031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("Unexpected quotatype %d", quotaType);
4670031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
4680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
4690dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
4700031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_INPUT -i %s --jump %s", ifn, costCString);
47126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
4720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_OUTPUT -o %s --jump %s", ifn, costCString);
47326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
4740dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
475bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    /* The "-N costly_shared" is created upfront, no need to handle it here. */
47626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    if (quotaType == QuotaUnique) {
4770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        snprintf(cmd, sizeof(cmd), "-F %s", costCString);
47826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
479a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall        snprintf(cmd, sizeof(cmd), "-X %s", costCString);
480a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall        res |= runIpxtablesCmd(cmd, IptRejectNoAdd);
481fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
482fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return res;
483fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
4844a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
4850dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceSharedQuota(const char *iface, int64_t maxBytes) {
4864a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char cmd[MAX_CMD_LEN];
4874a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char ifn[MAX_IFACENAME_LEN];
488fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res = 0;
48926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string quotaCmd;
4908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    std::string ifaceName;
4918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    ;
492bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    const char *costName = "shared";
49326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::list<std::string>::iterator it;
4944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
4958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!maxBytes) {
4968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        /* Don't talk about -1, deprecate it. */
4975ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
4988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
4998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
50026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
5015ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
50226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
50326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
50426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    ifaceName = ifn;
5054a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5064a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    if (maxBytes == -1) {
507fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        return removeInterfaceSharedQuota(ifn);
5084a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
5094a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5104a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    /* Insert ingress quota. */
5110dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) {
5120dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (*it == ifaceName)
513fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            break;
5144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
515fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
5160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == sharedQuotaIfaces.end()) {
51726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= prepCostlyIface(ifn, QuotaShared);
5180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (sharedQuotaIfaces.empty()) {
5190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes);
52026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall            res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
5214a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            if (res) {
5225ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block                ALOGE("Failed set quota rule");
523fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall                goto fail;
5244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            }
525fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            sharedQuotaBytes = maxBytes;
526fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
5270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        sharedQuotaIfaces.push_front(ifaceName);
528fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
529fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
530fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
531fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    if (maxBytes != sharedQuotaBytes) {
5328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res |= updateQuota(costName, maxBytes);
533fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (res) {
5345ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed update quota for %s", costName);
535fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            goto fail;
536fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
537fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        sharedQuotaBytes = maxBytes;
5384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
5394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return 0;
540fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
541fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    fail:
5424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    /*
5434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall     * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse
5444a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall     * rules in the kernel to see which ones need cleaning up.
545fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall     * For now callers needs to choose if they want to "ndc bandwidth enable"
546fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall     * which resets everything.
5474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall     */
548fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    removeInterfaceSharedQuota(ifn);
5494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return -1;
5504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
5514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall/* It will also cleanup any shared alerts */
553fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeInterfaceSharedQuota(const char *iface) {
5544a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char ifn[MAX_IFACENAME_LEN];
555fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res = 0;
55626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string ifaceName;
5570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::list<std::string>::iterator it;
558bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    const char *costName = "shared";
5594a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
5615ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
56226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
56326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
5648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    ifaceName = ifn;
56526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
5660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) {
5670dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (*it == ifaceName)
568fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            break;
5694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
5700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == sharedQuotaIfaces.end()) {
5715ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No such iface %s to delete", ifn);
572fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        return -1;
5734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
574fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
57526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= cleanupCostlyIface(ifn, QuotaShared);
5760dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    sharedQuotaIfaces.erase(it);
577fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
5780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (sharedQuotaIfaces.empty()) {
579fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        std::string quotaCmd;
580bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, sharedQuotaBytes);
58126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
5828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        sharedQuotaBytes = 0;
5838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (sharedAlertBytes) {
5848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            removeSharedAlert();
5858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            sharedAlertBytes = 0;
5868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
587fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
5884a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return res;
5894a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
5900dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
5910dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceQuota(const char *iface, int64_t maxBytes) {
5920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char ifn[MAX_IFACENAME_LEN];
5930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
59426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string ifaceName;
59526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    const char *costName;
59626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::list<QuotaInfo>::iterator it;
59726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string quotaCmd;
5980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
5998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!maxBytes) {
6008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        /* Don't talk about -1, deprecate it. */
6015ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
6028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
6038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
6040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (maxBytes == -1) {
60526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return removeInterfaceQuota(iface);
6060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
6070dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
6095ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
61026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
61126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
61226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    ifaceName = ifn;
61326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    costName = iface;
61426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
6150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /* Insert ingress quota. */
6160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
6178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == ifaceName)
6180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            break;
6190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
6200dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6210dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == quotaIfaces.end()) {
62226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= prepCostlyIface(ifn, QuotaUnique);
6230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes);
62426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd);
6250dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (res) {
6265ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed set quota rule");
6270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            goto fail;
6280dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
6290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        quotaIfaces.push_front(QuotaInfo(ifaceName, maxBytes, 0));
6310dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6320dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    } else {
6338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res |= updateQuota(costName, maxBytes);
6340dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (res) {
6355ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed update quota for %s", iface);
6360dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            goto fail;
6370dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
6388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        it->quota = maxBytes;
6390dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
6400dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return 0;
6410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    fail:
6430dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /*
6440dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse
6450dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * rules in the kernel to see which ones need cleaning up.
6460dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * For now callers needs to choose if they want to "ndc bandwidth enable"
6470dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * which resets everything.
6480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     */
6490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    removeInterfaceSharedQuota(ifn);
6500dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return -1;
6510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
6520dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceSharedQuota(int64_t *bytes) {
6548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return getInterfaceQuota("shared", bytes);
6558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
6568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
6578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceQuota(const char *costName, int64_t *bytes) {
6588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    FILE *fp;
6598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *fname;
6608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int scanRes;
6618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
6628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&fname, "/proc/net/xt_quota/%s", costName);
6638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fp = fopen(fname, "r");
6648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(fname);
6658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!fp) {
6665ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Reading quota %s failed (%s)", costName, strerror(errno));
6678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
6688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
6698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    scanRes = fscanf(fp, "%lld", bytes);
6703fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("Read quota res=%d bytes=%lld", scanRes, *bytes);
6718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fclose(fp);
6728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return scanRes == 1 ? 0 : -1;
6738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
6748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
6750dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::removeInterfaceQuota(const char *iface) {
6760dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char ifn[MAX_IFACENAME_LEN];
6780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
67926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string ifaceName;
68026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    const char *costName;
68126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::list<QuotaInfo>::iterator it;
6820dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
6845ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
68526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
68626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
68726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    ifaceName = ifn;
68826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    costName = iface;
6890dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6900dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
6918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == ifaceName)
6920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            break;
6930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
6940dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == quotaIfaces.end()) {
6965ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No such iface %s to delete", ifn);
6970dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        return -1;
6980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
6990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /* This also removes the quota command of CostlyIface chain. */
70126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= cleanupCostlyIface(ifn, QuotaUnique);
7020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    quotaIfaces.erase(it);
7040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7050dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
7060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
7078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::updateQuota(const char *quotaName, int64_t bytes) {
7098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    FILE *fp;
7108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *fname;
7118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&fname, "/proc/net/xt_quota/%s", quotaName);
7138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fp = fopen(fname, "w");
7148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(fname);
7158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!fp) {
7165ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Updating quota %s failed (%s)", quotaName, strerror(errno));
7178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
7188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
7198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fprintf(fp, "%lld\n", bytes);
7208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fclose(fp);
7218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return 0;
7228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
7238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesAlertCmd(IptOp op, const char *alertName, int64_t bytes) {
7258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
7268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    const char *opFlag;
727876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall    const char *ifaceLimiting;
7288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
7298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    switch (op) {
7318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpInsert:
7328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-I";
7338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
7348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpReplace:
7358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-R";
7368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
7378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    default:
7388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpDelete:
7398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-D";
7408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
7418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
7428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
743876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall    ifaceLimiting = "! -i lo+";
7440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "bw_INPUT",
745c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich        bytes, alertName);
7468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
7478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertQuotaCmd);
748876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall    ifaceLimiting = "! -o lo+";
7490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "bw_OUTPUT",
750c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich        bytes, alertName);
7518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
7528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertQuotaCmd);
7538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
7548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
7558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
756c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::runIptablesAlertFwdCmd(IptOp op, const char *alertName, int64_t bytes) {
757c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    int res = 0;
758c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *opFlag;
759c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *ifaceLimiting;
7608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
761c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
762c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    switch (op) {
763c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    case IptOpInsert:
764c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        opFlag = "-I";
765c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        break;
766c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    case IptOpReplace:
767c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        opFlag = "-R";
768c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        break;
769c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    default:
770c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    case IptOpDelete:
771c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        opFlag = "-D";
772c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        break;
773c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
774c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
775c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    ifaceLimiting = "! -i lo+";
7760031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "bw_FORWARD",
777c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich        bytes, alertName);
778c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    res = runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
779c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    free(alertQuotaCmd);
780c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    return res;
781c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall}
782c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
783c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlert(int64_t bytes) {
784c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
7858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
7868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
7885ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
7898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
7908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
7918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (globalAlertBytes) {
7928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res = updateQuota(alertName, bytes);
7938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    } else {
7948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res = runIptablesAlertCmd(IptOpInsert, alertName, bytes);
795c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        if (globalAlertTetherCount) {
7963fb42e026ffebab2c8f282e42501040121e32d83Steve Block            ALOGV("setGlobalAlert for %d tether", globalAlertTetherCount);
797c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            res |= runIptablesAlertFwdCmd(IptOpInsert, alertName, bytes);
798c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        }
7998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    globalAlertBytes = bytes;
8018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
8028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
8038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
804c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlertInForwardChain(void) {
805c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
806c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    int res = 0;
807c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
808c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    globalAlertTetherCount++;
8093fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("setGlobalAlertInForwardChain(): %d tether", globalAlertTetherCount);
810c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
811c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /*
812c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is no globalAlert active we are done.
813c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is an active globalAlert but this is not the 1st
814c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * tether, we are also done.
815c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     */
816c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!globalAlertBytes || globalAlertTetherCount != 1) {
817c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return 0;
818c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
819c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
820c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /* We only add the rule if this was the 1st tether added. */
821c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    res = runIptablesAlertFwdCmd(IptOpInsert, alertName, globalAlertBytes);
822c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    return res;
823c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall}
824c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
8258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeGlobalAlert(void) {
8268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
827c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
8288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
8298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!globalAlertBytes) {
8315ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set");
8328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res = runIptablesAlertCmd(IptOpDelete, alertName, globalAlertBytes);
835c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (globalAlertTetherCount) {
836c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        res |= runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes);
837c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
8388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    globalAlertBytes = 0;
8398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
8408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
8418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
842c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::removeGlobalAlertInForwardChain(void) {
843c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    int res = 0;
844c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
845c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
846c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!globalAlertTetherCount) {
8475ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set");
848c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return -1;
849c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
850c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
851c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    globalAlertTetherCount--;
852c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /*
853c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is no globalAlert active we are done.
854c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is an active globalAlert but there are more
855c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * tethers, we are also done.
856c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     */
857c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!globalAlertBytes || globalAlertTetherCount >= 1) {
858c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return 0;
859c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
860c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
861c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /* We only detete the rule if this was the last tether removed. */
862c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    res = runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes);
863c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    return res;
864c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall}
865c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
8668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setSharedAlert(int64_t bytes) {
8678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!sharedQuotaBytes) {
8685ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Need to have a prior shared quota set to set an alert");
8698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
8725ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
8738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return setCostlyAlert("shared", bytes, &sharedAlertBytes);
8768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
8778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeSharedAlert(void) {
8798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return removeCostlyAlert("shared", &sharedAlertBytes);
8808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
8818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setInterfaceAlert(const char *iface, int64_t bytes) {
8838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    std::list<QuotaInfo>::iterator it;
8848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
8865ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
8878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
8908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == iface)
8918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
8928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (it == quotaIfaces.end()) {
8955ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Need to have a prior interface quota set to set an alert");
8968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return setCostlyAlert(iface, bytes, &it->alert);
9008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
9018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeInterfaceAlert(const char *iface) {
9038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    std::list<QuotaInfo>::iterator it;
9048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
9068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == iface)
9078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
9088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (it == quotaIfaces.end()) {
9115ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set for interface %s", iface);
9128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return removeCostlyAlert(iface, &it->alert);
9168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
9178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes) {
9198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
9208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *chainNameAndPos;
9218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
9228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertName;
9238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
9255ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
9268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&alertName, "%sAlert", costName);
9298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (*alertBytes) {
9308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res = updateQuota(alertName, *alertBytes);
9318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    } else {
9328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        asprintf(&chainNameAndPos, "costly_%s %d", costName, ALERT_RULE_POS_IN_COSTLY_CHAIN);
933c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich        asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "", "-I", chainNameAndPos, bytes, alertName);
9348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
9358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        free(alertQuotaCmd);
9368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        free(chainNameAndPos);
9378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    *alertBytes = bytes;
9398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertName);
9408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
9418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
9428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeCostlyAlert(const char *costName, int64_t *alertBytes) {
9448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
9458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *chainName;
9468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertName;
9478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
9488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&alertName, "%sAlert", costName);
9508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!*alertBytes) {
9515ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set for %s alert", costName);
9528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&chainName, "costly_%s", costName);
956c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "", "-D", chainName, *alertBytes, alertName);
9578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd);
9588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertQuotaCmd);
9598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(chainName);
9608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    *alertBytes = 0;
9628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertName);
9638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
9648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
965db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
966db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/*
967db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Parse the ptks and bytes out of:
9680031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Chain FORWARD (policy RETURN 0 packets, 0 bytes)
969db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall *     pkts      bytes target     prot opt in     out     source               destination
9700031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *        0        0 RETURN     all  --  rmnet0 wlan0   0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
971db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall *        0        0 DROP       all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0            state INVALID
9720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *        0        0 RETURN     all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0
973db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall *
974db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */
975a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrallint BandwidthController::parseForwardChainStats(TetherStats &stats, FILE *fp,
976a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall                                                std::string &extraProcessingInfo) {
977db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    int res;
978db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN];
979db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char iface0[MAX_IPT_OUTPUT_LINE_LEN];
980db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char iface1[MAX_IPT_OUTPUT_LINE_LEN];
981db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char rest[MAX_IPT_OUTPUT_LINE_LEN];
982db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
983db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char *buffPtr;
984db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    int64_t packets, bytes;
985db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
986db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) {
987db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        /* Clean up, so a failed parse can still print info */
988db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        iface0[0] = iface1[0] = rest[0] = packets = bytes = 0;
9890031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        res = sscanf(buffPtr, "%lld %lld RETURN all -- %s %s 0.%s",
990db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall                &packets, &bytes, iface0, iface1, rest);
9913fb42e026ffebab2c8f282e42501040121e32d83Steve Block        ALOGV("parse res=%d iface0=<%s> iface1=<%s> pkts=%lld bytes=%lld rest=<%s> orig line=<%s>", res,
992db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall             iface0, iface1, packets, bytes, rest, buffPtr);
993a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall        extraProcessingInfo += buffPtr;
994a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall
995db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        if (res != 5) {
996db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            continue;
997db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        }
998db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        if ((stats.ifaceIn == iface0) && (stats.ifaceOut == iface1)) {
9993fb42e026ffebab2c8f282e42501040121e32d83Steve Block            ALOGV("iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets);
1000db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            stats.rxPackets = packets;
1001db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            stats.rxBytes = bytes;
1002db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        } else if ((stats.ifaceOut == iface0) && (stats.ifaceIn == iface1)) {
10033fb42e026ffebab2c8f282e42501040121e32d83Steve Block            ALOGV("iface_in=%s iface_out=%s tx_bytes=%lld tx_packets=%lld ", iface1, iface0, bytes, packets);
1004db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            stats.txPackets = packets;
1005db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            stats.txBytes = bytes;
1006db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        }
1007db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1008db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /* Failure if rx or tx was not found */
1009db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    return (stats.rxBytes == -1 || stats.txBytes == -1) ? -1 : 0;
1010db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
1011db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1012db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1013db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallchar *BandwidthController::TetherStats::getStatsLine(void) {
1014db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char *msg;
1015db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    asprintf(&msg, "%s %s %lld %lld %lld %lld", ifaceIn.c_str(), ifaceOut.c_str(),
1016db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            rxBytes, rxPackets, txBytes, txPackets);
1017db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    return msg;
1018db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
1019db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1020a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrallint BandwidthController::getTetherStats(TetherStats &stats, std::string &extraProcessingInfo) {
1021db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    int res;
1022db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    std::string fullCmd;
1023db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    FILE *iptOutput;
1024db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    const char *cmd;
1025db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1026db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (stats.rxBytes != -1 || stats.txBytes != -1) {
10275ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Unexpected input stats. Byte counts should be -1.");
1028db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return -1;
1029db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1030db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1031db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /*
1032db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * Why not use some kind of lib to talk to iptables?
1033db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * Because the only libs are libiptc and libip6tc in iptables, and they are
1034db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * not easy to use. They require the known iptables match modules to be
1035db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * preloaded/linked, and require apparently a lot of wrapper code to get
1036db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * the wanted info.
1037db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     */
1038db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    fullCmd = IPTABLES_PATH;
10390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    fullCmd += " -nvx -L natctrl_FORWARD";
1040db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    iptOutput = popen(fullCmd.c_str(), "r");
1041db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!iptOutput) {
10425ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno));
1043a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall            extraProcessingInfo += "Failed to run iptables.";
1044db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return -1;
1045db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1046a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall    res = parseForwardChainStats(stats, iptOutput, extraProcessingInfo);
1047db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    pclose(iptOutput);
1048db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1049db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /* Currently NatController doesn't do ipv6 tethering, so we are done. */
1050db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    return res;
1051db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
1052