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
17e478873947f995e44e8c559342462c177a420ae0JP 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
2513debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti#include <string>
2613debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti#include <vector>
2713debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti
288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <errno.h>
294a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <fcntl.h>
30db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall#include <stdio.h>
318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <stdlib.h>
324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <string.h>
330b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich#include <ctype.h>
344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
352a54d96c5ae809216965e6f86e70cdae2ed7e09cMatthew Leach#define __STDC_FORMAT_MACROS 1
362a54d96c5ae809216965e6f86e70cdae2ed7e09cMatthew Leach#include <inttypes.h>
372a54d96c5ae809216965e6f86e70cdae2ed7e09cMatthew Leach
384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/socket.h>
394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/stat.h>
404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/types.h>
414a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/wait.h>
424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/netlink.h>
444a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/rtnetlink.h>
454a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/pkt_sched.h>
464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
477618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti#include "android-base/stringprintf.h"
4813debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti#include "android-base/strings.h"
494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#define LOG_TAG "BandwidthController"
504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/log.h>
514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/properties.h>
5214150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand#include <logwrap/logwrap.h>
534a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
540031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "NetdConstants.h"
554a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include "BandwidthController.h"
56baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall#include "NatController.h"  /* For LOCAL_TETHER_COUNTERS_CHAIN */
57baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall#include "ResponseCode.h"
584a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
59db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* Alphabetical */
607776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev#define ALERT_IPT_TEMPLATE "%s %s -m quota2 ! --quota %" PRId64" --name %s"
618e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_INPUT = "bw_INPUT";
628e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_FORWARD = "bw_FORWARD";
638e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_OUTPUT = "bw_OUTPUT";
648e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_RAW_PREROUTING = "bw_raw_PREROUTING";
658e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_MANGLE_POSTROUTING = "bw_mangle_POSTROUTING";
667618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti
6786a4798264c9421cb02bc69836a323d918f73779Lorenzo Colittiauto BandwidthController::execFunction = android_fork_execvp;
6886a4798264c9421cb02bc69836a323d918f73779Lorenzo Colittiauto BandwidthController::popenFunction = popen;
6913debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colittiauto BandwidthController::iptablesRestoreFunction = execIptablesRestore;
7086a4798264c9421cb02bc69836a323d918f73779Lorenzo Colitti
717618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colittinamespace {
727618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti
737618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitticonst char ALERT_GLOBAL_NAME[] = "globalAlert";
747618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitticonst int  MAX_CMD_ARGS = 32;
757618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitticonst int  MAX_CMD_LEN = 1024;
767618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitticonst int  MAX_IFACENAME_LEN = 64;
777618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitticonst int  MAX_IPT_OUTPUT_LINE_LEN = 256;
78db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall/**
804a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Some comments about the rules:
814a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *  * Ordering
824a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    - when an interface is marked as costly it should be INSERTED into the INPUT/OUTPUT chains.
8329e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *      E.g. "-I bw_INPUT -i rmnet0 --jump costly"
847e51cde19af016456fff750f745db8132f3124a5JP Abgrall *    - quota'd rules in the costly chain should be before bw_penalty_box lookups.
8529e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall *    - the qtaguid counting is done at the end of the bw_INPUT/bw_OUTPUT user chains.
864a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
874a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * global quota vs per interface quota
884a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *   - global quota for all costly interfaces uses a single costly chain:
894a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    . initial rules
907e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -N bw_costly_shared
917e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -I bw_INPUT -i iface0 --jump bw_costly_shared
927e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -I bw_OUTPUT -o iface0 --jump bw_costly_shared
937e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -I bw_costly_shared -m quota \! --quota 500000 \
94bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall *          --jump REJECT --reject-with icmp-net-prohibited
957e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -A bw_costly_shared --jump bw_penalty_box
967618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti *      iptables -A bw_penalty_box --jump bw_happy_box
97464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *      iptables -A bw_happy_box --jump bw_data_saver
988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *
994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *    . adding a new iface to this, E.g.:
1007e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -I bw_INPUT -i iface1 --jump bw_costly_shared
1017e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -I bw_OUTPUT -o iface1 --jump bw_costly_shared
1024a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
1034a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *   - quota per interface. This is achieve by having "costly" chains per quota.
1044a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *     E.g. adding a new costly interface iface0 with its own quota:
1057e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -N bw_costly_iface0
1067e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -I bw_INPUT -i iface0 --jump bw_costly_iface0
1077e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -I bw_OUTPUT -o iface0 --jump bw_costly_iface0
1087e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -A bw_costly_iface0 -m quota \! --quota 500000 \
109e478873947f995e44e8c559342462c177a420ae0JP Abgrall *          --jump REJECT --reject-with icmp-port-unreachable
1107e51cde19af016456fff750f745db8132f3124a5JP Abgrall *      iptables -A bw_costly_iface0 --jump bw_penalty_box
1114a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall *
112464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti * * Penalty box, happy box and data saver.
113464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *   - bw_penalty box is a blacklist of apps that are rejected.
114464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *   - bw_happy_box is a whitelist of apps. It always includes all system apps
115464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *   - bw_data_saver implements data usage restrictions.
116464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *   - Via the UI the user can add and remove apps from the whitelist and
117464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *     blacklist, and turn on/off data saver.
118464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *   - The blacklist takes precedence over the whitelist and the whitelist
119464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *     takes precedence over data saver.
120464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *
1217e51cde19af016456fff750f745db8132f3124a5JP Abgrall * * bw_penalty_box handling:
1227e51cde19af016456fff750f745db8132f3124a5JP Abgrall *  - only one bw_penalty_box for all interfaces
1237618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti *   E.g  Adding an app:
1247e51cde19af016456fff750f745db8132f3124a5JP Abgrall *    iptables -I bw_penalty_box -m owner --uid-owner app_3 \
125e478873947f995e44e8c559342462c177a420ae0JP Abgrall *        --jump REJECT --reject-with icmp-port-unreachable
126e478873947f995e44e8c559342462c177a420ae0JP Abgrall *
1277e51cde19af016456fff750f745db8132f3124a5JP Abgrall * * bw_happy_box handling:
1287618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti *  - The bw_happy_box comes after the penalty box.
129e478873947f995e44e8c559342462c177a420ae0JP Abgrall *   E.g  Adding a happy app,
1307e51cde19af016456fff750f745db8132f3124a5JP Abgrall *    iptables -I bw_happy_box -m owner --uid-owner app_3 \
131e478873947f995e44e8c559342462c177a420ae0JP Abgrall *        --jump RETURN
1327618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti *
133464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti * * bw_data_saver handling:
134464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *  - The bw_data_saver comes after the happy box.
135464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *    Enable data saver:
136464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *      iptables -R 1 bw_data_saver --jump REJECT --reject-with icmp-port-unreachable
137464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *    Disable data saver:
138464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti *      iptables -R 1 bw_data_saver --jump RETURN
1394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */
1407618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti
14113debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitticonst std::string COMMIT_AND_CLOSE = "COMMIT\n\x04";
14213debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitticonst std::string DATA_SAVER_ENABLE_COMMAND = "-R bw_data_saver 1";
14313debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitticonst std::string HAPPY_BOX_WHITELIST_COMMAND = android::base::StringPrintf(
14413debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "-I bw_happy_box -m owner --uid-owner %d-%d --jump RETURN", 0, MAX_SYSTEM_UID);
14513debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti
14613debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colittistatic const std::vector<std::string> IPT_FLUSH_COMMANDS = {
1470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /*
1480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Cleanup rules.
1497e51cde19af016456fff750f745db8132f3124a5JP Abgrall     * Should normally include bw_costly_<iface>, but we rely on the way they are setup
1500031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * to allow coexistance.
15139f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall     */
15213debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "*filter",
15313debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    ":bw_INPUT -",
15413debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    ":bw_OUTPUT -",
15513debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    ":bw_FORWARD -",
15613debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    ":bw_happy_box -",
15713debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    ":bw_penalty_box -",
15813debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    ":bw_data_saver -",
15913debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    ":bw_costly_shared -",
16013debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "COMMIT",
16113debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "*raw",
16213debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    ":bw_raw_PREROUTING -",
16313debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "COMMIT",
16413debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "*mangle",
16513debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    ":bw_mangle_POSTROUTING -",
16613debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    COMMIT_AND_CLOSE
1670dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall};
1680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
16913debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colittistatic const std::vector<std::string> IPT_BASIC_ACCOUNTING_COMMANDS = {
17013debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "*filter",
1710031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_INPUT -m owner --socket-exists", /* This is a tracking rule. */
1720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    "-A bw_OUTPUT -m owner --socket-exists", /* This is a tracking rule. */
1737618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti    "-A bw_costly_shared --jump bw_penalty_box",
174464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti    "-A bw_penalty_box --jump bw_happy_box",
175464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti    "-A bw_happy_box --jump bw_data_saver",
176464eabecf1174154b8f61845610c3f4f0ca294b3Lorenzo Colitti    "-A bw_data_saver -j RETURN",
17713debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    HAPPY_BOX_WHITELIST_COMMAND,
17813debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "COMMIT",
17913debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti
18013debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "*raw",
18113debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "-A bw_raw_PREROUTING -m owner --socket-exists", /* This is a tracking rule. */
18213debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "COMMIT",
18313debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti
18413debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "*mangle",
18513debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    "-A bw_mangle_POSTROUTING -m owner --socket-exists", /* This is a tracking rule. */
18613debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    COMMIT_AND_CLOSE
1877618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti};
1887618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti
1897618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti
1907618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti}  // namespace
1917618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti
1924a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallBandwidthController::BandwidthController(void) {
1934a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
1944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
195a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrallint BandwidthController::runIpxtablesCmd(const char *cmd, IptJumpOp jumpHandling,
196ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall                                         IptFailureLog failureHandling) {
1970dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
1988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1993fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("runIpxtablesCmd(cmd=%s)", cmd);
200a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    res |= runIptablesCmd(cmd, jumpHandling, IptIpV4, failureHandling);
201a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    res |= runIptablesCmd(cmd, jumpHandling, IptIpV6, failureHandling);
2020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
2030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
2040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
20526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::StrncpyAndCheck(char *buffer, const char *src, size_t buffSize) {
20626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
20726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    memset(buffer, '\0', buffSize);  // strncpy() is not filling leftover with '\0'
20826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    strncpy(buffer, src, buffSize);
20926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return buffer[buffSize - 1];
21026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall}
21126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
212a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrallint BandwidthController::runIptablesCmd(const char *cmd, IptJumpOp jumpHandling,
213ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall                                        IptIpVer iptVer, IptFailureLog failureHandling) {
21426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    char buffer[MAX_CMD_LEN];
2154a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    const char *argv[MAX_CMD_ARGS];
21626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    int argc = 0;
2174a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char *next = buffer;
2184a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char *tmp;
21911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    int res;
22014150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    int status = 0;
2214a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2220dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::string fullCmd = cmd;
22326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
224a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    switch (jumpHandling) {
225a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    case IptJumpReject:
226340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall        /*
227340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall         * Must be carefull what one rejects with, as uper layer protocols will just
228340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall         * keep on hammering the device until the number of retries are done.
229340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall         * For port-unreachable (default), TCP should consider as an abort (RFC1122).
230340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall         */
231340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall        fullCmd += " --jump REJECT";
232a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        break;
233a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    case IptJumpReturn:
234a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        fullCmd += " --jump RETURN";
235a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        break;
236a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    case IptJumpNoAdd:
237a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        break;
2380dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
2390dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
24094b2ab92f6e886d24092781159714be75c9f3954Paul Jensen    fullCmd.insert(0, " -w ");
24111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    fullCmd.insert(0, iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH);
2424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
24314150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) {
24414150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand        ALOGE("iptables command too long");
24514150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand        return -1;
24614150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    }
24714150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand
24814150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    argc = 0;
24914150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    while ((tmp = strsep(&next, " "))) {
25014150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand        argv[argc++] = tmp;
25114150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand        if (argc >= MAX_CMD_ARGS) {
25214150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand            ALOGE("iptables argument overflow");
2534a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            return -1;
2544a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall        }
25514150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    }
256fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
25714150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand    argv[argc] = NULL;
25886a4798264c9421cb02bc69836a323d918f73779Lorenzo Colitti    res = execFunction(argc, (char **)argv, &status, false,
25914150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand            failureHandling == IptFailShow);
260c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall    res = res || !WIFEXITED(status) || WEXITSTATUS(status);
261c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall    if (res && failureHandling == IptFailShow) {
262c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall      ALOGE("runIptablesCmd(): res=%d status=%d failed %s", res, status,
263c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall            fullCmd.c_str());
26411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    }
26511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    return res;
2664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
2674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
2680e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrallvoid BandwidthController::flushCleanTables(bool doClean) {
2690e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    /* Flush and remove the bw_costly_<iface> tables */
2700e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    flushExistingCostlyTables(doClean);
2710031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
27213debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    std::string commands = android::base::Join(IPT_FLUSH_COMMANDS, '\n');
27313debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    iptablesRestoreFunction(V4V6, commands);
2740e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall}
2750e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall
2760e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrallint BandwidthController::setupIptablesHooks(void) {
2770e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    /* flush+clean is allowed to fail */
2780e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    flushCleanTables(true);
2790031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
2800031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
2810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2820031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint BandwidthController::enableBandwidthControl(bool force) {
2830031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    char value[PROPERTY_VALUE_MAX];
2840031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2850031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!force) {
2860031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            property_get("persist.bandwidth.enable", value, "1");
2870031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            if (!strcmp(value, "0"))
2880031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall                    return 0;
2890031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
2908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
291db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /* Let's pretend we started from scratch ... */
2928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    sharedQuotaIfaces.clear();
2938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    quotaIfaces.clear();
294db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    globalAlertBytes = 0;
295c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    globalAlertTetherCount = 0;
296db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    sharedQuotaBytes = sharedAlertBytes = 0;
297db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
2980e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    flushCleanTables(false);
29913debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    std::string commands = android::base::Join(IPT_BASIC_ACCOUNTING_COMMANDS, '\n');
30013debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    return iptablesRestoreFunction(V4V6, commands);
3014a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
3024a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
3034a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::disableBandwidthControl(void) {
3040e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall
3050e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    flushCleanTables(false);
306fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return 0;
3074a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
3084a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
3097618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colittiint BandwidthController::enableDataSaver(bool enable) {
31013debb8996ca9cd3ce5d7f2817fe19e5df148f08Lorenzo Colitti    return runIpxtablesCmd(DATA_SAVER_ENABLE_COMMAND.c_str(),
3117618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti                           enable ? IptJumpReject : IptJumpReturn, IptFailShow);
3127618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti}
3137618ccb39a9e61b4b1e28e96394fd7097e62db8eLorenzo Colitti
3148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runCommands(int numCommands, const char *commands[],
3158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall                                     RunCmdErrHandling cmdErrHandling) {
316fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res = 0;
317ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    IptFailureLog failureLogging = IptFailShow;
318ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    if (cmdErrHandling == RunCmdFailureOk) {
319ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall        failureLogging = IptFailHide;
320ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall    }
3213fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("runCommands(): %d commands", numCommands);
322fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) {
323a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        res = runIpxtablesCmd(commands[cmdNum], IptJumpNoAdd, failureLogging);
3240031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        if (res && cmdErrHandling != RunCmdFailureOk)
325fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return res;
326fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
3270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
328fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
329fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
330a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrallstd::string BandwidthController::makeIptablesSpecialAppCmd(IptOp op, int uid, const char *chain) {
331fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    std::string res;
3328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *buff;
3338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    const char *opFlag;
334fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
335fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    switch (op) {
3368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpInsert:
3378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-I";
3388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
339109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall    case IptOpAppend:
340a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        ALOGE("Append op not supported for %s uids", chain);
341a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        res = "";
342a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        return res;
343109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        break;
3448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpReplace:
3458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-R";
3468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
3478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    default:
3488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpDelete:
3498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-D";
3508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
351fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
352a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    asprintf(&buff, "%s %s -m owner --uid-owner %d", opFlag, chain, uid);
3538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res = buff;
3548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(buff);
355fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return res;
356fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
357fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
358fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::addNaughtyApps(int numUids, char *appUids[]) {
359a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    return manipulateNaughtyApps(numUids, appUids, SpecialAppOpAdd);
360fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
361fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
362fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeNaughtyApps(int numUids, char *appUids[]) {
363a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    return manipulateNaughtyApps(numUids, appUids, SpecialAppOpRemove);
364fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
365fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
366e478873947f995e44e8c559342462c177a420ae0JP Abgrallint BandwidthController::addNiceApps(int numUids, char *appUids[]) {
367e478873947f995e44e8c559342462c177a420ae0JP Abgrall    return manipulateNiceApps(numUids, appUids, SpecialAppOpAdd);
368e478873947f995e44e8c559342462c177a420ae0JP Abgrall}
369e478873947f995e44e8c559342462c177a420ae0JP Abgrall
370e478873947f995e44e8c559342462c177a420ae0JP Abgrallint BandwidthController::removeNiceApps(int numUids, char *appUids[]) {
371e478873947f995e44e8c559342462c177a420ae0JP Abgrall    return manipulateNiceApps(numUids, appUids, SpecialAppOpRemove);
372e478873947f995e44e8c559342462c177a420ae0JP Abgrall}
373e478873947f995e44e8c559342462c177a420ae0JP Abgrall
374a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrallint BandwidthController::manipulateNaughtyApps(int numUids, char *appStrUids[], SpecialAppOp appOp) {
375b1f0557b544cd5e689e013ff66591361d75ab1ffLorenzo Colitti    return manipulateSpecialApps(numUids, appStrUids, "bw_penalty_box", IptJumpReject, appOp);
376a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall}
377a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall
378e478873947f995e44e8c559342462c177a420ae0JP Abgrallint BandwidthController::manipulateNiceApps(int numUids, char *appStrUids[], SpecialAppOp appOp) {
379b1f0557b544cd5e689e013ff66591361d75ab1ffLorenzo Colitti    return manipulateSpecialApps(numUids, appStrUids, "bw_happy_box", IptJumpReturn, appOp);
380e478873947f995e44e8c559342462c177a420ae0JP Abgrall}
381e478873947f995e44e8c559342462c177a420ae0JP Abgrall
382a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall
383a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrallint BandwidthController::manipulateSpecialApps(int numUids, char *appStrUids[],
384a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall                                               const char *chain,
385a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall                                               IptJumpOp jumpHandling, SpecialAppOp appOp) {
386a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall
387fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int uidNum;
38826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    const char *failLogTemplate;
38926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    IptOp op;
390fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int appUids[numUids];
391a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    std::string iptCmd;
3928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
39326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    switch (appOp) {
394a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    case SpecialAppOpAdd:
3958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        op = IptOpInsert;
396af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall        failLogTemplate = "Failed to add app uid %s(%d) to %s.";
3978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
398a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    case SpecialAppOpRemove:
3998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        op = IptOpDelete;
400af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall        failLogTemplate = "Failed to delete app uid %s(%d) from %s box.";
4018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
4020031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    default:
4030031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("Unexpected app Op %d", appOp);
4040031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
40526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
40626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
407fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (uidNum = 0; uidNum < numUids; uidNum++) {
408af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall        char *end;
409af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall        appUids[uidNum] = strtoul(appStrUids[uidNum], &end, 0);
410af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall        if (*end || !*appStrUids[uidNum]) {
411af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall            ALOGE(failLogTemplate, appStrUids[uidNum], appUids[uidNum], chain);
412fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            goto fail_parse;
413fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
414fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
415fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
416fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    for (uidNum = 0; uidNum < numUids; uidNum++) {
417b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall        int uid = appUids[uidNum];
418b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall
419a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        iptCmd = makeIptablesSpecialAppCmd(op, uid, chain);
420a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        if (runIpxtablesCmd(iptCmd.c_str(), jumpHandling)) {
421af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall            ALOGE(failLogTemplate, appStrUids[uidNum], uid, chain);
422fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            goto fail_with_uidNum;
423fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
424fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
425fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return 0;
426fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
42726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_with_uidNum:
428fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    /* Try to remove the uid that failed in any case*/
429a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    iptCmd = makeIptablesSpecialAppCmd(IptOpDelete, appUids[uidNum], chain);
430a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    runIpxtablesCmd(iptCmd.c_str(), jumpHandling);
43126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_parse:
43226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    return -1;
4334a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
4344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
43526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallstd::string BandwidthController::makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota) {
436fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    std::string res;
4378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *buff;
4388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    const char *opFlag;
4390dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
4407776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev    ALOGV("makeIptablesQuotaCmd(%d, %" PRId64")", op, quota);
4410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
442fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    switch (op) {
4438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpInsert:
4448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-I";
4458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
446109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall    case IptOpAppend:
447109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        opFlag = "-A";
448109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        break;
4498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpReplace:
4508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-R";
4518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
4528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    default:
4538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpDelete:
4548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-D";
4558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
456fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
4578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
458bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    // The requried IP version specific --jump REJECT ... will be added later.
4597776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev    asprintf(&buff, "%s bw_costly_%s -m quota2 ! --quota %" PRId64" --name %s", opFlag, costName, quota,
4608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall             costName);
4618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res = buff;
4628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(buff);
4630dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
4640dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
4650dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
46626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::prepCostlyIface(const char *ifn, QuotaType quotaType) {
4670dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char cmd[MAX_CMD_LEN];
4680031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    int res = 0, res1, res2;
4698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int ruleInsertPos = 1;
4700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::string costString;
4710dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    const char *costCString;
4720dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
4730dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /* The "-N costly" is created upfront, no need to handle it here. */
47426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    switch (quotaType) {
47526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaUnique:
4767e51cde19af016456fff750f745db8132f3124a5JP Abgrall        costString = "bw_costly_";
4770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costString += ifn;
4780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costCString = costString.c_str();
4790031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        /*
4807e51cde19af016456fff750f745db8132f3124a5JP Abgrall         * Flush the bw_costly_<iface> is allowed to fail in case it didn't exist.
4810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         * Creating a new one is allowed to fail in case it existed.
4820031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         * This helps with netd restarts.
4830031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall         */
4840031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        snprintf(cmd, sizeof(cmd), "-F %s", costCString);
485a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        res1 = runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide);
4860dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        snprintf(cmd, sizeof(cmd), "-N %s", costCString);
487a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        res2 = runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide);
4880031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        res = (res1 && res2) || (!res1 && !res2);
4890031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
4907e51cde19af016456fff750f745db8132f3124a5JP Abgrall        snprintf(cmd, sizeof(cmd), "-A %s -j bw_penalty_box", costCString);
491a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        res |= runIpxtablesCmd(cmd, IptJumpNoAdd);
49226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
49326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaShared:
4947e51cde19af016456fff750f745db8132f3124a5JP Abgrall        costCString = "bw_costly_shared";
49526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
4960031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    default:
4970031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("Unexpected quotatype %d", quotaType);
4980031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
4990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
5000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
5018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (globalAlertBytes) {
5028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        /* The alert rule comes 1st */
5038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        ruleInsertPos = 2;
5048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
5050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
5060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_INPUT -i %s --jump %s", ifn, costCString);
507a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide);
5080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
5090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-I bw_INPUT %d -i %s --jump %s", ruleInsertPos, ifn, costCString);
510a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    res |= runIpxtablesCmd(cmd, IptJumpNoAdd);
5110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
5120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_OUTPUT -o %s --jump %s", ifn, costCString);
513a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide);
5140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
5150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-I bw_OUTPUT %d -o %s --jump %s", ruleInsertPos, ifn, costCString);
516a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    res |= runIpxtablesCmd(cmd, IptJumpNoAdd);
51758a944859781731de308939e914ea3ba27465f25Erik Kline
51858a944859781731de308939e914ea3ba27465f25Erik Kline    snprintf(cmd, sizeof(cmd), "-D bw_FORWARD -o %s --jump %s", ifn, costCString);
51958a944859781731de308939e914ea3ba27465f25Erik Kline    runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide);
52058a944859781731de308939e914ea3ba27465f25Erik Kline    snprintf(cmd, sizeof(cmd), "-A bw_FORWARD -o %s --jump %s", ifn, costCString);
52158a944859781731de308939e914ea3ba27465f25Erik Kline    res |= runIpxtablesCmd(cmd, IptJumpNoAdd);
52258a944859781731de308939e914ea3ba27465f25Erik Kline
5230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
5240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
5250dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
52626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::cleanupCostlyIface(const char *ifn, QuotaType quotaType) {
5270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char cmd[MAX_CMD_LEN];
5280dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
5290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::string costString;
5300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    const char *costCString;
5310dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
53226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    switch (quotaType) {
53326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaUnique:
5347e51cde19af016456fff750f745db8132f3124a5JP Abgrall        costString = "bw_costly_";
5350dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costString += ifn;
5360dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        costCString = costString.c_str();
53726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
53826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    case QuotaShared:
5397e51cde19af016456fff750f745db8132f3124a5JP Abgrall        costCString = "bw_costly_shared";
54026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        break;
5410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    default:
5420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("Unexpected quotatype %d", quotaType);
5430031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
5440dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
5450dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
5460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D bw_INPUT -i %s --jump %s", ifn, costCString);
547a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    res |= runIpxtablesCmd(cmd, IptJumpNoAdd);
54858a944859781731de308939e914ea3ba27465f25Erik Kline    for (const auto tableName : {LOCAL_OUTPUT, LOCAL_FORWARD}) {
54958a944859781731de308939e914ea3ba27465f25Erik Kline        snprintf(cmd, sizeof(cmd), "-D %s -o %s --jump %s", tableName, ifn, costCString);
55058a944859781731de308939e914ea3ba27465f25Erik Kline        res |= runIpxtablesCmd(cmd, IptJumpNoAdd);
55158a944859781731de308939e914ea3ba27465f25Erik Kline    }
5520dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
5537e51cde19af016456fff750f745db8132f3124a5JP Abgrall    /* The "-N bw_costly_shared" is created upfront, no need to handle it here. */
55426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    if (quotaType == QuotaUnique) {
5550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        snprintf(cmd, sizeof(cmd), "-F %s", costCString);
556a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        res |= runIpxtablesCmd(cmd, IptJumpNoAdd);
557a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall        snprintf(cmd, sizeof(cmd), "-X %s", costCString);
558a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        res |= runIpxtablesCmd(cmd, IptJumpNoAdd);
559fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
560fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    return res;
561fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall}
5624a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5630dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceSharedQuota(const char *iface, int64_t maxBytes) {
5644a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char ifn[MAX_IFACENAME_LEN];
565fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res = 0;
56626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string quotaCmd;
5678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    std::string ifaceName;
5688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    ;
569bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    const char *costName = "shared";
57026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::list<std::string>::iterator it;
5714a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!maxBytes) {
5738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        /* Don't talk about -1, deprecate it. */
5745ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
5758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
5768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
57769261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(iface))
57869261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall        return -1;
57926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
5805ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
58126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
58226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
58326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    ifaceName = ifn;
5844a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5854a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    if (maxBytes == -1) {
586fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        return removeInterfaceSharedQuota(ifn);
5874a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
5884a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
5894a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    /* Insert ingress quota. */
5900dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) {
5910dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (*it == ifaceName)
592fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            break;
5934a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
594fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
5950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == sharedQuotaIfaces.end()) {
59626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= prepCostlyIface(ifn, QuotaShared);
5970dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (sharedQuotaIfaces.empty()) {
5980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes);
599a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall            res |= runIpxtablesCmd(quotaCmd.c_str(), IptJumpReject);
6004a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            if (res) {
6015ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block                ALOGE("Failed set quota rule");
602fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall                goto fail;
6034a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            }
604fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            sharedQuotaBytes = maxBytes;
605fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
6060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        sharedQuotaIfaces.push_front(ifaceName);
607fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
608fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
609fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
610fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    if (maxBytes != sharedQuotaBytes) {
6118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res |= updateQuota(costName, maxBytes);
612fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (res) {
6135ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed update quota for %s", costName);
614fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            goto fail;
615fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
616fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        sharedQuotaBytes = maxBytes;
6174a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
6184a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return 0;
619fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
620fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    fail:
6214a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    /*
6224a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall     * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse
6234a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall     * rules in the kernel to see which ones need cleaning up.
624fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall     * For now callers needs to choose if they want to "ndc bandwidth enable"
625fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall     * which resets everything.
6264a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall     */
627fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    removeInterfaceSharedQuota(ifn);
6284a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return -1;
6294a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
6304a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
6318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall/* It will also cleanup any shared alerts */
632fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeInterfaceSharedQuota(const char *iface) {
6334a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    char ifn[MAX_IFACENAME_LEN];
634fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    int res = 0;
63526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string ifaceName;
6360dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    std::list<std::string>::iterator it;
637bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall    const char *costName = "shared";
6384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
63969261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(iface))
64069261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall        return -1;
6418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
6425ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
64326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
64426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
6458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    ifaceName = ifn;
64626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
6470dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) {
6480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (*it == ifaceName)
649fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            break;
6504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
6510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == sharedQuotaIfaces.end()) {
6525ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No such iface %s to delete", ifn);
653fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        return -1;
6544a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
655fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
65626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= cleanupCostlyIface(ifn, QuotaShared);
6570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    sharedQuotaIfaces.erase(it);
658fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
6590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (sharedQuotaIfaces.empty()) {
660fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        std::string quotaCmd;
661bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall        quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, sharedQuotaBytes);
662a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        res |= runIpxtablesCmd(quotaCmd.c_str(), IptJumpReject);
6638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        sharedQuotaBytes = 0;
6648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (sharedAlertBytes) {
6658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            removeSharedAlert();
6668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            sharedAlertBytes = 0;
6678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
668fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall    }
6694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return res;
6704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
6710dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6720dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceQuota(const char *iface, int64_t maxBytes) {
6730dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char ifn[MAX_IFACENAME_LEN];
6740dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
67526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string ifaceName;
67626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    const char *costName;
67726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::list<QuotaInfo>::iterator it;
67826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string quotaCmd;
6790dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
68069261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(iface))
6810b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        return -1;
6820b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich
6838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!maxBytes) {
6848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        /* Don't talk about -1, deprecate it. */
6855ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
6868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
6878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
6880dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (maxBytes == -1) {
68926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return removeInterfaceQuota(iface);
6900dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
6910dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
6928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
6935ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
69426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
69526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
69626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    ifaceName = ifn;
69726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    costName = iface;
69826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall
6990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /* Insert ingress quota. */
7000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
7018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == ifaceName)
7020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            break;
7030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
7040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7050dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == quotaIfaces.end()) {
706e478873947f995e44e8c559342462c177a420ae0JP Abgrall        /* Preparing the iface adds a penalty/happy box check */
70726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        res |= prepCostlyIface(ifn, QuotaUnique);
708baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        /*
709e478873947f995e44e8c559342462c177a420ae0JP Abgrall         * The rejecting quota limit should go after the penalty/happy box checks
710baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         * or else a naughty app could just eat up the quota.
711baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         * So we append here.
712baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         */
713109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        quotaCmd = makeIptablesQuotaCmd(IptOpAppend, costName, maxBytes);
714a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        res |= runIpxtablesCmd(quotaCmd.c_str(), IptJumpReject);
7150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (res) {
7165ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed set quota rule");
7170dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            goto fail;
7180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
7190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        quotaIfaces.push_front(QuotaInfo(ifaceName, maxBytes, 0));
7210dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7220dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    } else {
7238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res |= updateQuota(costName, maxBytes);
7240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (res) {
7255ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Failed update quota for %s", iface);
7260dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            goto fail;
7270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
7288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        it->quota = maxBytes;
7290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
7300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return 0;
7310dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7320dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    fail:
7330dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /*
7340dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse
7350dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * rules in the kernel to see which ones need cleaning up.
7360dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * For now callers needs to choose if they want to "ndc bandwidth enable"
7370dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     * which resets everything.
7380dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall     */
7390dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    removeInterfaceSharedQuota(ifn);
7400dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return -1;
7410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
7420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceSharedQuota(int64_t *bytes) {
7448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return getInterfaceQuota("shared", bytes);
7458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
7468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceQuota(const char *costName, int64_t *bytes) {
7488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    FILE *fp;
7498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *fname;
7508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int scanRes;
7518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
75269261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(costName))
7530b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        return -1;
7540b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich
7558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&fname, "/proc/net/xt_quota/%s", costName);
75653ea9cadf6cc5f8be1c16b5b6b660cd7366fd3f0Nick Kralevich    fp = fopen(fname, "re");
7578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(fname);
7588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!fp) {
7595ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Reading quota %s failed (%s)", costName, strerror(errno));
7608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
7618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
762ca0b5e275e7405ff4109e83c1cc1c36aabc8167bMark Salyzyn    scanRes = fscanf(fp, "%" SCNd64, bytes);
7637776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev    ALOGV("Read quota res=%d bytes=%" PRId64, scanRes, *bytes);
7648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fclose(fp);
7658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return scanRes == 1 ? 0 : -1;
7668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
7678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
7680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::removeInterfaceQuota(const char *iface) {
7690dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    char ifn[MAX_IFACENAME_LEN];
7710dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    int res = 0;
77226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::string ifaceName;
77326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    std::list<QuotaInfo>::iterator it;
7740dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
77569261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(iface))
7760b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        return -1;
7778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) {
7785ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN);
77926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall        return -1;
78026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    }
78126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    ifaceName = ifn;
7820dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7830dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
7848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == ifaceName)
7850dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            break;
7860dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
7870dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7880dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    if (it == quotaIfaces.end()) {
7895ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No such iface %s to delete", ifn);
7900dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        return -1;
7910dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    }
7920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    /* This also removes the quota command of CostlyIface chain. */
79426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall    res |= cleanupCostlyIface(ifn, QuotaUnique);
7950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7960dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    quotaIfaces.erase(it);
7970dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
7980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    return res;
7990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}
8008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::updateQuota(const char *quotaName, int64_t bytes) {
8028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    FILE *fp;
8038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *fname;
8048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
80569261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(quotaName)) {
8060b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        ALOGE("updateQuota: Invalid quotaName \"%s\"", quotaName);
8070b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        return -1;
8080b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich    }
8090b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich
8108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&fname, "/proc/net/xt_quota/%s", quotaName);
81153ea9cadf6cc5f8be1c16b5b6b660cd7366fd3f0Nick Kralevich    fp = fopen(fname, "we");
8128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(fname);
8138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!fp) {
8145ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Updating quota %s failed (%s)", quotaName, strerror(errno));
8158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8177776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev    fprintf(fp, "%" PRId64"\n", bytes);
8188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    fclose(fp);
8198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return 0;
8208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
8218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesAlertCmd(IptOp op, const char *alertName, int64_t bytes) {
8238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
8248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    const char *opFlag;
8258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
8268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    switch (op) {
8288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpInsert:
8298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-I";
8308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
831109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall    case IptOpAppend:
832109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        opFlag = "-A";
833109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        break;
8348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpReplace:
8358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-R";
8368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
8378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    default:
8388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    case IptOpDelete:
8398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        opFlag = "-D";
8408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        break;
8418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
84392009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_INPUT",
844c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich        bytes, alertName);
845a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    res |= runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd);
8468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertQuotaCmd);
84792009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_OUTPUT",
848c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich        bytes, alertName);
849a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    res |= runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd);
8508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertQuotaCmd);
8518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
8528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
8538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
854c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::runIptablesAlertFwdCmd(IptOp op, const char *alertName, int64_t bytes) {
855c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    int res = 0;
856c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *opFlag;
8578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
858c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
859c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    switch (op) {
860c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    case IptOpInsert:
861c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        opFlag = "-I";
862c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        break;
863109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall    case IptOpAppend:
864109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        opFlag = "-A";
865109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        break;
866c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    case IptOpReplace:
867c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        opFlag = "-R";
868c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        break;
869c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    default:
870c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    case IptOpDelete:
871c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        opFlag = "-D";
872c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        break;
873c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
874c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
87592009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_FORWARD",
876c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich        bytes, alertName);
877a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    res = runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd);
878c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    free(alertQuotaCmd);
879c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    return res;
880c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall}
881c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
882c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlert(int64_t bytes) {
883c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
8848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
8858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
8868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
8875ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
8888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
8898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (globalAlertBytes) {
8918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res = updateQuota(alertName, bytes);
8928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    } else {
8938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res = runIptablesAlertCmd(IptOpInsert, alertName, bytes);
894c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        if (globalAlertTetherCount) {
8953fb42e026ffebab2c8f282e42501040121e32d83Steve Block            ALOGV("setGlobalAlert for %d tether", globalAlertTetherCount);
896c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            res |= runIptablesAlertFwdCmd(IptOpInsert, alertName, bytes);
897c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        }
8988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
8998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    globalAlertBytes = bytes;
9008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
9018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
9028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
903c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlertInForwardChain(void) {
904c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
905c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    int res = 0;
906c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
907c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    globalAlertTetherCount++;
9083fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("setGlobalAlertInForwardChain(): %d tether", globalAlertTetherCount);
909c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
910c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /*
911c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is no globalAlert active we are done.
912c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is an active globalAlert but this is not the 1st
913c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * tether, we are also done.
914c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     */
915c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!globalAlertBytes || globalAlertTetherCount != 1) {
916c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return 0;
917c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
918c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
919c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /* We only add the rule if this was the 1st tether added. */
920c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    res = runIptablesAlertFwdCmd(IptOpInsert, alertName, globalAlertBytes);
921c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    return res;
922c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall}
923c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
9248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeGlobalAlert(void) {
9258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
926c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
9278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
9288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!globalAlertBytes) {
9305ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set");
9318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    res = runIptablesAlertCmd(IptOpDelete, alertName, globalAlertBytes);
934c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (globalAlertTetherCount) {
935c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        res |= runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes);
936c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
9378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    globalAlertBytes = 0;
9388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
9398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
9408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
941c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::removeGlobalAlertInForwardChain(void) {
942c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    int res = 0;
943c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    const char *alertName = ALERT_GLOBAL_NAME;
944c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
945c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!globalAlertTetherCount) {
9465ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set");
947c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return -1;
948c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
949c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
950c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    globalAlertTetherCount--;
951c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /*
952c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is no globalAlert active we are done.
953c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * If there is an active globalAlert but there are more
954c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     * tethers, we are also done.
955c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall     */
956c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!globalAlertBytes || globalAlertTetherCount >= 1) {
957c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return 0;
958c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
959c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
960c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    /* We only detete the rule if this was the last tether removed. */
961c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    res = runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes);
962c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    return res;
963c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall}
964c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
9658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setSharedAlert(int64_t bytes) {
9668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!sharedQuotaBytes) {
9675ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Need to have a prior shared quota set to set an alert");
9688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
9715ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
9728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return setCostlyAlert("shared", bytes, &sharedAlertBytes);
9758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
9768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeSharedAlert(void) {
9788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return removeCostlyAlert("shared", &sharedAlertBytes);
9798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
9808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setInterfaceAlert(const char *iface, int64_t bytes) {
9828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    std::list<QuotaInfo>::iterator it;
9838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
98469261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(iface)) {
9850b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        ALOGE("setInterfaceAlert: Invalid iface \"%s\"", iface);
9860b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        return -1;
9870b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich    }
9880b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich
9898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
9905ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
9918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
9928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
9948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == iface)
9958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
9968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
9978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
9988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (it == quotaIfaces.end()) {
9995ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Need to have a prior interface quota set to set an alert");
10008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
10018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
10028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
10038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return setCostlyAlert(iface, bytes, &it->alert);
10048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
10058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
10068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeInterfaceAlert(const char *iface) {
10078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    std::list<QuotaInfo>::iterator it;
10088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
100969261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(iface)) {
10100b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        ALOGE("removeInterfaceAlert: Invalid iface \"%s\"", iface);
10110b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        return -1;
10120b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich    }
10130b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich
10148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) {
10158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (it->ifaceName == iface)
10168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            break;
10178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
10188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
10198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (it == quotaIfaces.end()) {
10205ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set for interface %s", iface);
10218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
10228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
10238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
10248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return removeCostlyAlert(iface, &it->alert);
10258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
10268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
10278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes) {
10288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
1029109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall    char *chainName;
10308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
10318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertName;
10328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
103369261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(costName)) {
10340b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        ALOGE("setCostlyAlert: Invalid costName \"%s\"", costName);
10350b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        return -1;
10360b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich    }
10370b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich
10388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!bytes) {
10395ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid bytes value. 1..max_int64.");
10408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
10418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
10428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    asprintf(&alertName, "%sAlert", costName);
10438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (*alertBytes) {
10448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        res = updateQuota(alertName, *alertBytes);
10458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    } else {
10467e51cde19af016456fff750f745db8132f3124a5JP Abgrall        asprintf(&chainName, "bw_costly_%s", costName);
1047109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-A", chainName, bytes, alertName);
1048a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall        res |= runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd);
10498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        free(alertQuotaCmd);
1050109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall        free(chainName);
10518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
10528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    *alertBytes = bytes;
10538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertName);
10548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
10558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
10568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
10578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeCostlyAlert(const char *costName, int64_t *alertBytes) {
10588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertQuotaCmd;
10598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *chainName;
10608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    char *alertName;
10618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    int res = 0;
10628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
106369261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(costName)) {
10640b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        ALOGE("removeCostlyAlert: Invalid costName \"%s\"", costName);
10650b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich        return -1;
10660b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich    }
10670b2b9021ee27af2449c433fa13ed5c57e55dd816Nick Kralevich
10688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    if (!*alertBytes) {
10695ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("No prior alert set for %s alert", costName);
10708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        return -1;
10718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    }
10728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1073a9d791f48e3472400ffad73dca88c28fb2f7aaa7Jesper Hansson    asprintf(&alertName, "%sAlert", costName);
10747e51cde19af016456fff750f745db8132f3124a5JP Abgrall    asprintf(&chainName, "bw_costly_%s", costName);
107592009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall    asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-D", chainName, *alertBytes, alertName);
1076a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall    res |= runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd);
10778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertQuotaCmd);
10788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(chainName);
10798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
10808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    *alertBytes = 0;
10818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    free(alertName);
10828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall    return res;
10838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall}
1084db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
10857364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colittivoid BandwidthController::addStats(TetherStatsList& statsList, const TetherStats& stats) {
10867364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti    for (TetherStats& existing : statsList) {
10877364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti        if (existing.addStatsIfMatch(stats)) {
10887364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti            return;
10897364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti        }
10907364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti    }
10917364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti    // No match. Insert a new interface pair.
10927364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti    statsList.push_back(stats);
10937364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti}
10947364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti
1095db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/*
1096db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Parse the ptks and bytes out of:
1097baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall *   Chain natctrl_tether_counters (4 references)
1098baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall *       pkts      bytes target     prot opt in     out     source               destination
1099f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall *         26     2373 RETURN     all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0
1100f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall *         27     2002 RETURN     all  --  rmnet0 wlan0   0.0.0.0/0            0.0.0.0/0
1101f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall *       1040   107471 RETURN     all  --  bt-pan rmnet0  0.0.0.0/0            0.0.0.0/0
1102f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall *       1450  1708806 RETURN     all  --  rmnet0 bt-pan  0.0.0.0/0            0.0.0.0/0
110326c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti * or:
110426c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti *   Chain natctrl_tether_counters (0 references)
110526c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti *       pkts      bytes target     prot opt in     out     source               destination
110626c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti *          0        0 RETURN     all      wlan0  rmnet_data0  ::/0                 ::/0
110726c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti *          0        0 RETURN     all      rmnet_data0 wlan0   ::/0                 ::/0
110826c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti *
1109f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall * It results in an error if invoked and no tethering counter rules exist. The constraint
1110f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall * helps detect complete parsing failure.
1111db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */
11127364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colittiint BandwidthController::addForwardChainStats(const TetherStats& filter,
11137364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti                                              TetherStatsList& statsList, FILE *fp,
11147364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti                                              std::string &extraProcessingInfo) {
1115db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    int res;
1116db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN];
1117db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char iface0[MAX_IPT_OUTPUT_LINE_LEN];
1118db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char iface1[MAX_IPT_OUTPUT_LINE_LEN];
1119db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char rest[MAX_IPT_OUTPUT_LINE_LEN];
1120db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1121baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    TetherStats stats;
1122db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char *buffPtr;
1123db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    int64_t packets, bytes;
1124f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    int statsFound = 0;
1125baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
1126baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    bool filterPair = filter.intIface[0] && filter.extIface[0];
1127baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
1128baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    char *filterMsg = filter.getStatsLine();
1129baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    ALOGV("filter: %s",  filterMsg);
1130baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    free(filterMsg);
1131baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
1132baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    stats = filter;
1133db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1134db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) {
1135db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        /* Clean up, so a failed parse can still print info */
1136db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        iface0[0] = iface1[0] = rest[0] = packets = bytes = 0;
113726c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        if (strstr(buffPtr, "0.0.0.0")) {
113826c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti            // IPv4 has -- indicating what to do with fragments...
113926c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti            //       26     2373 RETURN     all  --  wlan0  rmnet0  0.0.0.0/0            0.0.0.0/0
114026c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti            res = sscanf(buffPtr, "%" SCNd64" %" SCNd64" RETURN all -- %s %s 0.%s",
114126c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti                    &packets, &bytes, iface0, iface1, rest);
114226c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        } else {
114326c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti            // ... but IPv6 does not.
114426c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti            //       26     2373 RETURN     all      wlan0  rmnet0  ::/0                 ::/0
114526c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti            res = sscanf(buffPtr, "%" SCNd64" %" SCNd64" RETURN all %s %s ::/%s",
114626c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti                    &packets, &bytes, iface0, iface1, rest);
114726c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        }
11487776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev        ALOGV("parse res=%d iface0=<%s> iface1=<%s> pkts=%" PRId64" bytes=%" PRId64" rest=<%s> orig line=<%s>", res,
1149db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall             iface0, iface1, packets, bytes, rest, buffPtr);
1150a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall        extraProcessingInfo += buffPtr;
1151a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall
1152db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        if (res != 5) {
1153db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            continue;
1154db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        }
1155baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        /*
1156baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         * The following assumes that the 1st rule has in:extIface out:intIface,
1157baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         * which is what NatController sets up.
1158baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         * If not filtering, the 1st match rx, and sets up the pair for the tx side.
1159baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         */
1160baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        if (filter.intIface[0] && filter.extIface[0]) {
1161baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            if (filter.intIface == iface0 && filter.extIface == iface1) {
11627776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev                ALOGV("2Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
1163baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.rxPackets = packets;
1164baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.rxBytes = bytes;
1165baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            } else if (filter.intIface == iface1 && filter.extIface == iface0) {
11667776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev                ALOGV("2Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
1167baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.txPackets = packets;
1168baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.txBytes = bytes;
1169baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            }
1170baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        } else if (filter.intIface[0] || filter.extIface[0]) {
1171baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            if (filter.intIface == iface0 || filter.extIface == iface1) {
11727776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev                ALOGV("1Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
1173baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.intIface = iface0;
1174baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.extIface = iface1;
1175baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.rxPackets = packets;
1176baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.rxBytes = bytes;
1177baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            } else if (filter.intIface == iface1 || filter.extIface == iface0) {
11787776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev                ALOGV("1Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
1179baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.intIface = iface1;
1180baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.extIface = iface0;
1181baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.txPackets = packets;
1182baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.txBytes = bytes;
1183baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            }
1184baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        } else /* if (!filter.intFace[0] && !filter.extIface[0]) */ {
1185baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            if (!stats.intIface[0]) {
11867776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev                ALOGV("0Filter RX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
1187baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.intIface = iface0;
1188baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.extIface = iface1;
1189baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.rxPackets = packets;
1190baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.rxBytes = bytes;
1191baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            } else if (stats.intIface == iface1 && stats.extIface == iface0) {
11927776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev                ALOGV("0Filter TX iface_in=%s iface_out=%s rx_bytes=%" PRId64" rx_packets=%" PRId64" ", iface0, iface1, bytes, packets);
1193baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.txPackets = packets;
1194baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats.txBytes = bytes;
1195baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            }
1196baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        }
1197baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        if (stats.rxBytes != -1 && stats.txBytes != -1) {
11987776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev            ALOGV("rx_bytes=%" PRId64" tx_bytes=%" PRId64" filterPair=%d", stats.rxBytes, stats.txBytes, filterPair);
11997364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti            addStats(statsList, stats);
1200baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            if (filterPair) {
1201baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                return 0;
1202baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            } else {
12037364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti                statsFound++;
1204baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                stats = filter;
1205baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            }
1206db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        }
1207db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1208f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall
1209f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    /* It is always an error to find only one side of the stats. */
1210f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    /* It is an error to find nothing when not filtering. */
1211f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    if (((stats.rxBytes == -1) != (stats.txBytes == -1)) ||
1212f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        (!statsFound && !filterPair)) {
1213f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        return -1;
1214baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
1215f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    return 0;
1216db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
1217db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1218baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrallchar *BandwidthController::TetherStats::getStatsLine(void) const {
1219db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char *msg;
12207776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev    asprintf(&msg, "%s %s %" PRId64" %" PRId64" %" PRId64" %" PRId64, intIface.c_str(), extIface.c_str(),
1221db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            rxBytes, rxPackets, txBytes, txPackets);
1222db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    return msg;
1223db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
1224db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
122526c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colittistd::string getTetherStatsCommand(const char *binary) {
1226db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    /*
1227db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * Why not use some kind of lib to talk to iptables?
1228db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * Because the only libs are libiptc and libip6tc in iptables, and they are
1229db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * not easy to use. They require the known iptables match modules to be
1230db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * preloaded/linked, and require apparently a lot of wrapper code to get
1231db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     * the wanted info.
1232db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall     */
123326c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti    return android::base::StringPrintf("%s -nvx -w -L %s", binary,
123426c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti                                       NatController::LOCAL_TETHER_COUNTERS_CHAIN);
123526c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti}
12367364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti
123726c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colittiint BandwidthController::getTetherStats(SocketClient *cli, TetherStats& filter,
123826c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti                                        std::string &extraProcessingInfo) {
123926c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti    int res = 0;
124026c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti    std::string fullCmd;
124126c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti    FILE *iptOutput;
124226c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti
124326c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti    TetherStatsList statsList;
124426c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti
124526c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti    for (const auto binary : {IPTABLES_PATH, IP6TABLES_PATH}) {
124626c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        fullCmd = getTetherStatsCommand(binary);
124726c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        iptOutput = popenFunction(fullCmd.c_str(), "r");
124826c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        if (!iptOutput) {
124926c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti                ALOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno));
125026c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti                extraProcessingInfo += "Failed to run iptables.";
125126c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti            return -1;
125226c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        }
125326c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti
125426c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        res = addForwardChainStats(filter, statsList, iptOutput, extraProcessingInfo);
125526c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        pclose(iptOutput);
125626c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        if (res != 0) {
125726c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti            return res;
125826c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti        }
125926c9132b8b5993f8edbb999696e18fa6469d6759Lorenzo Colitti    }
1260db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
12617364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti    if (filter.intIface[0] && filter.extIface[0] && statsList.size() == 1) {
12627364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti        cli->sendMsg(ResponseCode::TetheringStatsResult, statsList[0].getStatsLine(), false);
12637364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti    } else {
12647364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti        for (const auto& stats: statsList) {
12657364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti            cli->sendMsg(ResponseCode::TetheringStatsListResult, stats.getStatsLine(), false);
12667364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti        }
12677364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti        if (res == 0) {
12687364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti            cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
12697364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti        }
12707364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti    }
12717364b75ca058d34875eb3567a57bfd9c03628129Lorenzo Colitti
1272db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    return res;
1273db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
12740e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall
12750e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrallvoid BandwidthController::flushExistingCostlyTables(bool doClean) {
12760e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    std::string fullCmd;
12770e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    FILE *iptOutput;
12780e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall
12790e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    /* Only lookup ip4 table names as ip6 will have the same tables ... */
12800e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    fullCmd = IPTABLES_PATH;
128199b40503edccae74d0917b9d1e17a5939ac7193bYusuke Sato    fullCmd += " -w -S";
128286a4798264c9421cb02bc69836a323d918f73779Lorenzo Colitti    iptOutput = popenFunction(fullCmd.c_str(), "r");
12830e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    if (!iptOutput) {
12840e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall            ALOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno));
12850e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        return;
12860e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    }
12870e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    /* ... then flush/clean both ip4 and ip6 iptables. */
12880e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    parseAndFlushCostlyTables(iptOutput, doClean);
12890e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    pclose(iptOutput);
12900e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall}
12910e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall
12920e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrallvoid BandwidthController::parseAndFlushCostlyTables(FILE *fp, bool doRemove) {
12930e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    int res;
12940e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN];
12950e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    char costlyIfaceName[MAX_IPT_OUTPUT_LINE_LEN];
12960e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    char cmd[MAX_CMD_LEN];
12970e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    char *buffPtr;
12980e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall
12990e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) {
13000e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        costlyIfaceName[0] = '\0';   /* So that debugging output always works */
13010e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        res = sscanf(buffPtr, "-N bw_costly_%s", costlyIfaceName);
13020e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        ALOGV("parse res=%d costly=<%s> orig line=<%s>", res,
13030e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall            costlyIfaceName, buffPtr);
13040e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        if (res != 1) {
13050e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall            continue;
13060e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        }
13070e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        /* Exclusions: "shared" is not an ifacename */
13080e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        if (!strcmp(costlyIfaceName, "shared")) {
13090e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall            continue;
13100e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        }
13110e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall
13120e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        snprintf(cmd, sizeof(cmd), "-F bw_costly_%s", costlyIfaceName);
13130e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide);
13140e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        if (doRemove) {
13150e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall            snprintf(cmd, sizeof(cmd), "-X bw_costly_%s", costlyIfaceName);
13160e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall            runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide);
13170e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall        }
13180e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall    }
13190e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall}
1320