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