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";
548e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_INPUT = "bw_INPUT";
558e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_FORWARD = "bw_FORWARD";
568e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_OUTPUT = "bw_OUTPUT";
578e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_RAW_PREROUTING = "bw_raw_PREROUTING";
588e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_MANGLE_POSTROUTING = "bw_mangle_POSTROUTING";
59db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_CMD_ARGS = 32;
60db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_CMD_LEN = 1024;
61db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_IFACENAME_LEN = 64;
62db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int  BandwidthController::MAX_IPT_OUTPUT_LINE_LEN = 256;
63db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
6411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrallbool BandwidthController::useLogwrapCall = false;
654a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall/**
674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Some comments about the rules:
684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *  * Ordering
694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    - when an interface is marked as costly it should be INSERTED into the INPUT/OUTPUT chains.
7029e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      E.g. "-I bw_INPUT -i rmnet0 --jump costly"
714a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    - quota'd rules in the costly chain should be before penalty_box lookups.
7229e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *    - the qtaguid counting is done at the end of the bw_INPUT/bw_OUTPUT user chains.
734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
744a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * global quota vs per interface quota
754a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *   - global quota for all costly interfaces uses a single costly chain:
764a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    . initial rules
77bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -N costly_shared
7829e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_INPUT -i iface0 --jump costly_shared
7929e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_OUTPUT -o iface0 --jump costly_shared
80bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -I costly_shared -m quota \! --quota 500000 \
81bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *          --jump REJECT --reject-with icmp-net-prohibited
82bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -A costly_shared --jump penalty_box
838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *
844a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    . adding a new iface to this, E.g.:
8529e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_INPUT -i iface1 --jump costly_shared
8629e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_OUTPUT -o iface1 --jump costly_shared
874a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
884a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *   - quota per interface. This is achieve by having "costly" chains per quota.
894a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *     E.g. adding a new costly interface iface0 with its own quota:
904a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *      iptables -N costly_iface0
9129e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_INPUT -i iface0 --jump costly_iface0
9229e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      iptables -I bw_OUTPUT -o iface0 --jump costly_iface0
93bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -A costly_iface0 -m quota \! --quota 500000 \
94bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *          --jump REJECT --reject-with icmp-net-prohibited
95bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *      iptables -A costly_iface0 --jump penalty_box
964a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
974a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * penalty_box handling:
984a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *  - only one penalty_box for all interfaces
994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *   E.g  Adding an app:
100bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *    iptables -A penalty_box -m owner --uid-owner app_3 \
101bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *        --jump REJECT --reject-with icmp-net-prohibited
1024a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */
1030031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char *BandwidthController::IPT_FLUSH_COMMANDS[] = {
1040031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /*
1050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Cleanup rules.
1060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Should normally include costly_<iface>, but we rely on the way they are setup
1070031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * to allow coexistance.
10839f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall     */
1090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F bw_INPUT",
1100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F bw_OUTPUT",
1110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F bw_FORWARD",
1120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F penalty_box",
1130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-F costly_shared",
114f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall
115f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall    "-t raw -F bw_raw_PREROUTING",
116f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall    "-t mangle -F bw_mangle_POSTROUTING",
1170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall};
1180031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1190031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall/* The cleanup commands assume flushing has been done. */
1200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char *BandwidthController::IPT_CLEANUP_COMMANDS[] = {
1210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-X penalty_box",
1220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-X costly_shared",
1230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall};
1244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
125db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_SETUP_COMMANDS[] = {
126bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    "-N costly_shared",
1270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    "-N penalty_box",
1280dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall};
1290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
130db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_BASIC_ACCOUNTING_COMMANDS[] = {
1310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_INPUT -i lo --jump RETURN",
1320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_INPUT -m owner --socket-exists", /* This is a tracking rule. */
1330dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
1340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_OUTPUT -o lo --jump RETURN",
1350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_OUTPUT -m owner --socket-exists", /* This is a tracking rule. */
1360dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
137bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    "-A costly_shared --jump penalty_box",
138f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall
139f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall    "-t raw -A bw_raw_PREROUTING ! -i lo+ -m owner --socket-exists", /* This is a tracking rule. */
140f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall    "-t mangle -A bw_mangle_POSTROUTING ! -o lo+ -m owner --socket-exists", /* This is a tracking rule. */
1410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall};
1424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
1434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallBandwidthController::BandwidthController(void) {
1444a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char value[PROPERTY_VALUE_MAX];
1454a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
14611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    property_get("persist.bandwidth.uselogwrap", value, "0");
14711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    useLogwrapCall = !strcmp(value, "1");
1484a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
1494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
150ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrallint BandwidthController::runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling,
151ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall                                         IptFailureLog failureHandling) {
1520dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
1538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1543fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("runIpxtablesCmd(cmd=%s)", cmd);
155ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    res |= runIptablesCmd(cmd, rejectHandling, IptIpV4, failureHandling);
156ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    res |= runIptablesCmd(cmd, rejectHandling, IptIpV6, failureHandling);
1570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
1580dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
1590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
16026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::StrncpyAndCheck(char *buffer, const char *src, size_t buffSize) {
16126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
16226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    memset(buffer, '\0', buffSize);  // strncpy() is not filling leftover with '\0'
16326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    strncpy(buffer, src, buffSize);
16426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return buffer[buffSize - 1];
16526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall}
16626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
1678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesCmd(const char *cmd, IptRejectOp rejectHandling,
168ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall                                        IptIpVer iptVer, IptFailureLog failureHandling) {
16926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    char buffer[MAX_CMD_LEN];
1704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    const char *argv[MAX_CMD_ARGS];
17126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    int argc = 0;
1724a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char *next = buffer;
1734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char *tmp;
17411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    int res;
1754a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
1760dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::string fullCmd = cmd;
17726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
17826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    if (rejectHandling == IptRejectAdd) {
1790dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        fullCmd += " --jump REJECT --reject-with";
18026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        switch (iptVer) {
18126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        case IptIpV4:
1828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            fullCmd += " icmp-net-prohibited";
1838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
18426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        case IptIpV6:
1858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            fullCmd += " icmp6-adm-prohibited";
1868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
1870dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
1880dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
1890dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
19011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    fullCmd.insert(0, " ");
19111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    fullCmd.insert(0, iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH);
1924a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
19311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    if (!useLogwrapCall) {
1949e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        res = system_nosh(fullCmd.c_str());
19511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    } else {
19611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) {
1975ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("iptables command too long");
1984a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            return -1;
1994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall        }
200fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
20111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        argc = 0;
20211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        while ((tmp = strsep(&next, " "))) {
20311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall            argv[argc++] = tmp;
20411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall            if (argc >= MAX_CMD_ARGS) {
2055ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block                ALOGE("iptables argument overflow");
20611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall                return -1;
20711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall            }
20811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        }
20911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall
21011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        argv[argc] = NULL;
211c4bbfa247dbe4dda17e28694d49afd3ec0b06badGlenn Kasten        res = logwrap(argc, argv);
21211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    }
213ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    if (res && failureHandling == IptFailShow) {
2145ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("runIptablesCmd(): failed %s res=%d", fullCmd.c_str(), res);
21511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    }
21611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    return res;
2174a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
2184a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2190031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint BandwidthController::setupIptablesHooks(void) {
2200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /* Some of the initialCommands are allowed to fail */
2220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*),
2230031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_FLUSH_COMMANDS, RunCmdFailureOk);
2240031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2250031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_CLEANUP_COMMANDS) / sizeof(char*),
2260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_CLEANUP_COMMANDS, RunCmdFailureOk);
2270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_SETUP_COMMANDS) / sizeof(char*),
2290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_SETUP_COMMANDS, RunCmdFailureBad);
2300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
2320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
2330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint BandwidthController::enableBandwidthControl(bool force) {
235fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res;
2360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    char value[PROPERTY_VALUE_MAX];
2370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!force) {
2390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            property_get("persist.bandwidth.enable", value, "1");
2400031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            if (!strcmp(value, "0"))
2410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall                    return 0;
2420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
2438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
244db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /* Let's pretend we started from scratch ... */
2458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    sharedQuotaIfaces.clear();
2468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    quotaIfaces.clear();
2478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    naughtyAppUids.clear();
248db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    globalAlertBytes = 0;
249c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    globalAlertTetherCount = 0;
250db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    sharedQuotaBytes = sharedAlertBytes = 0;
251db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
2520031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    res = runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*),
2530031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_FLUSH_COMMANDS, RunCmdFailureOk);
254db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
2550031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    res |= runCommands(sizeof(IPT_BASIC_ACCOUNTING_COMMANDS) / sizeof(char*),
256db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            IPT_BASIC_ACCOUNTING_COMMANDS, RunCmdFailureBad);
2578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
258fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return res;
2594a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2604a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
2614a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2624a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::disableBandwidthControl(void) {
2630031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*),
2640031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            IPT_FLUSH_COMMANDS, RunCmdFailureOk);
265fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return 0;
2664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
2674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runCommands(int numCommands, const char *commands[],
2698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall                                     RunCmdErrHandling cmdErrHandling) {
270fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res = 0;
271ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    IptFailureLog failureLogging = IptFailShow;
272ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    if (cmdErrHandling == RunCmdFailureOk) {
273ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall        failureLogging = IptFailHide;
274ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    }
2753fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("runCommands(): %d commands", numCommands);
276fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) {
277ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall        res = runIpxtablesCmd(commands[cmdNum], IptRejectNoAdd, failureLogging);
2780031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        if (res && cmdErrHandling != RunCmdFailureOk)
279fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return res;
280fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
2810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
282fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
283fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
2840dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallstd::string BandwidthController::makeIptablesNaughtyCmd(IptOp op, int uid) {
285fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    std::string res;
2868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *buff;
2878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    const char *opFlag;
288fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
289fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    switch (op) {
2908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpInsert:
2918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-I";
2928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
2938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpReplace:
2948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-R";
2958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
2968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    default:
2978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpDelete:
2988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-D";
2998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
300fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
3018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&buff, "%s penalty_box -m owner --uid-owner %d", opFlag, uid);
3028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res = buff;
3038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(buff);
304fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return res;
305fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
306fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
307fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::addNaughtyApps(int numUids, char *appUids[]) {
30826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpAdd);
309fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
310fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
311fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeNaughtyApps(int numUids, char *appUids[]) {
31226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpRemove);
313fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
314fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
31526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::maninpulateNaughtyApps(int numUids, char *appStrUids[], NaughtyAppOp appOp) {
316fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    char cmd[MAX_CMD_LEN];
317fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int uidNum;
31826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    const char *failLogTemplate;
31926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    IptOp op;
320fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int appUids[numUids];
32126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string naughtyCmd;
322b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall    std::list<int /*uid*/>::iterator it;
3238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
32426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    switch (appOp) {
32526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case NaughtyAppOpAdd:
3268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        op = IptOpInsert;
3278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        failLogTemplate = "Failed to add app uid %d to penalty box.";
3288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
32926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case NaughtyAppOpRemove:
3308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        op = IptOpDelete;
3318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        failLogTemplate = "Failed to delete app uid %d from penalty box.";
3328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
3330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    default:
3340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("Unexpected app Op %d", appOp);
3350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
33626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
33726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
338fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (uidNum = 0; uidNum < numUids; uidNum++) {
339fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        appUids[uidNum] = atol(appStrUids[uidNum]);
340fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (appUids[uidNum] == 0) {
3415ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE(failLogTemplate, appUids[uidNum]);
342fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            goto fail_parse;
343fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
344