BandwidthController.cpp revision c4bbfa247dbe4dda17e28694d49afd3ec0b06bad
14a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall/* 24a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Copyright (C) 2011 The Android Open Source Project 34a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 44a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Licensed under the Apache License, Version 2.0 (the "License"); 54a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * you may not use this file except in compliance with the License. 64a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * You may obtain a copy of the License at 74a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 84a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * http://www.apache.org/licenses/LICENSE-2.0 94a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 104a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Unless required by applicable law or agreed to in writing, software 114a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * distributed under the License is distributed on an "AS IS" BASIS, 124a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * See the License for the specific language governing permissions and 144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * limitations under the License. 154a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 164a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 17db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall// #define LOG_NDEBUG 0 18db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 19db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* 20db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * The CommandListener, FrameworkListener don't allow for 21db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * multiple calls in parallel to reach the BandwidthController. 22db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * If they ever were to allow it, then netd/ would need some tweaking. 23db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */ 24db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <errno.h> 264a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <fcntl.h> 27db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall#include <stdio.h> 288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <stdlib.h> 294a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <string.h> 304a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 314a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/socket.h> 324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/stat.h> 334a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/types.h> 344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/wait.h> 354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 364a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/netlink.h> 374a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/rtnetlink.h> 384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/pkt_sched.h> 394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#define LOG_TAG "BandwidthController" 414a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/log.h> 424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/properties.h> 434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 44c4bbfa247dbe4dda17e28694d49afd3ec0b06badGlenn Kastenextern "C" int logwrap(int argc, const char **argv); 459e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrallextern "C" int system_nosh(const char *command); 464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include "BandwidthController.h" 484ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#include "oem_iptables_hook.h" 494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 50db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* Alphabetical */ 51c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich#define ALERT_IPT_TEMPLATE "%s %s %s -m quota2 ! --quota %lld --name %s" 52db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int BandwidthController::ALERT_RULE_POS_IN_COSTLY_CHAIN = 4; 53c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallconst char BandwidthController::ALERT_GLOBAL_NAME[] = "globalAlert"; 54db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char BandwidthController::IP6TABLES_PATH[] = "/system/bin/ip6tables"; 55db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char BandwidthController::IPTABLES_PATH[] = "/system/bin/iptables"; 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 6111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrallbool BandwidthController::useLogwrapCall = false; 624a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 634a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall/** 644a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Some comments about the rules: 654a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * Ordering 664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - when an interface is marked as costly it should be INSERTED into the INPUT/OUTPUT chains. 674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g. "-I INPUT -i rmnet0 --goto costly" 684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - quota'd rules in the costly chain should be before penalty_box lookups. 694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * global quota vs per interface quota 714a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - global quota for all costly interfaces uses a single costly chain: 724a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * . initial rules 73bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -N costly_shared 74bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I INPUT -i iface0 --goto costly_shared 75bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I OUTPUT -o iface0 --goto costly_shared 76bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I costly_shared -m quota \! --quota 500000 \ 77bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * --jump REJECT --reject-with icmp-net-prohibited 78bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A costly_shared --jump penalty_box 79bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A costly_shared -m owner --socket-exists 808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall * 814a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * . adding a new iface to this, E.g.: 82bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I INPUT -i iface1 --goto costly_shared 83bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I OUTPUT -o iface1 --goto costly_shared 844a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 854a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - quota per interface. This is achieve by having "costly" chains per quota. 864a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g. adding a new costly interface iface0 with its own quota: 874a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -N costly_iface0 884a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I INPUT -i iface0 --goto costly_iface0 894a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I OUTPUT -o iface0 --goto costly_iface0 90bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A costly_iface0 -m quota \! --quota 500000 \ 91bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * --jump REJECT --reject-with icmp-net-prohibited 92bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A costly_iface0 --jump penalty_box 934a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -A costly_iface0 -m owner --socket-exists 944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 954a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * penalty_box handling: 964a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - only one penalty_box for all interfaces 974a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g Adding an app: 98bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A penalty_box -m owner --uid-owner app_3 \ 99bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * --jump REJECT --reject-with icmp-net-prohibited 1004a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 101db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_CLEANUP_COMMANDS[] = { 1020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* Cleanup rules. */ 1030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-F", 1040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-t raw -F", 10539f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall /* TODO: If at some point we need more user chains than here, then we will need 10639f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall * a different cleanup approach. 10739f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall */ 108bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-X", /* Should normally only be costly_shared, penalty_box, and costly_<iface> */ 1090dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1104a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 111db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_SETUP_COMMANDS[] = { 1120dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* Created needed chains. */ 113bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-N costly_shared", 1140dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-N penalty_box", 1150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 117db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_BASIC_ACCOUNTING_COMMANDS[] = { 1180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-F INPUT", 1190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-A INPUT -i lo --jump ACCEPT", 1200dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-A INPUT -m owner --socket-exists", /* This is a tracking rule. */ 1210dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 1220dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-F OUTPUT", 1230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-A OUTPUT -o lo --jump ACCEPT", 1240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-A OUTPUT -m owner --socket-exists", /* This is a tracking rule. */ 1250dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 126bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-F costly_shared", 127bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-A costly_shared --jump penalty_box", 128bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-A costly_shared -m owner --socket-exists", /* This is a tracking rule. */ 1290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* TODO(jpa): Figure out why iptables doesn't correctly return from this 1300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * chain. For now, hack the chain exit with an ACCEPT. 1310dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall */ 132bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-A costly_shared --jump ACCEPT", 1330dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallBandwidthController::BandwidthController(void) { 1364a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char value[PROPERTY_VALUE_MAX]; 1374a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall property_get("persist.bandwidth.enable", value, "0"); 1394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (!strcmp(value, "1")) { 1404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall enableBandwidthControl(); 1414a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 1424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 14311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall property_get("persist.bandwidth.uselogwrap", value, "0"); 14411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall useLogwrapCall = !strcmp(value, "1"); 1454a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 1464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 14726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling) { 1480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 1498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 1503fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("runIpxtablesCmd(cmd=%s)", cmd); 15126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIptablesCmd(cmd, rejectHandling, IptIpV4); 15226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIptablesCmd(cmd, rejectHandling, IptIpV6); 1530dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 1540dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 1550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 15626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::StrncpyAndCheck(char *buffer, const char *src, size_t buffSize) { 15726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 15826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall memset(buffer, '\0', buffSize); // strncpy() is not filling leftover with '\0' 15926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall strncpy(buffer, src, buffSize); 16026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return buffer[buffSize - 1]; 16126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall} 16226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 1638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesCmd(const char *cmd, IptRejectOp rejectHandling, 1648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall IptIpVer iptVer) { 16526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall char buffer[MAX_CMD_LEN]; 1664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall const char *argv[MAX_CMD_ARGS]; 16726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall int argc = 0; 1684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char *next = buffer; 1694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char *tmp; 17011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall int res; 1714a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1720dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string fullCmd = cmd; 17326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 17426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (rejectHandling == IptRejectAdd) { 1750dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall fullCmd += " --jump REJECT --reject-with"; 17626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (iptVer) { 17726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case IptIpV4: 1788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fullCmd += " icmp-net-prohibited"; 1798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 18026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case IptIpV6: 1818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fullCmd += " icmp6-adm-prohibited"; 1828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 1830dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 1840dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 1850dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 18611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall fullCmd.insert(0, " "); 18711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall fullCmd.insert(0, iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH); 1884a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 18911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (!useLogwrapCall) { 1909e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall res = system_nosh(fullCmd.c_str()); 19111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } else { 19211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) { 1935ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("iptables command too long"); 1944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return -1; 1954a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 196fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 19711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall argc = 0; 19811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall while ((tmp = strsep(&next, " "))) { 19911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall argv[argc++] = tmp; 20011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (argc >= MAX_CMD_ARGS) { 2015ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("iptables argument overflow"); 20211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall return -1; 20311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 20411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 20511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall 20611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall argv[argc] = NULL; 207c4bbfa247dbe4dda17e28694d49afd3ec0b06badGlenn Kasten res = logwrap(argc, argv); 20811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 20911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (res) { 2105ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("runIptablesCmd(): failed %s res=%d", fullCmd.c_str(), res); 21111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 21211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall return res; 2134a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2154a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::enableBandwidthControl(void) { 216fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res; 2178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 218db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Let's pretend we started from scratch ... */ 2198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedQuotaIfaces.clear(); 2208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall quotaIfaces.clear(); 2218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall naughtyAppUids.clear(); 222db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall globalAlertBytes = 0; 223c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall globalAlertTetherCount = 0; 224db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall sharedQuotaBytes = sharedAlertBytes = 0; 225db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 226db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 227db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Some of the initialCommands are allowed to fail */ 228db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall runCommands(sizeof(IPT_CLEANUP_COMMANDS) / sizeof(char*), 229db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall IPT_CLEANUP_COMMANDS, RunCmdFailureOk); 230db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall runCommands(sizeof(IPT_SETUP_COMMANDS) / sizeof(char*), 231db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall IPT_SETUP_COMMANDS, RunCmdFailureOk); 232db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall res = runCommands(sizeof(IPT_BASIC_ACCOUNTING_COMMANDS) / sizeof(char*), 233db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall IPT_BASIC_ACCOUNTING_COMMANDS, RunCmdFailureBad); 2348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 2354ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo setupOemIptablesHook(); 2364ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 237fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 2384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2414a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::disableBandwidthControl(void) { 242db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* The IPT_CLEANUP_COMMANDS are allowed to fail. */ 243db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall runCommands(sizeof(IPT_CLEANUP_COMMANDS) / sizeof(char*), 244db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall IPT_CLEANUP_COMMANDS, RunCmdFailureOk); 2454ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo setupOemIptablesHook(); 246fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return 0; 2474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2484a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runCommands(int numCommands, const char *commands[], 2508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall RunCmdErrHandling cmdErrHandling) { 251fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 2523fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("runCommands(): %d commands", numCommands); 253fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) { 25426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res = runIpxtablesCmd(commands[cmdNum], IptRejectNoAdd); 25526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (res && cmdErrHandling != RunCmdFailureBad) 256fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 257fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 25826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return cmdErrHandling == RunCmdFailureBad ? res : 0; 259fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 260fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 2610dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallstd::string BandwidthController::makeIptablesNaughtyCmd(IptOp op, int uid) { 262fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string res; 2638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *buff; 2648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 265fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 266fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall switch (op) { 2678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 2688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 2698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 2708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 2718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 2728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 2738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 2748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 2758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 2768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 277fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 2788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&buff, "%s penalty_box -m owner --uid-owner %d", opFlag, uid); 2798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = buff; 2808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(buff); 281fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 282fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 283fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 284fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::addNaughtyApps(int numUids, char *appUids[]) { 28526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpAdd); 286fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 287fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 288fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeNaughtyApps(int numUids, char *appUids[]) { 28926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpRemove); 290fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 291fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 29226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::maninpulateNaughtyApps(int numUids, char *appStrUids[], NaughtyAppOp appOp) { 293fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall char cmd[MAX_CMD_LEN]; 294fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int uidNum; 29526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *failLogTemplate; 29626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall IptOp op; 297fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int appUids[numUids]; 29826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string naughtyCmd; 2998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 30026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (appOp) { 30126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case NaughtyAppOpAdd: 3028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall op = IptOpInsert; 3038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall failLogTemplate = "Failed to add app uid %d to penalty box."; 3048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 30526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case NaughtyAppOpRemove: 3068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall op = IptOpDelete; 3078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall failLogTemplate = "Failed to delete app uid %d from penalty box."; 3088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 30926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 31026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 311fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (uidNum = 0; uidNum < numUids; uidNum++) { 312fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall appUids[uidNum] = atol(appStrUids[uidNum]); 313fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (appUids[uidNum] == 0) { 3145ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE(failLogTemplate, appUids[uidNum]); 315fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_parse; 316fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 317fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 318fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 319fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (uidNum = 0; uidNum < numUids; uidNum++) { 32026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall naughtyCmd = makeIptablesNaughtyCmd(op, appUids[uidNum]); 32126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd)) { 3225ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE(failLogTemplate, appUids[uidNum]); 323fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_with_uidNum; 324fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 325fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 326fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return 0; 327fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 32826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_with_uidNum: 329fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* Try to remove the uid that failed in any case*/ 33026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall naughtyCmd = makeIptablesNaughtyCmd(IptOpDelete, appUids[uidNum]); 33126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd); 33226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_parse: 33326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 3344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 3354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 33626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallstd::string BandwidthController::makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota) { 337fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string res; 3388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *buff; 3398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 3400dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 3413fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("makeIptablesQuotaCmd(%d, %lld)", op, quota); 3420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 343fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall switch (op) { 3448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 3458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 3468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 3478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 3488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 3498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 3508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 3518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 3528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 3538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 354fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 3558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 356bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall // The requried IP version specific --jump REJECT ... will be added later. 3578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&buff, "%s costly_%s -m quota2 ! --quota %lld --name %s", opFlag, costName, quota, 3588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall costName); 3598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = buff; 3608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(buff); 3610dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 3620dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 3630dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 36426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::prepCostlyIface(const char *ifn, QuotaType quotaType) { 3650dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char cmd[MAX_CMD_LEN]; 3660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 3678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int ruleInsertPos = 1; 3680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string costString; 3690dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall const char *costCString; 3700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 3710dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* The "-N costly" is created upfront, no need to handle it here. */ 37226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (quotaType) { 37326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaUnique: 374bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costString = "costly_"; 3750dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costString += ifn; 3760dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costCString = costString.c_str(); 3770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-N %s", costCString); 37826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 3790dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-A %s -j penalty_box", costCString); 38026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 3810dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-A %s -m owner --socket-exists", costCString); 38226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 3830dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* TODO(jpa): Figure out why iptables doesn't correctly return from this 3840dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * chain. For now, hack the chain exit with an ACCEPT. 3850dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall */ 3860dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-A %s --jump ACCEPT", costCString); 38726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 38826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 38926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaShared: 390bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costCString = "costly_shared"; 39126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 3920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 3930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 3948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (globalAlertBytes) { 3958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* The alert rule comes 1st */ 3968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ruleInsertPos = 2; 3978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 3988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall snprintf(cmd, sizeof(cmd), "-I INPUT %d -i %s --goto %s", ruleInsertPos, ifn, costCString); 39926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 4008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall snprintf(cmd, sizeof(cmd), "-I OUTPUT %d -o %s --goto %s", ruleInsertPos, ifn, costCString); 40126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 4020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 4030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 4040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 40526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::cleanupCostlyIface(const char *ifn, QuotaType quotaType) { 4060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char cmd[MAX_CMD_LEN]; 4070dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 4080dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string costString; 4090dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall const char *costCString; 4100dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 41126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (quotaType) { 41226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaUnique: 413bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costString = "costly_"; 4140dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costString += ifn; 4150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costCString = costString.c_str(); 41626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 41726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaShared: 418bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costCString = "costly_shared"; 41926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 4200dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 4210dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 4220dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-D INPUT -i %s --goto %s", ifn, costCString); 42326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 4240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-D OUTPUT -o %s --goto %s", ifn, costCString); 42526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 4260dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 427bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall /* The "-N costly_shared" is created upfront, no need to handle it here. */ 42826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (quotaType == QuotaUnique) { 4290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-F %s", costCString); 43026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 431a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall snprintf(cmd, sizeof(cmd), "-X %s", costCString); 432a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 433fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 434fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 435fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 4364a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4370dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceSharedQuota(const char *iface, int64_t maxBytes) { 4384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char cmd[MAX_CMD_LEN]; 4394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char ifn[MAX_IFACENAME_LEN]; 440fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 44126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string quotaCmd; 4428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::string ifaceName; 4438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ; 444bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall const char *costName = "shared"; 44526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<std::string>::iterator it; 4464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!maxBytes) { 4488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* Don't talk about -1, deprecate it. */ 4495ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 4508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 4518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 45226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 4535ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 45426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 45526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 45626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 4574a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4584a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (maxBytes == -1) { 459fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return removeInterfaceSharedQuota(ifn); 4604a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 4614a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4624a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* Insert ingress quota. */ 4630dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) { 4640dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (*it == ifaceName) 465fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 4664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 467fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 4680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == sharedQuotaIfaces.end()) { 46926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= prepCostlyIface(ifn, QuotaShared); 4700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (sharedQuotaIfaces.empty()) { 4710dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes); 47226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd); 4734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (res) { 4745ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed set quota rule"); 475fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail; 4764a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 477fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = maxBytes; 478fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 4790dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall sharedQuotaIfaces.push_front(ifaceName); 480fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 481fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 482fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 483fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (maxBytes != sharedQuotaBytes) { 4848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= updateQuota(costName, maxBytes); 485fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (res) { 4865ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed update quota for %s", costName); 487fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail; 488fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 489fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = maxBytes; 4904a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 4914a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return 0; 492fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 493fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall fail: 4944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* 4954a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse 4964a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * rules in the kernel to see which ones need cleaning up. 497fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * For now callers needs to choose if they want to "ndc bandwidth enable" 498fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * which resets everything. 4994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 500fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall removeInterfaceSharedQuota(ifn); 5014a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return -1; 5024a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 5034a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 5048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall/* It will also cleanup any shared alerts */ 505fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeInterfaceSharedQuota(const char *iface) { 5064a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char ifn[MAX_IFACENAME_LEN]; 507fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 50826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 5090dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::list<std::string>::iterator it; 510bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall const char *costName = "shared"; 5114a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 5128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 5135ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 51426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 51526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 5168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ifaceName = ifn; 51726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 5180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) { 5190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (*it == ifaceName) 520fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 5214a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 5220dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == sharedQuotaIfaces.end()) { 5235ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No such iface %s to delete", ifn); 524fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return -1; 5254a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 526fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 52726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= cleanupCostlyIface(ifn, QuotaShared); 5280dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall sharedQuotaIfaces.erase(it); 529fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 5300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (sharedQuotaIfaces.empty()) { 531fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string quotaCmd; 532bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, sharedQuotaBytes); 53326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd); 5348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedQuotaBytes = 0; 5358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (sharedAlertBytes) { 5368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall removeSharedAlert(); 5378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedAlertBytes = 0; 5388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 539fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 5404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return res; 5414a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 5420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5430dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceQuota(const char *iface, int64_t maxBytes) { 5440dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char ifn[MAX_IFACENAME_LEN]; 5450dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 54626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 54726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *costName; 54826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<QuotaInfo>::iterator it; 54926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string quotaCmd; 5500dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!maxBytes) { 5528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* Don't talk about -1, deprecate it. */ 5535ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 5548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 5558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 5560dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (maxBytes == -1) { 55726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return removeInterfaceQuota(iface); 5580dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 5615ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 56226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 56326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 56426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 56526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall costName = iface; 56626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 5670dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* Insert ingress quota. */ 5680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 5698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == ifaceName) 5700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall break; 5710dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5720dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5730dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == quotaIfaces.end()) { 57426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= prepCostlyIface(ifn, QuotaUnique); 5750dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes); 57626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd); 5770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (res) { 5785ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed set quota rule"); 5790dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall goto fail; 5800dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5810dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall quotaIfaces.push_front(QuotaInfo(ifaceName, maxBytes, 0)); 5830dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5840dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } else { 5858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= updateQuota(costName, maxBytes); 5860dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (res) { 5875ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed update quota for %s", iface); 5880dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall goto fail; 5890dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall it->quota = maxBytes; 5910dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return 0; 5930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5940dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall fail: 5950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* 5960dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse 5970dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * rules in the kernel to see which ones need cleaning up. 5980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * For now callers needs to choose if they want to "ndc bandwidth enable" 5990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * which resets everything. 6000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall */ 6010dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall removeInterfaceSharedQuota(ifn); 6020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return -1; 6030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 6040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceSharedQuota(int64_t *bytes) { 6068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return getInterfaceQuota("shared", bytes); 6078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 6088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceQuota(const char *costName, int64_t *bytes) { 6108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall FILE *fp; 6118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *fname; 6128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int scanRes; 6138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&fname, "/proc/net/xt_quota/%s", costName); 6158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fp = fopen(fname, "r"); 6168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(fname); 6178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!fp) { 6185ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Reading quota %s failed (%s)", costName, strerror(errno)); 6198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 6208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 6218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall scanRes = fscanf(fp, "%lld", bytes); 6223fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("Read quota res=%d bytes=%lld", scanRes, *bytes); 6238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fclose(fp); 6248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return scanRes == 1 ? 0 : -1; 6258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 6268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::removeInterfaceQuota(const char *iface) { 6280dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char ifn[MAX_IFACENAME_LEN]; 6300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 63126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 63226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *costName; 63326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<QuotaInfo>::iterator it; 6340dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 6365ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 63726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 63826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 63926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 64026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall costName = iface; 6410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 6438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == ifaceName) 6440dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall break; 6450dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6460dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6470dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == quotaIfaces.end()) { 6485ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No such iface %s to delete", ifn); 6490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return -1; 6500dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6520dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* This also removes the quota command of CostlyIface chain. */ 65326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= cleanupCostlyIface(ifn, QuotaUnique); 6540dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaIfaces.erase(it); 6560dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 6580dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 6598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::updateQuota(const char *quotaName, int64_t bytes) { 6618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall FILE *fp; 6628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *fname; 6638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&fname, "/proc/net/xt_quota/%s", quotaName); 6658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fp = fopen(fname, "w"); 6668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(fname); 6678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!fp) { 6685ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Updating quota %s failed (%s)", quotaName, strerror(errno)); 6698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 6708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 6718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fprintf(fp, "%lld\n", bytes); 6728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fclose(fp); 6738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return 0; 6748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 6758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesAlertCmd(IptOp op, const char *alertName, int64_t bytes) { 6778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 6788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 679876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall const char *ifaceLimiting; 6808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 6818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall switch (op) { 6838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 6848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 6858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 6868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 6878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 6888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 6898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 6908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 6918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 6928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 6938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 6948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 695876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall ifaceLimiting = "! -i lo+"; 696876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "INPUT", 697c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich bytes, alertName); 6988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 6998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 700876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall ifaceLimiting = "! -o lo+"; 701876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "OUTPUT", 702c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich bytes, alertName); 7038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 7048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 7058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 7068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 708c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::runIptablesAlertFwdCmd(IptOp op, const char *alertName, int64_t bytes) { 709c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall int res = 0; 710c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *opFlag; 711c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *ifaceLimiting; 7128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 713c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 714c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall switch (op) { 715c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall case IptOpInsert: 716c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall opFlag = "-I"; 717c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall break; 718c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall case IptOpReplace: 719c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall opFlag = "-R"; 720c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall break; 721c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall default: 722c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall case IptOpDelete: 723c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall opFlag = "-D"; 724c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall break; 725c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 726c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 727c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall ifaceLimiting = "! -i lo+"; 728c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "FORWARD", 729c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich bytes, alertName); 730c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res = runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 731c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall free(alertQuotaCmd); 732c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return res; 733c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall} 734c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 735c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlert(int64_t bytes) { 736c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 7378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 7388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 7405ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 7418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (globalAlertBytes) { 7448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = updateQuota(alertName, bytes); 7458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } else { 7468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = runIptablesAlertCmd(IptOpInsert, alertName, bytes); 747c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (globalAlertTetherCount) { 7483fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("setGlobalAlert for %d tether", globalAlertTetherCount); 749c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res |= runIptablesAlertFwdCmd(IptOpInsert, alertName, bytes); 750c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 7518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall globalAlertBytes = bytes; 7538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 7548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 756c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlertInForwardChain(void) { 757c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 758c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall int res = 0; 759c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 760c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall globalAlertTetherCount++; 7613fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("setGlobalAlertInForwardChain(): %d tether", globalAlertTetherCount); 762c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 763c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* 764c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is no globalAlert active we are done. 765c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is an active globalAlert but this is not the 1st 766c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * tether, we are also done. 767c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall */ 768c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (!globalAlertBytes || globalAlertTetherCount != 1) { 769c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return 0; 770c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 771c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 772c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* We only add the rule if this was the 1st tether added. */ 773c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res = runIptablesAlertFwdCmd(IptOpInsert, alertName, globalAlertBytes); 774c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return res; 775c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall} 776c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 7778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeGlobalAlert(void) { 7788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 779c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 7808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 7818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!globalAlertBytes) { 7835ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set"); 7848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = runIptablesAlertCmd(IptOpDelete, alertName, globalAlertBytes); 787c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (globalAlertTetherCount) { 788c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res |= runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes); 789c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 7908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall globalAlertBytes = 0; 7918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 7928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 794c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::removeGlobalAlertInForwardChain(void) { 795c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall int res = 0; 796c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 797c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 798c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (!globalAlertTetherCount) { 7995ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set"); 800c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return -1; 801c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 802c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 803c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall globalAlertTetherCount--; 804c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* 805c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is no globalAlert active we are done. 806c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is an active globalAlert but there are more 807c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * tethers, we are also done. 808c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall */ 809c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (!globalAlertBytes || globalAlertTetherCount >= 1) { 810c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return 0; 811c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 812c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 813c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* We only detete the rule if this was the last tether removed. */ 814c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res = runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes); 815c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return res; 816c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall} 817c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 8188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setSharedAlert(int64_t bytes) { 8198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!sharedQuotaBytes) { 8205ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Need to have a prior shared quota set to set an alert"); 8218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 8245ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 8258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return setCostlyAlert("shared", bytes, &sharedAlertBytes); 8288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeSharedAlert(void) { 8318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return removeCostlyAlert("shared", &sharedAlertBytes); 8328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setInterfaceAlert(const char *iface, int64_t bytes) { 8358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::list<QuotaInfo>::iterator it; 8368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 8385ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 8398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 8428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == iface) 8438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 8448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it == quotaIfaces.end()) { 8475ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Need to have a prior interface quota set to set an alert"); 8488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return setCostlyAlert(iface, bytes, &it->alert); 8528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeInterfaceAlert(const char *iface) { 8558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::list<QuotaInfo>::iterator it; 8568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 8588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == iface) 8598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 8608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it == quotaIfaces.end()) { 8635ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set for interface %s", iface); 8648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return removeCostlyAlert(iface, &it->alert); 8688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes) { 8718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 8728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *chainNameAndPos; 8738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 8748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertName; 8758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 8775ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 8788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertName, "%sAlert", costName); 8818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (*alertBytes) { 8828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = updateQuota(alertName, *alertBytes); 8838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } else { 8848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&chainNameAndPos, "costly_%s %d", costName, ALERT_RULE_POS_IN_COSTLY_CHAIN); 885c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "", "-I", chainNameAndPos, bytes, alertName); 8868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 8878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 8888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(chainNameAndPos); 8898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *alertBytes = bytes; 8918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertName); 8928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 8938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeCostlyAlert(const char *costName, int64_t *alertBytes) { 8968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 8978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *chainName; 8988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertName; 8998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 9008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertName, "%sAlert", costName); 9028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!*alertBytes) { 9035ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set for %s alert", costName); 9048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 9058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&chainName, "costly_%s", costName); 908c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "", "-D", chainName, *alertBytes, alertName); 9098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 9108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 9118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(chainName); 9128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *alertBytes = 0; 9148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertName); 9158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 9168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 917db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 918db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* 919db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Parse the ptks and bytes out of: 920db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) 921db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * pkts bytes target prot opt in out source destination 922db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * 0 0 ACCEPT all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 923db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * 0 0 DROP all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0 state INVALID 924db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * 0 0 ACCEPT all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0 925db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * 926db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */ 927a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrallint BandwidthController::parseForwardChainStats(TetherStats &stats, FILE *fp, 928a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall std::string &extraProcessingInfo) { 929db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall int res; 930db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN]; 931db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char iface0[MAX_IPT_OUTPUT_LINE_LEN]; 932db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char iface1[MAX_IPT_OUTPUT_LINE_LEN]; 933db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char rest[MAX_IPT_OUTPUT_LINE_LEN]; 934db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 935db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char *buffPtr; 936db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall int64_t packets, bytes; 937db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 938db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) { 939db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Clean up, so a failed parse can still print info */ 940db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall iface0[0] = iface1[0] = rest[0] = packets = bytes = 0; 941db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall res = sscanf(buffPtr, "%lld %lld ACCEPT all -- %s %s 0.%s", 942db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall &packets, &bytes, iface0, iface1, rest); 9433fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("parse res=%d iface0=<%s> iface1=<%s> pkts=%lld bytes=%lld rest=<%s> orig line=<%s>", res, 944db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall iface0, iface1, packets, bytes, rest, buffPtr); 945a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall extraProcessingInfo += buffPtr; 946a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall 947db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall if (res != 5) { 948db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall continue; 949db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 950db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall if ((stats.ifaceIn == iface0) && (stats.ifaceOut == iface1)) { 9513fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets); 952db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall stats.rxPackets = packets; 953db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall stats.rxBytes = bytes; 954db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } else if ((stats.ifaceOut == iface0) && (stats.ifaceIn == iface1)) { 9553fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("iface_in=%s iface_out=%s tx_bytes=%lld tx_packets=%lld ", iface1, iface0, bytes, packets); 956db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall stats.txPackets = packets; 957db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall stats.txBytes = bytes; 958db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 959db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 960db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Failure if rx or tx was not found */ 961db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return (stats.rxBytes == -1 || stats.txBytes == -1) ? -1 : 0; 962db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall} 963db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 964db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 965db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallchar *BandwidthController::TetherStats::getStatsLine(void) { 966db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char *msg; 967db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall asprintf(&msg, "%s %s %lld %lld %lld %lld", ifaceIn.c_str(), ifaceOut.c_str(), 968db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall rxBytes, rxPackets, txBytes, txPackets); 969db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return msg; 970db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall} 971db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 972a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrallint BandwidthController::getTetherStats(TetherStats &stats, std::string &extraProcessingInfo) { 973db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall int res; 974db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall std::string fullCmd; 975db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall FILE *iptOutput; 976db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall const char *cmd; 977db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 978db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall if (stats.rxBytes != -1 || stats.txBytes != -1) { 9795ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Unexpected input stats. Byte counts should be -1."); 980db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return -1; 981db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 982db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 983db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* 984db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Why not use some kind of lib to talk to iptables? 985db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Because the only libs are libiptc and libip6tc in iptables, and they are 986db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * not easy to use. They require the known iptables match modules to be 987db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * preloaded/linked, and require apparently a lot of wrapper code to get 988db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * the wanted info. 989db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */ 990db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall fullCmd = IPTABLES_PATH; 991db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall fullCmd += " -nvx -L FORWARD"; 992db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall iptOutput = popen(fullCmd.c_str(), "r"); 993db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall if (!iptOutput) { 9945ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno)); 995a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall extraProcessingInfo += "Failed to run iptables."; 996db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return -1; 997db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 998a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall res = parseForwardChainStats(stats, iptOutput, extraProcessingInfo); 999db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall pclose(iptOutput); 1000db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1001db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Currently NatController doesn't do ipv6 tethering, so we are done. */ 1002db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return res; 1003db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall} 1004