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