BandwidthController.cpp revision 0031cead820149e2fe3ccb3cc2fe05758a3cb5c2
14a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall/* 24a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Copyright (C) 2011 The Android Open Source Project 34a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 44a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Licensed under the Apache License, Version 2.0 (the "License"); 54a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * you may not use this file except in compliance with the License. 64a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * You may obtain a copy of the License at 74a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 84a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * http://www.apache.org/licenses/LICENSE-2.0 94a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 104a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Unless required by applicable law or agreed to in writing, software 114a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * distributed under the License is distributed on an "AS IS" BASIS, 124a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * See the License for the specific language governing permissions and 144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * limitations under the License. 154a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 164a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 17db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall// #define LOG_NDEBUG 0 18db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 19db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* 20db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * The CommandListener, FrameworkListener don't allow for 21db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * multiple calls in parallel to reach the BandwidthController. 22db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * If they ever were to allow it, then netd/ would need some tweaking. 23db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */ 24db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <errno.h> 264a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <fcntl.h> 27db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall#include <stdio.h> 288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <stdlib.h> 294a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <string.h> 304a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 314a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/socket.h> 324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/stat.h> 334a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/types.h> 344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/wait.h> 354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 364a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/netlink.h> 374a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/rtnetlink.h> 384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/pkt_sched.h> 394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#define LOG_TAG "BandwidthController" 414a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/log.h> 424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/properties.h> 434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 44c4bbfa247dbe4dda17e28694d49afd3ec0b06badGlenn Kastenextern "C" int logwrap(int argc, const char **argv); 459e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrallextern "C" int system_nosh(const char *command); 464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "NetdConstants.h" 484a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include "BandwidthController.h" 494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 50db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* Alphabetical */ 51c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich#define ALERT_IPT_TEMPLATE "%s %s %s -m quota2 ! --quota %lld --name %s" 52db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int BandwidthController::ALERT_RULE_POS_IN_COSTLY_CHAIN = 4; 53c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallconst char BandwidthController::ALERT_GLOBAL_NAME[] = "globalAlert"; 54db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int BandwidthController::MAX_CMD_ARGS = 32; 55db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int BandwidthController::MAX_CMD_LEN = 1024; 56db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int BandwidthController::MAX_IFACENAME_LEN = 64; 57db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int BandwidthController::MAX_IPT_OUTPUT_LINE_LEN = 256; 58db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 5911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrallbool BandwidthController::useLogwrapCall = false; 604a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP 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. 650031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * E.g. "-I INPUT -i rmnet0 --jump costly" 664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - quota'd rules in the costly chain should be before penalty_box lookups. 674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * global quota vs per interface quota 694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - global quota for all costly interfaces uses a single costly chain: 704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * . initial rules 71bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -N costly_shared 720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -I INPUT -i iface0 --jump costly_shared 730031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -I OUTPUT -o iface0 --jump costly_shared 74bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I costly_shared -m quota \! --quota 500000 \ 75bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * --jump REJECT --reject-with icmp-net-prohibited 76bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A costly_shared --jump penalty_box 77bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A costly_shared -m owner --socket-exists 788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall * 794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * . adding a new iface to this, E.g.: 800031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -I INPUT -i iface1 --jump costly_shared 810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -I 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 860031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -I INPUT -i iface0 --jump costly_iface0 870031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -I 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 * iptables -A costly_iface0 -m owner --socket-exists 924a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 934a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * penalty_box handling: 944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - only one penalty_box for all interfaces 954a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g Adding an app: 96bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A penalty_box -m owner --uid-owner app_3 \ 97bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * --jump REJECT --reject-with icmp-net-prohibited 984a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 990031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char *BandwidthController::IPT_FLUSH_COMMANDS[] = { 1000031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall /* 1010031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Cleanup rules. 1020031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Should normally include costly_<iface>, but we rely on the way they are setup 1030031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * to allow coexistance. 10439f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall */ 1050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-F bw_INPUT", 1060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-F bw_OUTPUT", 1070031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-F bw_FORWARD", 1080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-F penalty_box", 1090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-F costly_shared", 1100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}; 1110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 1120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall/* The cleanup commands assume flushing has been done. */ 1130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char *BandwidthController::IPT_CLEANUP_COMMANDS[] = { 1140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall /* Delete hooks to custom chains. */ 1150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-D INPUT -j bw_INPUT", 1160031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-D OUTPUT -j bw_OUTPUT", 1170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-D FORWARD -j bw_FORWARD", 1180031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-X bw_INPUT", 1190031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-X bw_OUTPUT", 1200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-X bw_FORWARD", 1210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-X penalty_box", 1220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-X costly_shared", 1230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 125db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_SETUP_COMMANDS[] = { 1260dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* Created needed chains. */ 1270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-N bw_INPUT", 1280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-A INPUT -j bw_INPUT", 1290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 1300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-N bw_OUTPUT", 1310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-A OUTPUT -j bw_OUTPUT", 1320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 1330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-N bw_FORWARD", 1340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-I FORWARD -j bw_FORWARD", 1350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 136bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-N costly_shared", 1370dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-N penalty_box", 1380dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1390dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 140db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_BASIC_ACCOUNTING_COMMANDS[] = { 1410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-A bw_INPUT -i lo --jump RETURN", 1420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-A bw_INPUT -m owner --socket-exists", /* This is a tracking rule. */ 1430dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 1440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-A bw_OUTPUT -o lo --jump RETURN", 1450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-A bw_OUTPUT -m owner --socket-exists", /* This is a tracking rule. */ 1460dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 147bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-A costly_shared --jump penalty_box", 148bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-A costly_shared -m owner --socket-exists", /* This is a tracking rule. */ 1490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallBandwidthController::BandwidthController(void) { 1524a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char value[PROPERTY_VALUE_MAX]; 1534a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 15411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall property_get("persist.bandwidth.uselogwrap", value, "0"); 15511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall useLogwrapCall = !strcmp(value, "1"); 1564a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 1574a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 15826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling) { 1590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 1608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 1613fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("runIpxtablesCmd(cmd=%s)", cmd); 16226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIptablesCmd(cmd, rejectHandling, IptIpV4); 16326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIptablesCmd(cmd, rejectHandling, IptIpV6); 1640dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 1650dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 1660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 16726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::StrncpyAndCheck(char *buffer, const char *src, size_t buffSize) { 16826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 16926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall memset(buffer, '\0', buffSize); // strncpy() is not filling leftover with '\0' 17026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall strncpy(buffer, src, buffSize); 17126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return buffer[buffSize - 1]; 17226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall} 17326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 1748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesCmd(const char *cmd, IptRejectOp rejectHandling, 1758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall IptIpVer iptVer) { 17626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall char buffer[MAX_CMD_LEN]; 1774a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall const char *argv[MAX_CMD_ARGS]; 17826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall int argc = 0; 1794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char *next = buffer; 1804a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char *tmp; 18111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall int res; 1824a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1830dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string fullCmd = cmd; 18426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 18526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (rejectHandling == IptRejectAdd) { 1860dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall fullCmd += " --jump REJECT --reject-with"; 18726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (iptVer) { 18826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case IptIpV4: 1898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fullCmd += " icmp-net-prohibited"; 1908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 19126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case IptIpV6: 1928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fullCmd += " icmp6-adm-prohibited"; 1938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 1940dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 1950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 1960dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 19711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall fullCmd.insert(0, " "); 19811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall fullCmd.insert(0, iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH); 1994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 20011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (!useLogwrapCall) { 2019e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall res = system_nosh(fullCmd.c_str()); 20211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } else { 20311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) { 2045ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("iptables command too long"); 2054a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return -1; 2064a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 207fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 20811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall argc = 0; 20911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall while ((tmp = strsep(&next, " "))) { 21011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall argv[argc++] = tmp; 21111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (argc >= MAX_CMD_ARGS) { 2125ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("iptables argument overflow"); 21311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall return -1; 21411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 21511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 21611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall 21711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall argv[argc] = NULL; 218c4bbfa247dbe4dda17e28694d49afd3ec0b06badGlenn Kasten res = logwrap(argc, argv); 21911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 22011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (res) { 2215ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("runIptablesCmd(): failed %s res=%d", fullCmd.c_str(), res); 22211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 22311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall return res; 2244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2254a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint BandwidthController::setupIptablesHooks(void) { 2270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall /* Some of the initialCommands are allowed to fail */ 2290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*), 2300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall IPT_FLUSH_COMMANDS, RunCmdFailureOk); 2310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall runCommands(sizeof(IPT_CLEANUP_COMMANDS) / sizeof(char*), 2330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall IPT_CLEANUP_COMMANDS, RunCmdFailureOk); 2340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall runCommands(sizeof(IPT_SETUP_COMMANDS) / sizeof(char*), 2360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall IPT_SETUP_COMMANDS, RunCmdFailureBad); 2370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return 0; 2390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2400031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall} 2410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint BandwidthController::enableBandwidthControl(bool force) { 243fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res; 2440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall char value[PROPERTY_VALUE_MAX]; 2450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall if (!force) { 2470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall property_get("persist.bandwidth.enable", value, "1"); 2480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall if (!strcmp(value, "0")) 2490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return 0; 2500031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall } 2518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 252db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Let's pretend we started from scratch ... */ 2538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedQuotaIfaces.clear(); 2548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall quotaIfaces.clear(); 2558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall naughtyAppUids.clear(); 256db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall globalAlertBytes = 0; 257c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall globalAlertTetherCount = 0; 258db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall sharedQuotaBytes = sharedAlertBytes = 0; 259db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 2600031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall res = runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*), 2610031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall IPT_FLUSH_COMMANDS, RunCmdFailureOk); 262db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 2630031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall res |= runCommands(sizeof(IPT_BASIC_ACCOUNTING_COMMANDS) / sizeof(char*), 264db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall IPT_BASIC_ACCOUNTING_COMMANDS, RunCmdFailureBad); 2658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 266fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 2674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::disableBandwidthControl(void) { 2710031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*), 2720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall IPT_FLUSH_COMMANDS, RunCmdFailureOk); 273fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return 0; 2744a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2754a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runCommands(int numCommands, const char *commands[], 2778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall RunCmdErrHandling cmdErrHandling) { 278fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 2793fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("runCommands(): %d commands", numCommands); 280fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) { 28126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res = runIpxtablesCmd(commands[cmdNum], IptRejectNoAdd); 2820031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall if (res && cmdErrHandling != RunCmdFailureOk) 283fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 284fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 2850031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return 0; 286fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 287fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 2880dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallstd::string BandwidthController::makeIptablesNaughtyCmd(IptOp op, int uid) { 289fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string res; 2908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *buff; 2918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 292fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 293fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall switch (op) { 2948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 2958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 2968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 2978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 2988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 2998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 3008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 3018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 3028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 3038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 304fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 3058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&buff, "%s penalty_box -m owner --uid-owner %d", opFlag, uid); 3068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = buff; 3078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(buff); 308fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 309fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 310fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 311fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::addNaughtyApps(int numUids, char *appUids[]) { 31226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpAdd); 313fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 314fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 315fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeNaughtyApps(int numUids, char *appUids[]) { 31626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpRemove); 317fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 318fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 31926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::maninpulateNaughtyApps(int numUids, char *appStrUids[], NaughtyAppOp appOp) { 320fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall char cmd[MAX_CMD_LEN]; 321fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int uidNum; 32226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *failLogTemplate; 32326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall IptOp op; 324fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int appUids[numUids]; 32526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string naughtyCmd; 3268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 32726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (appOp) { 32826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case NaughtyAppOpAdd: 3298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall op = IptOpInsert; 3308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall failLogTemplate = "Failed to add app uid %d to penalty box."; 3318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 33226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case NaughtyAppOpRemove: 3338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall op = IptOpDelete; 3348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall failLogTemplate = "Failed to delete app uid %d from penalty box."; 3358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 3360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall default: 3370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall ALOGE("Unexpected app Op %d", appOp); 3380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return -1; 33926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 34026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 341fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (uidNum = 0; uidNum < numUids; uidNum++) { 342fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall appUids[uidNum] = atol(appStrUids[uidNum]); 343fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (appUids[uidNum] == 0) { 3445ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE(failLogTemplate, appUids[uidNum]); 345fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_parse; 346fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 347fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 348fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 349fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (uidNum = 0; uidNum < numUids; uidNum++) { 35026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall naughtyCmd = makeIptablesNaughtyCmd(op, appUids[uidNum]); 35126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd)) { 3525ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE(failLogTemplate, appUids[uidNum]); 353fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_with_uidNum; 354fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 355fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 356fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return 0; 357fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 35826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_with_uidNum: 359fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* Try to remove the uid that failed in any case*/ 36026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall naughtyCmd = makeIptablesNaughtyCmd(IptOpDelete, appUids[uidNum]); 36126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd); 36226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_parse: 36326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 3644a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 3654a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 36626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallstd::string BandwidthController::makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota) { 367fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string res; 3688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *buff; 3698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 3700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 3713fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("makeIptablesQuotaCmd(%d, %lld)", op, quota); 3720dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 373fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall switch (op) { 3748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 3758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 3768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 3778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 3788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 3798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 3808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 3818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 3828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 3838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 384fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 3858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 386bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall // The requried IP version specific --jump REJECT ... will be added later. 3878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&buff, "%s costly_%s -m quota2 ! --quota %lld --name %s", opFlag, costName, quota, 3888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall costName); 3898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = buff; 3908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(buff); 3910dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 3920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 3930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 39426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::prepCostlyIface(const char *ifn, QuotaType quotaType) { 3950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char cmd[MAX_CMD_LEN]; 3960031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall int res = 0, res1, res2; 3978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int ruleInsertPos = 1; 3980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string costString; 3990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall const char *costCString; 4000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 4010dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* The "-N costly" is created upfront, no need to handle it here. */ 40226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (quotaType) { 40326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaUnique: 404bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costString = "costly_"; 4050dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costString += ifn; 4060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costCString = costString.c_str(); 4070031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall /* 4080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Flush the costly_<iface> is allowed to fail in case it didn't exist. 4090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Creating a new one is allowed to fail in case it existed. 4100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * This helps with netd restarts. 4110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall */ 4120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-F %s", costCString); 4130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall res1 = runIpxtablesCmd(cmd, IptRejectNoAdd); 4140dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-N %s", costCString); 4150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall res2 = runIpxtablesCmd(cmd, IptRejectNoAdd); 4160031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall res = (res1 && res2) || (!res1 && !res2); 4170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 4180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-A %s -j penalty_box", costCString); 41926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 4200dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-A %s -m owner --socket-exists", costCString); 42126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 42226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 42326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaShared: 424bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costCString = "costly_shared"; 42526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 4260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall default: 4270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall ALOGE("Unexpected quotatype %d", quotaType); 4280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return -1; 4290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 4300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 4318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (globalAlertBytes) { 4328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* The alert rule comes 1st */ 4338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ruleInsertPos = 2; 4348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 4350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 4360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_INPUT -i %s --jump %s", ifn, costCString); 4370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall runIpxtablesCmd(cmd, IptRejectNoAdd); 4380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 4390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-I bw_INPUT %d -i %s --jump %s", ruleInsertPos, ifn, costCString); 44026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 4410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 4420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_OUTPUT -o %s --jump %s", ifn, costCString); 4430031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall runIpxtablesCmd(cmd, IptRejectNoAdd); 4440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 4450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-I bw_OUTPUT %d -o %s --jump %s", ruleInsertPos, ifn, costCString); 44626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 4470dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 4480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 4490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 45026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::cleanupCostlyIface(const char *ifn, QuotaType quotaType) { 4510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char cmd[MAX_CMD_LEN]; 4520dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 4530dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string costString; 4540dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall const char *costCString; 4550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 45626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (quotaType) { 45726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaUnique: 458bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costString = "costly_"; 4590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costString += ifn; 4600dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costCString = costString.c_str(); 46126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 46226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaShared: 463bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costCString = "costly_shared"; 46426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 4650031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall default: 4660031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall ALOGE("Unexpected quotatype %d", quotaType); 4670031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return -1; 4680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 4690dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 4700031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_INPUT -i %s --jump %s", ifn, costCString); 47126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 4720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_OUTPUT -o %s --jump %s", ifn, costCString); 47326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 4740dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 475bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall /* The "-N costly_shared" is created upfront, no need to handle it here. */ 47626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (quotaType == QuotaUnique) { 4770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-F %s", costCString); 47826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 479a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall snprintf(cmd, sizeof(cmd), "-X %s", costCString); 480a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 481fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 482fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 483fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 4844a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4850dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceSharedQuota(const char *iface, int64_t maxBytes) { 4864a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char cmd[MAX_CMD_LEN]; 4874a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char ifn[MAX_IFACENAME_LEN]; 488fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 48926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string quotaCmd; 4908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::string ifaceName; 4918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ; 492bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall const char *costName = "shared"; 49326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<std::string>::iterator it; 4944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!maxBytes) { 4968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* Don't talk about -1, deprecate it. */ 4975ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 4988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 4998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 50026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 5015ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 50226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 50326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 50426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 5054a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 5064a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (maxBytes == -1) { 507fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return removeInterfaceSharedQuota(ifn); 5084a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 5094a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 5104a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* Insert ingress quota. */ 5110dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) { 5120dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (*it == ifaceName) 513fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 5144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 515fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 5160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == sharedQuotaIfaces.end()) { 51726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= prepCostlyIface(ifn, QuotaShared); 5180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (sharedQuotaIfaces.empty()) { 5190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes); 52026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd); 5214a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (res) { 5225ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed set quota rule"); 523fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail; 5244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 525fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = maxBytes; 526fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 5270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall sharedQuotaIfaces.push_front(ifaceName); 528fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 529fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 530fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 531fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (maxBytes != sharedQuotaBytes) { 5328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= updateQuota(costName, maxBytes); 533fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (res) { 5345ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed update quota for %s", costName); 535fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail; 536fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 537fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = maxBytes; 5384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 5394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return 0; 540fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 541fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall fail: 5424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* 5434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse 5444a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * rules in the kernel to see which ones need cleaning up. 545fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * For now callers needs to choose if they want to "ndc bandwidth enable" 546fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * which resets everything. 5474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 548fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall removeInterfaceSharedQuota(ifn); 5494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return -1; 5504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 5514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 5528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall/* It will also cleanup any shared alerts */ 553fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeInterfaceSharedQuota(const char *iface) { 5544a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char ifn[MAX_IFACENAME_LEN]; 555fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 55626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 5570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::list<std::string>::iterator it; 558bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall const char *costName = "shared"; 5594a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP 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 } 5648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ifaceName = ifn; 56526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 5660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) { 5670dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (*it == ifaceName) 568fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 5694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 5700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == sharedQuotaIfaces.end()) { 5715ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No such iface %s to delete", ifn); 572fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return -1; 5734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 574fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 57526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= cleanupCostlyIface(ifn, QuotaShared); 5760dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall sharedQuotaIfaces.erase(it); 577fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 5780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (sharedQuotaIfaces.empty()) { 579fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string quotaCmd; 580bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, sharedQuotaBytes); 58126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd); 5828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedQuotaBytes = 0; 5838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (sharedAlertBytes) { 5848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall removeSharedAlert(); 5858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedAlertBytes = 0; 5868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 587fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 5884a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return res; 5894a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 5900dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5910dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceQuota(const char *iface, int64_t maxBytes) { 5920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char ifn[MAX_IFACENAME_LEN]; 5930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 59426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 59526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *costName; 59626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<QuotaInfo>::iterator it; 59726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string quotaCmd; 5980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!maxBytes) { 6008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* Don't talk about -1, deprecate it. */ 6015ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 6028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 6038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 6040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (maxBytes == -1) { 60526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return removeInterfaceQuota(iface); 6060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6070dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 6095ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 61026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 61126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 61226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 61326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall costName = iface; 61426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 6150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* Insert ingress quota. */ 6160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 6178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == ifaceName) 6180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall break; 6190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6200dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6210dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == quotaIfaces.end()) { 62226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= prepCostlyIface(ifn, QuotaUnique); 6230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes); 62426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd); 6250dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (res) { 6265ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed set quota rule"); 6270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall goto fail; 6280dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall quotaIfaces.push_front(QuotaInfo(ifaceName, maxBytes, 0)); 6310dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6320dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } else { 6338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= updateQuota(costName, maxBytes); 6340dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (res) { 6355ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed update quota for %s", iface); 6360dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall goto fail; 6370dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall it->quota = maxBytes; 6390dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6400dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return 0; 6410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall fail: 6430dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* 6440dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse 6450dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * rules in the kernel to see which ones need cleaning up. 6460dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * For now callers needs to choose if they want to "ndc bandwidth enable" 6470dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * which resets everything. 6480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall */ 6490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall removeInterfaceSharedQuota(ifn); 6500dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return -1; 6510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 6520dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceSharedQuota(int64_t *bytes) { 6548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return getInterfaceQuota("shared", bytes); 6558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 6568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceQuota(const char *costName, int64_t *bytes) { 6588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall FILE *fp; 6598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *fname; 6608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int scanRes; 6618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&fname, "/proc/net/xt_quota/%s", costName); 6638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fp = fopen(fname, "r"); 6648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(fname); 6658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!fp) { 6665ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Reading quota %s failed (%s)", costName, strerror(errno)); 6678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 6688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 6698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall scanRes = fscanf(fp, "%lld", bytes); 6703fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("Read quota res=%d bytes=%lld", scanRes, *bytes); 6718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fclose(fp); 6728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return scanRes == 1 ? 0 : -1; 6738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 6748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6750dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::removeInterfaceQuota(const char *iface) { 6760dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char ifn[MAX_IFACENAME_LEN]; 6780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 67926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 68026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *costName; 68126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<QuotaInfo>::iterator it; 6820dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 6845ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 68526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 68626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 68726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 68826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall costName = iface; 6890dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6900dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 6918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == ifaceName) 6920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall break; 6930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6940dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == quotaIfaces.end()) { 6965ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No such iface %s to delete", ifn); 6970dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return -1; 6980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* This also removes the quota command of CostlyIface chain. */ 70126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= cleanupCostlyIface(ifn, QuotaUnique); 7020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaIfaces.erase(it); 7040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7050dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 7060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 7078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::updateQuota(const char *quotaName, int64_t bytes) { 7098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall FILE *fp; 7108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *fname; 7118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&fname, "/proc/net/xt_quota/%s", quotaName); 7138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fp = fopen(fname, "w"); 7148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(fname); 7158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!fp) { 7165ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Updating quota %s failed (%s)", quotaName, strerror(errno)); 7178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fprintf(fp, "%lld\n", bytes); 7208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fclose(fp); 7218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return 0; 7228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesAlertCmd(IptOp op, const char *alertName, int64_t bytes) { 7258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 7268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 727876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall const char *ifaceLimiting; 7288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 7298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall switch (op) { 7318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 7328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 7338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 7348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 7358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 7368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 7378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 7388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 7398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 7408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 7418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 743876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall ifaceLimiting = "! -i lo+"; 7440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "bw_INPUT", 745c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich bytes, alertName); 7468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 7478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 748876666947664c718a8d0cae9bbddb06cc91f912cJP Abgrall ifaceLimiting = "! -o lo+"; 7490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "bw_OUTPUT", 750c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich bytes, alertName); 7518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 7528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 7538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 7548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 756c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::runIptablesAlertFwdCmd(IptOp op, const char *alertName, int64_t bytes) { 757c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall int res = 0; 758c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *opFlag; 759c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *ifaceLimiting; 7608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 761c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 762c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall switch (op) { 763c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall case IptOpInsert: 764c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall opFlag = "-I"; 765c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall break; 766c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall case IptOpReplace: 767c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall opFlag = "-R"; 768c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall break; 769c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall default: 770c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall case IptOpDelete: 771c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall opFlag = "-D"; 772c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall break; 773c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 774c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 775c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall ifaceLimiting = "! -i lo+"; 7760031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, ifaceLimiting, opFlag, "bw_FORWARD", 777c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich bytes, alertName); 778c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res = runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 779c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall free(alertQuotaCmd); 780c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return res; 781c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall} 782c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 783c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlert(int64_t bytes) { 784c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 7858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 7868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 7885ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 7898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (globalAlertBytes) { 7928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = updateQuota(alertName, bytes); 7938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } else { 7948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = runIptablesAlertCmd(IptOpInsert, alertName, bytes); 795c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (globalAlertTetherCount) { 7963fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("setGlobalAlert for %d tether", globalAlertTetherCount); 797c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res |= runIptablesAlertFwdCmd(IptOpInsert, alertName, bytes); 798c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 7998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall globalAlertBytes = bytes; 8018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 8028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 804c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlertInForwardChain(void) { 805c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 806c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall int res = 0; 807c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 808c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall globalAlertTetherCount++; 8093fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("setGlobalAlertInForwardChain(): %d tether", globalAlertTetherCount); 810c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 811c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* 812c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is no globalAlert active we are done. 813c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is an active globalAlert but this is not the 1st 814c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * tether, we are also done. 815c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall */ 816c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (!globalAlertBytes || globalAlertTetherCount != 1) { 817c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return 0; 818c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 819c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 820c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* We only add the rule if this was the 1st tether added. */ 821c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res = runIptablesAlertFwdCmd(IptOpInsert, alertName, globalAlertBytes); 822c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return res; 823c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall} 824c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 8258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeGlobalAlert(void) { 8268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 827c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 8288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 8298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!globalAlertBytes) { 8315ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set"); 8328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = runIptablesAlertCmd(IptOpDelete, alertName, globalAlertBytes); 835c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (globalAlertTetherCount) { 836c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res |= runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes); 837c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 8388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall globalAlertBytes = 0; 8398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 8408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 842c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::removeGlobalAlertInForwardChain(void) { 843c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall int res = 0; 844c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 845c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 846c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (!globalAlertTetherCount) { 8475ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set"); 848c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return -1; 849c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 850c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 851c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall globalAlertTetherCount--; 852c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* 853c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is no globalAlert active we are done. 854c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is an active globalAlert but there are more 855c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * tethers, we are also done. 856c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall */ 857c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (!globalAlertBytes || globalAlertTetherCount >= 1) { 858c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return 0; 859c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 860c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 861c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* We only detete the rule if this was the last tether removed. */ 862c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res = runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes); 863c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return res; 864c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall} 865c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 8668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setSharedAlert(int64_t bytes) { 8678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!sharedQuotaBytes) { 8685ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Need to have a prior shared quota set to set an alert"); 8698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 8725ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 8738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return setCostlyAlert("shared", bytes, &sharedAlertBytes); 8768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeSharedAlert(void) { 8798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return removeCostlyAlert("shared", &sharedAlertBytes); 8808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setInterfaceAlert(const char *iface, int64_t bytes) { 8838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::list<QuotaInfo>::iterator it; 8848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 8865ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 8878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 8908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == iface) 8918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 8928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it == quotaIfaces.end()) { 8955ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Need to have a prior interface quota set to set an alert"); 8968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return setCostlyAlert(iface, bytes, &it->alert); 9008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 9018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeInterfaceAlert(const char *iface) { 9038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::list<QuotaInfo>::iterator it; 9048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 9068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == iface) 9078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 9088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it == quotaIfaces.end()) { 9115ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set for interface %s", iface); 9128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 9138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return removeCostlyAlert(iface, &it->alert); 9168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 9178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes) { 9198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 9208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *chainNameAndPos; 9218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 9228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertName; 9238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 9255ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 9268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 9278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertName, "%sAlert", costName); 9298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (*alertBytes) { 9308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = updateQuota(alertName, *alertBytes); 9318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } else { 9328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&chainNameAndPos, "costly_%s %d", costName, ALERT_RULE_POS_IN_COSTLY_CHAIN); 933c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "", "-I", chainNameAndPos, bytes, alertName); 9348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 9358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 9368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(chainNameAndPos); 9378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *alertBytes = bytes; 9398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertName); 9408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 9418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 9428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeCostlyAlert(const char *costName, int64_t *alertBytes) { 9448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 9458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *chainName; 9468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertName; 9478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 9488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertName, "%sAlert", costName); 9508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!*alertBytes) { 9515ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set for %s alert", costName); 9528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 9538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&chainName, "costly_%s", costName); 956c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "", "-D", chainName, *alertBytes, alertName); 9578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 9588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 9598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(chainName); 9608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *alertBytes = 0; 9628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertName); 9638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 9648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 965db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 966db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* 967db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Parse the ptks and bytes out of: 9680031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Chain FORWARD (policy RETURN 0 packets, 0 bytes) 969db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * pkts bytes target prot opt in out source destination 9700031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * 0 0 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 971db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * 0 0 DROP all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0 state INVALID 9720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * 0 0 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0 973db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * 974db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */ 975a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrallint BandwidthController::parseForwardChainStats(TetherStats &stats, FILE *fp, 976a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall std::string &extraProcessingInfo) { 977db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall int res; 978db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN]; 979db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char iface0[MAX_IPT_OUTPUT_LINE_LEN]; 980db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char iface1[MAX_IPT_OUTPUT_LINE_LEN]; 981db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char rest[MAX_IPT_OUTPUT_LINE_LEN]; 982db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 983db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char *buffPtr; 984db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall int64_t packets, bytes; 985db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 986db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) { 987db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Clean up, so a failed parse can still print info */ 988db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall iface0[0] = iface1[0] = rest[0] = packets = bytes = 0; 9890031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall res = sscanf(buffPtr, "%lld %lld RETURN all -- %s %s 0.%s", 990db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall &packets, &bytes, iface0, iface1, rest); 9913fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("parse res=%d iface0=<%s> iface1=<%s> pkts=%lld bytes=%lld rest=<%s> orig line=<%s>", res, 992db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall iface0, iface1, packets, bytes, rest, buffPtr); 993a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall extraProcessingInfo += buffPtr; 994a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall 995db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall if (res != 5) { 996db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall continue; 997db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 998db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall if ((stats.ifaceIn == iface0) && (stats.ifaceOut == iface1)) { 9993fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets); 1000db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall stats.rxPackets = packets; 1001db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall stats.rxBytes = bytes; 1002db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } else if ((stats.ifaceOut == iface0) && (stats.ifaceIn == iface1)) { 10033fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("iface_in=%s iface_out=%s tx_bytes=%lld tx_packets=%lld ", iface1, iface0, bytes, packets); 1004db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall stats.txPackets = packets; 1005db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall stats.txBytes = bytes; 1006db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 1007db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 1008db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Failure if rx or tx was not found */ 1009db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return (stats.rxBytes == -1 || stats.txBytes == -1) ? -1 : 0; 1010db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall} 1011db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1012db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1013db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallchar *BandwidthController::TetherStats::getStatsLine(void) { 1014db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char *msg; 1015db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall asprintf(&msg, "%s %s %lld %lld %lld %lld", ifaceIn.c_str(), ifaceOut.c_str(), 1016db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall rxBytes, rxPackets, txBytes, txPackets); 1017db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return msg; 1018db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall} 1019db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1020a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrallint BandwidthController::getTetherStats(TetherStats &stats, std::string &extraProcessingInfo) { 1021db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall int res; 1022db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall std::string fullCmd; 1023db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall FILE *iptOutput; 1024db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall const char *cmd; 1025db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1026db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall if (stats.rxBytes != -1 || stats.txBytes != -1) { 10275ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Unexpected input stats. Byte counts should be -1."); 1028db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return -1; 1029db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 1030db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1031db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* 1032db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Why not use some kind of lib to talk to iptables? 1033db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Because the only libs are libiptc and libip6tc in iptables, and they are 1034db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * not easy to use. They require the known iptables match modules to be 1035db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * preloaded/linked, and require apparently a lot of wrapper code to get 1036db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * the wanted info. 1037db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */ 1038db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall fullCmd = IPTABLES_PATH; 10390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall fullCmd += " -nvx -L natctrl_FORWARD"; 1040db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall iptOutput = popen(fullCmd.c_str(), "r"); 1041db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall if (!iptOutput) { 10425ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno)); 1043a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall extraProcessingInfo += "Failed to run iptables."; 1044db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return -1; 1045db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 1046a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall res = parseForwardChainStats(stats, iptOutput, extraProcessingInfo); 1047db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall pclose(iptOutput); 1048db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1049db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Currently NatController doesn't do ipv6 tethering, so we are done. */ 1050db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return res; 1051db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall} 1052