BandwidthController.cpp revision 0e540ec038dfdbcf5cba3d5b9b2765e1dcec062b
14a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall/* 24a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Copyright (C) 2011 The Android Open Source Project 34a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 44a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Licensed under the Apache License, Version 2.0 (the "License"); 54a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * you may not use this file except in compliance with the License. 64a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * You may obtain a copy of the License at 74a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 84a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * http://www.apache.org/licenses/LICENSE-2.0 94a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 104a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Unless required by applicable law or agreed to in writing, software 114a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * distributed under the License is distributed on an "AS IS" BASIS, 124a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * See the License for the specific language governing permissions and 144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * limitations under the License. 154a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 164a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 17e478873947f995e44e8c559342462c177a420ae0JP Abgrall// #define LOG_NDEBUG 0 18db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 19db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* 20db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * The CommandListener, FrameworkListener don't allow for 21db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * multiple calls in parallel to reach the BandwidthController. 22db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * If they ever were to allow it, then netd/ would need some tweaking. 23db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */ 24db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <errno.h> 264a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <fcntl.h> 27db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall#include <stdio.h> 288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <stdlib.h> 294a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <string.h> 304a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 314a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/socket.h> 324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/stat.h> 334a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/types.h> 344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/wait.h> 354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 364a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/netlink.h> 374a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/rtnetlink.h> 384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/pkt_sched.h> 394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#define LOG_TAG "BandwidthController" 414a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/log.h> 424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/properties.h> 4314150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand#include <logwrap/logwrap.h> 444a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "NetdConstants.h" 464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include "BandwidthController.h" 47baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall#include "NatController.h" /* For LOCAL_TETHER_COUNTERS_CHAIN */ 48baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall#include "ResponseCode.h" 494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 50db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* Alphabetical */ 5192009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall#define ALERT_IPT_TEMPLATE "%s %s -m quota2 ! --quota %lld --name %s" 52c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallconst char BandwidthController::ALERT_GLOBAL_NAME[] = "globalAlert"; 538e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_INPUT = "bw_INPUT"; 548e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_FORWARD = "bw_FORWARD"; 558e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_OUTPUT = "bw_OUTPUT"; 568e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_RAW_PREROUTING = "bw_raw_PREROUTING"; 578e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* BandwidthController::LOCAL_MANGLE_POSTROUTING = "bw_mangle_POSTROUTING"; 58db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int BandwidthController::MAX_CMD_ARGS = 32; 59db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int BandwidthController::MAX_CMD_LEN = 1024; 60db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int BandwidthController::MAX_IFACENAME_LEN = 64; 61db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst int BandwidthController::MAX_IPT_OUTPUT_LINE_LEN = 256; 62db7da58e8d2aa021060098057f944ef754be06e3JP 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. 6729e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall * E.g. "-I bw_INPUT -i rmnet0 --jump costly" 687e51cde19af016456fff750f745db8132f3124a5JP Abgrall * - quota'd rules in the costly chain should be before bw_penalty_box lookups. 697e51cde19af016456fff750f745db8132f3124a5JP Abgrall * - bw_happy_box rejects everything by default. 7029e8de22ad806bdcaa971ffeeb360c9f908aa346JP Abgrall * - the qtaguid counting is done at the end of the bw_INPUT/bw_OUTPUT user chains. 714a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 724a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * global quota vs per interface quota 734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - global quota for all costly interfaces uses a single costly chain: 744a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * . initial rules 757e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -N bw_costly_shared 767e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -I bw_INPUT -i iface0 --jump bw_costly_shared 777e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -I bw_OUTPUT -o iface0 --jump bw_costly_shared 787e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -I bw_costly_shared -m quota \! --quota 500000 \ 79bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * --jump REJECT --reject-with icmp-net-prohibited 807e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -A bw_costly_shared --jump bw_penalty_box 81e478873947f995e44e8c559342462c177a420ae0JP Abgrall * If the happy box is enabled, 827e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -A bw_penalty_box --jump bw_happy_box 838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall * 844a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * . adding a new iface to this, E.g.: 857e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -I bw_INPUT -i iface1 --jump bw_costly_shared 867e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -I bw_OUTPUT -o iface1 --jump bw_costly_shared 874a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 884a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - quota per interface. This is achieve by having "costly" chains per quota. 894a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g. adding a new costly interface iface0 with its own quota: 907e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -N bw_costly_iface0 917e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -I bw_INPUT -i iface0 --jump bw_costly_iface0 927e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -I bw_OUTPUT -o iface0 --jump bw_costly_iface0 937e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -A bw_costly_iface0 -m quota \! --quota 500000 \ 94e478873947f995e44e8c559342462c177a420ae0JP Abgrall * --jump REJECT --reject-with icmp-port-unreachable 957e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -A bw_costly_iface0 --jump bw_penalty_box 964a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 977e51cde19af016456fff750f745db8132f3124a5JP Abgrall * * bw_penalty_box handling: 987e51cde19af016456fff750f745db8132f3124a5JP Abgrall * - only one bw_penalty_box for all interfaces 997e51cde19af016456fff750f745db8132f3124a5JP Abgrall * E.g Adding an app, it has to preserve the appened bw_happy_box, so "-I": 1007e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -I bw_penalty_box -m owner --uid-owner app_3 \ 101e478873947f995e44e8c559342462c177a420ae0JP Abgrall * --jump REJECT --reject-with icmp-port-unreachable 102e478873947f995e44e8c559342462c177a420ae0JP Abgrall * 1037e51cde19af016456fff750f745db8132f3124a5JP Abgrall * * bw_happy_box handling: 1047e51cde19af016456fff750f745db8132f3124a5JP Abgrall * - The bw_happy_box goes at the end of the penalty box. 105e478873947f995e44e8c559342462c177a420ae0JP Abgrall * E.g Adding a happy app, 1067e51cde19af016456fff750f745db8132f3124a5JP Abgrall * iptables -I bw_happy_box -m owner --uid-owner app_3 \ 107e478873947f995e44e8c559342462c177a420ae0JP Abgrall * --jump RETURN 1084a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 1090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char *BandwidthController::IPT_FLUSH_COMMANDS[] = { 1100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall /* 1110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Cleanup rules. 1127e51cde19af016456fff750f745db8132f3124a5JP Abgrall * Should normally include bw_costly_<iface>, but we rely on the way they are setup 1130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * to allow coexistance. 11439f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall */ 1150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-F bw_INPUT", 1160031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-F bw_OUTPUT", 1170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-F bw_FORWARD", 1187e51cde19af016456fff750f745db8132f3124a5JP Abgrall "-F bw_happy_box", 1197e51cde19af016456fff750f745db8132f3124a5JP Abgrall "-F bw_penalty_box", 1207e51cde19af016456fff750f745db8132f3124a5JP Abgrall "-F bw_costly_shared", 121f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall 122f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall "-t raw -F bw_raw_PREROUTING", 123f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall "-t mangle -F bw_mangle_POSTROUTING", 1240031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}; 1250031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 1260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall/* The cleanup commands assume flushing has been done. */ 1270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallconst char *BandwidthController::IPT_CLEANUP_COMMANDS[] = { 1287e51cde19af016456fff750f745db8132f3124a5JP Abgrall "-X bw_happy_box", 1297e51cde19af016456fff750f745db8132f3124a5JP Abgrall "-X bw_penalty_box", 1307e51cde19af016456fff750f745db8132f3124a5JP Abgrall "-X bw_costly_shared", 1310dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 133db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_SETUP_COMMANDS[] = { 1347e51cde19af016456fff750f745db8132f3124a5JP Abgrall "-N bw_happy_box", 1357e51cde19af016456fff750f745db8132f3124a5JP Abgrall "-N bw_penalty_box", 1367e51cde19af016456fff750f745db8132f3124a5JP Abgrall "-N bw_costly_shared", 1370dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1380dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 139db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallconst char *BandwidthController::IPT_BASIC_ACCOUNTING_COMMANDS[] = { 1400031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-A bw_INPUT -m owner --socket-exists", /* This is a tracking rule. */ 1410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 1420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall "-A bw_OUTPUT -m owner --socket-exists", /* This is a tracking rule. */ 1430dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 1447e51cde19af016456fff750f745db8132f3124a5JP Abgrall "-A bw_costly_shared --jump bw_penalty_box", 145f66d6e9db6be3e94b80c59fab99e237d2e2968c5JP Abgrall 14692009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall "-t raw -A bw_raw_PREROUTING -m owner --socket-exists", /* This is a tracking rule. */ 14792009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall "-t mangle -A bw_mangle_POSTROUTING -m owner --socket-exists", /* This is a tracking rule. */ 1480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallBandwidthController::BandwidthController(void) { 1514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 1524a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 153a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrallint BandwidthController::runIpxtablesCmd(const char *cmd, IptJumpOp jumpHandling, 154ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall IptFailureLog failureHandling) { 1550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 1568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 1573fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("runIpxtablesCmd(cmd=%s)", cmd); 158a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIptablesCmd(cmd, jumpHandling, IptIpV4, failureHandling); 159a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIptablesCmd(cmd, jumpHandling, IptIpV6, failureHandling); 1600dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 1610dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 1620dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 16326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::StrncpyAndCheck(char *buffer, const char *src, size_t buffSize) { 16426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 16526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall memset(buffer, '\0', buffSize); // strncpy() is not filling leftover with '\0' 16626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall strncpy(buffer, src, buffSize); 16726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return buffer[buffSize - 1]; 16826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall} 16926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 170a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrallint BandwidthController::runIptablesCmd(const char *cmd, IptJumpOp jumpHandling, 171ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall IptIpVer iptVer, IptFailureLog failureHandling) { 17226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall char buffer[MAX_CMD_LEN]; 1734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall const char *argv[MAX_CMD_ARGS]; 17426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall int argc = 0; 1754a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char *next = buffer; 1764a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char *tmp; 17711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall int res; 17814150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand int status = 0; 1794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1800dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string fullCmd = cmd; 18126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 182a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall switch (jumpHandling) { 183a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall case IptJumpReject: 184340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall /* 185340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall * Must be carefull what one rejects with, as uper layer protocols will just 186340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall * keep on hammering the device until the number of retries are done. 187340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall * For port-unreachable (default), TCP should consider as an abort (RFC1122). 188340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall */ 189340d5ccf04d4d441d8dd1788a7925d0313038b7cJP Abgrall fullCmd += " --jump REJECT"; 190a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall break; 191a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall case IptJumpReturn: 192a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall fullCmd += " --jump RETURN"; 193a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall break; 194a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall case IptJumpNoAdd: 195a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall break; 1960dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 1970dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 19811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall fullCmd.insert(0, " "); 19911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall fullCmd.insert(0, iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH); 2004a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 20114150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) { 20214150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand ALOGE("iptables command too long"); 20314150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand return -1; 20414150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand } 20514150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand 20614150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand argc = 0; 20714150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand while ((tmp = strsep(&next, " "))) { 20814150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand argv[argc++] = tmp; 20914150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand if (argc >= MAX_CMD_ARGS) { 21014150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand ALOGE("iptables argument overflow"); 2114a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return -1; 2124a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 21314150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand } 214fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 21514150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand argv[argc] = NULL; 21614150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand res = android_fork_execvp(argc, (char **)argv, &status, false, 21714150215fcd9060c25a25930e85057df5904f6f6Rom Lemarchand failureHandling == IptFailShow); 218c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall res = res || !WIFEXITED(status) || WEXITSTATUS(status); 219c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall if (res && failureHandling == IptFailShow) { 220c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall ALOGE("runIptablesCmd(): res=%d status=%d failed %s", res, status, 221c8dc63b14f5bcef34a23061c17d3bbe66df51429JP Abgrall fullCmd.c_str()); 22211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 22311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall return res; 2244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2254a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2260e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrallvoid BandwidthController::flushCleanTables(bool doClean) { 2270e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall /* Flush and remove the bw_costly_<iface> tables */ 2280e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall flushExistingCostlyTables(doClean); 2290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall /* Some of the initialCommands are allowed to fail */ 2310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall runCommands(sizeof(IPT_FLUSH_COMMANDS) / sizeof(char*), 2320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall IPT_FLUSH_COMMANDS, RunCmdFailureOk); 2330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2340e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall if (doClean) { 2350e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall runCommands(sizeof(IPT_CLEANUP_COMMANDS) / sizeof(char*), 2360e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall IPT_CLEANUP_COMMANDS, RunCmdFailureOk); 2370e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall } 2380e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall} 2390e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall 2400e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrallint BandwidthController::setupIptablesHooks(void) { 2410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2420e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall /* flush+clean is allowed to fail */ 2430e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall flushCleanTables(true); 2440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall runCommands(sizeof(IPT_SETUP_COMMANDS) / sizeof(char*), 2450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall IPT_SETUP_COMMANDS, RunCmdFailureBad); 2460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return 0; 2480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall} 2490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2500031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint BandwidthController::enableBandwidthControl(bool force) { 251fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res; 2520031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall char value[PROPERTY_VALUE_MAX]; 2530031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 2540031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall if (!force) { 2550031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall property_get("persist.bandwidth.enable", value, "1"); 2560031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall if (!strcmp(value, "0")) 2570031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return 0; 2580031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall } 2598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 260db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Let's pretend we started from scratch ... */ 2618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedQuotaIfaces.clear(); 2628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall quotaIfaces.clear(); 2638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall naughtyAppUids.clear(); 264e478873947f995e44e8c559342462c177a420ae0JP Abgrall niceAppUids.clear(); 265db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall globalAlertBytes = 0; 266c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall globalAlertTetherCount = 0; 267db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall sharedQuotaBytes = sharedAlertBytes = 0; 268db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 2690e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall flushCleanTables(false); 2700e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall res = runCommands(sizeof(IPT_BASIC_ACCOUNTING_COMMANDS) / sizeof(char*), 271db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall IPT_BASIC_ACCOUNTING_COMMANDS, RunCmdFailureBad); 2728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 273fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 2744a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2754a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2764a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2774a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::disableBandwidthControl(void) { 2780e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall 2790e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall flushCleanTables(false); 280fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return 0; 2814a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2824a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runCommands(int numCommands, const char *commands[], 2848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall RunCmdErrHandling cmdErrHandling) { 285fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 286ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall IptFailureLog failureLogging = IptFailShow; 287ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall if (cmdErrHandling == RunCmdFailureOk) { 288ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall failureLogging = IptFailHide; 289ad729ac11e080b1f1bdd9cd32807d9ae74ce2a63JP Abgrall } 2903fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("runCommands(): %d commands", numCommands); 291fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) { 292a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res = runIpxtablesCmd(commands[cmdNum], IptJumpNoAdd, failureLogging); 2930031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall if (res && cmdErrHandling != RunCmdFailureOk) 294fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 295fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 2960031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return 0; 297fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 298fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 299a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrallstd::string BandwidthController::makeIptablesSpecialAppCmd(IptOp op, int uid, const char *chain) { 300fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string res; 3018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *buff; 3028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 303fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 304fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall switch (op) { 3058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 3068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 3078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 308109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall case IptOpAppend: 309a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall ALOGE("Append op not supported for %s uids", chain); 310a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res = ""; 311a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall return res; 312109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall break; 3138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 3148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 3158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 3168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 3178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 3188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 3198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 320fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 321a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall asprintf(&buff, "%s %s -m owner --uid-owner %d", opFlag, chain, uid); 3228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = buff; 3238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(buff); 324fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 325fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 326fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 327e478873947f995e44e8c559342462c177a420ae0JP Abgrallint BandwidthController::enableHappyBox(void) { 328e478873947f995e44e8c559342462c177a420ae0JP Abgrall char cmd[MAX_CMD_LEN]; 329e478873947f995e44e8c559342462c177a420ae0JP Abgrall int res = 0; 330e478873947f995e44e8c559342462c177a420ae0JP Abgrall 331e478873947f995e44e8c559342462c177a420ae0JP Abgrall /* 332e478873947f995e44e8c559342462c177a420ae0JP Abgrall * We tentatively delete before adding, which helps recovering 333e478873947f995e44e8c559342462c177a420ae0JP Abgrall * from bad states (e.g. netd died). 334e478873947f995e44e8c559342462c177a420ae0JP Abgrall */ 335e478873947f995e44e8c559342462c177a420ae0JP Abgrall 336e478873947f995e44e8c559342462c177a420ae0JP Abgrall /* Should not exist, but ignore result if already there. */ 3377e51cde19af016456fff750f745db8132f3124a5JP Abgrall snprintf(cmd, sizeof(cmd), "-N bw_happy_box"); 338e478873947f995e44e8c559342462c177a420ae0JP Abgrall runIpxtablesCmd(cmd, IptJumpNoAdd); 339e478873947f995e44e8c559342462c177a420ae0JP Abgrall 340e478873947f995e44e8c559342462c177a420ae0JP Abgrall /* Should be empty, but clear in case something was wrong. */ 341e478873947f995e44e8c559342462c177a420ae0JP Abgrall niceAppUids.clear(); 3427e51cde19af016456fff750f745db8132f3124a5JP Abgrall snprintf(cmd, sizeof(cmd), "-F bw_happy_box"); 343e478873947f995e44e8c559342462c177a420ae0JP Abgrall res |= runIpxtablesCmd(cmd, IptJumpNoAdd); 344e478873947f995e44e8c559342462c177a420ae0JP Abgrall 3457e51cde19af016456fff750f745db8132f3124a5JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_penalty_box -j bw_happy_box"); 346e478873947f995e44e8c559342462c177a420ae0JP Abgrall runIpxtablesCmd(cmd, IptJumpNoAdd); 3477e51cde19af016456fff750f745db8132f3124a5JP Abgrall snprintf(cmd, sizeof(cmd), "-A bw_penalty_box -j bw_happy_box"); 348e478873947f995e44e8c559342462c177a420ae0JP Abgrall res |= runIpxtablesCmd(cmd, IptJumpNoAdd); 349e478873947f995e44e8c559342462c177a420ae0JP Abgrall 350e478873947f995e44e8c559342462c177a420ae0JP Abgrall /* Reject. Defaulting to prot-unreachable */ 3517e51cde19af016456fff750f745db8132f3124a5JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_happy_box -j REJECT"); 352e478873947f995e44e8c559342462c177a420ae0JP Abgrall runIpxtablesCmd(cmd, IptJumpNoAdd); 3537e51cde19af016456fff750f745db8132f3124a5JP Abgrall snprintf(cmd, sizeof(cmd), "-A bw_happy_box -j REJECT"); 354e478873947f995e44e8c559342462c177a420ae0JP Abgrall res |= runIpxtablesCmd(cmd, IptJumpNoAdd); 355e478873947f995e44e8c559342462c177a420ae0JP Abgrall 356e478873947f995e44e8c559342462c177a420ae0JP Abgrall return res; 357e478873947f995e44e8c559342462c177a420ae0JP Abgrall} 358e478873947f995e44e8c559342462c177a420ae0JP Abgrall 359e478873947f995e44e8c559342462c177a420ae0JP Abgrallint BandwidthController::disableHappyBox(void) { 360e478873947f995e44e8c559342462c177a420ae0JP Abgrall char cmd[MAX_CMD_LEN]; 361e478873947f995e44e8c559342462c177a420ae0JP Abgrall 362e478873947f995e44e8c559342462c177a420ae0JP Abgrall /* Best effort */ 3637e51cde19af016456fff750f745db8132f3124a5JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_penalty_box -j bw_happy_box"); 364e478873947f995e44e8c559342462c177a420ae0JP Abgrall runIpxtablesCmd(cmd, IptJumpNoAdd); 365e478873947f995e44e8c559342462c177a420ae0JP Abgrall niceAppUids.clear(); 3667e51cde19af016456fff750f745db8132f3124a5JP Abgrall snprintf(cmd, sizeof(cmd), "-F bw_happy_box"); 367e478873947f995e44e8c559342462c177a420ae0JP Abgrall runIpxtablesCmd(cmd, IptJumpNoAdd); 3687e51cde19af016456fff750f745db8132f3124a5JP Abgrall snprintf(cmd, sizeof(cmd), "-X bw_happy_box"); 369e478873947f995e44e8c559342462c177a420ae0JP Abgrall runIpxtablesCmd(cmd, IptJumpNoAdd); 370e478873947f995e44e8c559342462c177a420ae0JP Abgrall 371e478873947f995e44e8c559342462c177a420ae0JP Abgrall return 0; 372e478873947f995e44e8c559342462c177a420ae0JP Abgrall} 373e478873947f995e44e8c559342462c177a420ae0JP Abgrall 374fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::addNaughtyApps(int numUids, char *appUids[]) { 375a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall return manipulateNaughtyApps(numUids, appUids, SpecialAppOpAdd); 376fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 377fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 378fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeNaughtyApps(int numUids, char *appUids[]) { 379a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall return manipulateNaughtyApps(numUids, appUids, SpecialAppOpRemove); 380fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 381fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 382e478873947f995e44e8c559342462c177a420ae0JP Abgrallint BandwidthController::addNiceApps(int numUids, char *appUids[]) { 383e478873947f995e44e8c559342462c177a420ae0JP Abgrall return manipulateNiceApps(numUids, appUids, SpecialAppOpAdd); 384e478873947f995e44e8c559342462c177a420ae0JP Abgrall} 385e478873947f995e44e8c559342462c177a420ae0JP Abgrall 386e478873947f995e44e8c559342462c177a420ae0JP Abgrallint BandwidthController::removeNiceApps(int numUids, char *appUids[]) { 387e478873947f995e44e8c559342462c177a420ae0JP Abgrall return manipulateNiceApps(numUids, appUids, SpecialAppOpRemove); 388e478873947f995e44e8c559342462c177a420ae0JP Abgrall} 389e478873947f995e44e8c559342462c177a420ae0JP Abgrall 390a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrallint BandwidthController::manipulateNaughtyApps(int numUids, char *appStrUids[], SpecialAppOp appOp) { 3917e51cde19af016456fff750f745db8132f3124a5JP Abgrall return manipulateSpecialApps(numUids, appStrUids, "bw_penalty_box", naughtyAppUids, IptJumpReject, appOp); 392a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall} 393a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall 394e478873947f995e44e8c559342462c177a420ae0JP Abgrallint BandwidthController::manipulateNiceApps(int numUids, char *appStrUids[], SpecialAppOp appOp) { 3957e51cde19af016456fff750f745db8132f3124a5JP Abgrall return manipulateSpecialApps(numUids, appStrUids, "bw_happy_box", niceAppUids, IptJumpReturn, appOp); 396e478873947f995e44e8c559342462c177a420ae0JP Abgrall} 397e478873947f995e44e8c559342462c177a420ae0JP Abgrall 398a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall 399a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrallint BandwidthController::manipulateSpecialApps(int numUids, char *appStrUids[], 400a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall const char *chain, 401a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall std::list<int /*appUid*/> &specialAppUids, 402a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall IptJumpOp jumpHandling, SpecialAppOp appOp) { 403a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall 404fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall char cmd[MAX_CMD_LEN]; 405fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int uidNum; 40626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *failLogTemplate; 40726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall IptOp op; 408fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int appUids[numUids]; 409a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall std::string iptCmd; 410b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall std::list<int /*uid*/>::iterator it; 4118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 41226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (appOp) { 413a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall case SpecialAppOpAdd: 4148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall op = IptOpInsert; 415af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall failLogTemplate = "Failed to add app uid %s(%d) to %s."; 4168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 417a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall case SpecialAppOpRemove: 4188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall op = IptOpDelete; 419af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall failLogTemplate = "Failed to delete app uid %s(%d) from %s box."; 4208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 4210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall default: 4220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall ALOGE("Unexpected app Op %d", appOp); 4230031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return -1; 42426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 42526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 426fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (uidNum = 0; uidNum < numUids; uidNum++) { 427af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall char *end; 428af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall appUids[uidNum] = strtoul(appStrUids[uidNum], &end, 0); 429af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall if (*end || !*appStrUids[uidNum]) { 430af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall ALOGE(failLogTemplate, appStrUids[uidNum], appUids[uidNum], chain); 431fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_parse; 432fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 433fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 434fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 435fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (uidNum = 0; uidNum < numUids; uidNum++) { 436b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall int uid = appUids[uidNum]; 437a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall for (it = specialAppUids.begin(); it != specialAppUids.end(); it++) { 438b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall if (*it == uid) 439b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall break; 440b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall } 441a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall bool found = (it != specialAppUids.end()); 442b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall 443a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall if (appOp == SpecialAppOpRemove) { 444b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall if (!found) { 445b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall ALOGE("No such appUid %d to remove", uid); 446b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall return -1; 447b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall } 448a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall specialAppUids.erase(it); 449b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall } else { 450b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall if (found) { 451b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall ALOGE("appUid %d exists already", uid); 452b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall return -1; 453b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall } 454a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall specialAppUids.push_front(uid); 455b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall } 456b1d24094c2c5d48bbb3dfad4a0551ff0bf77ce6cJP Abgrall 457a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall iptCmd = makeIptablesSpecialAppCmd(op, uid, chain); 458a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall if (runIpxtablesCmd(iptCmd.c_str(), jumpHandling)) { 459af476f7b659beff8315a83f094ce697c5179dae6JP Abgrall ALOGE(failLogTemplate, appStrUids[uidNum], uid, chain); 460fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_with_uidNum; 461fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 462fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 463fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return 0; 464fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 46526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_with_uidNum: 466fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* Try to remove the uid that failed in any case*/ 467a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall iptCmd = makeIptablesSpecialAppCmd(IptOpDelete, appUids[uidNum], chain); 468a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall runIpxtablesCmd(iptCmd.c_str(), jumpHandling); 46926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_parse: 47026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 4714a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 4724a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 47326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallstd::string BandwidthController::makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota) { 474fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string res; 4758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *buff; 4768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 4770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 4783fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("makeIptablesQuotaCmd(%d, %lld)", op, quota); 4790dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 480fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall switch (op) { 4818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 4828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 4838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 484109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall case IptOpAppend: 485109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall opFlag = "-A"; 486109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall break; 4878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 4888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 4898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 4908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 4918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 4928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 4938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 494fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 4958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 496bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall // The requried IP version specific --jump REJECT ... will be added later. 4977e51cde19af016456fff750f745db8132f3124a5JP Abgrall asprintf(&buff, "%s bw_costly_%s -m quota2 ! --quota %lld --name %s", opFlag, costName, quota, 4988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall costName); 4998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = buff; 5008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(buff); 5010dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 5020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 5030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 50426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::prepCostlyIface(const char *ifn, QuotaType quotaType) { 5050dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char cmd[MAX_CMD_LEN]; 5060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall int res = 0, res1, res2; 5078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int ruleInsertPos = 1; 5080dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string costString; 5090dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall const char *costCString; 5100dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5110dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* The "-N costly" is created upfront, no need to handle it here. */ 51226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (quotaType) { 51326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaUnique: 5147e51cde19af016456fff750f745db8132f3124a5JP Abgrall costString = "bw_costly_"; 5150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costString += ifn; 5160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costCString = costString.c_str(); 5170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall /* 5187e51cde19af016456fff750f745db8132f3124a5JP Abgrall * Flush the bw_costly_<iface> is allowed to fail in case it didn't exist. 5190031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Creating a new one is allowed to fail in case it existed. 5200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * This helps with netd restarts. 5210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall */ 5220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-F %s", costCString); 523a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res1 = runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide); 5240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-N %s", costCString); 525a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res2 = runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide); 5260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall res = (res1 && res2) || (!res1 && !res2); 5270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 5287e51cde19af016456fff750f745db8132f3124a5JP Abgrall snprintf(cmd, sizeof(cmd), "-A %s -j bw_penalty_box", costCString); 529a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(cmd, IptJumpNoAdd); 53026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 53126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaShared: 5327e51cde19af016456fff750f745db8132f3124a5JP Abgrall costCString = "bw_costly_shared"; 53326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 5340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall default: 5350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall ALOGE("Unexpected quotatype %d", quotaType); 5360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return -1; 5370dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5380dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (globalAlertBytes) { 5408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* The alert rule comes 1st */ 5418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ruleInsertPos = 2; 5428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 5430031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 5440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_INPUT -i %s --jump %s", ifn, costCString); 545a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide); 5460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 5470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-I bw_INPUT %d -i %s --jump %s", ruleInsertPos, ifn, costCString); 548a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(cmd, IptJumpNoAdd); 5490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 5500031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_OUTPUT -o %s --jump %s", ifn, costCString); 551a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide); 5520031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall 5530031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-I bw_OUTPUT %d -o %s --jump %s", ruleInsertPos, ifn, costCString); 554a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(cmd, IptJumpNoAdd); 5550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 5560dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 5570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 55826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::cleanupCostlyIface(const char *ifn, QuotaType quotaType) { 5590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char cmd[MAX_CMD_LEN]; 5600dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 5610dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string costString; 5620dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall const char *costCString; 5630dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 56426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (quotaType) { 56526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaUnique: 5667e51cde19af016456fff750f745db8132f3124a5JP Abgrall costString = "bw_costly_"; 5670dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costString += ifn; 5680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costCString = costString.c_str(); 56926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 57026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaShared: 5717e51cde19af016456fff750f745db8132f3124a5JP Abgrall costCString = "bw_costly_shared"; 57226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 5730031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall default: 5740031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall ALOGE("Unexpected quotatype %d", quotaType); 5750031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall return -1; 5760dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5780031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_INPUT -i %s --jump %s", ifn, costCString); 579a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(cmd, IptJumpNoAdd); 5800031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall snprintf(cmd, sizeof(cmd), "-D bw_OUTPUT -o %s --jump %s", ifn, costCString); 581a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(cmd, IptJumpNoAdd); 5820dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5837e51cde19af016456fff750f745db8132f3124a5JP Abgrall /* The "-N bw_costly_shared" is created upfront, no need to handle it here. */ 58426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (quotaType == QuotaUnique) { 5850dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-F %s", costCString); 586a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(cmd, IptJumpNoAdd); 587a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall snprintf(cmd, sizeof(cmd), "-X %s", costCString); 588a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(cmd, IptJumpNoAdd); 589fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 590fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 591fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 5924a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 5930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceSharedQuota(const char *iface, int64_t maxBytes) { 5944a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char cmd[MAX_CMD_LEN]; 5954a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char ifn[MAX_IFACENAME_LEN]; 596fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 59726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string quotaCmd; 5988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::string ifaceName; 5998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ; 600bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall const char *costName = "shared"; 60126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<std::string>::iterator it; 6024a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 6038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!maxBytes) { 6048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* Don't talk about -1, deprecate it. */ 6055ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 6068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 6078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 60826e0d49fa743d7881104196a9eda733bd2aac92fJP 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; 6134a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 6144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (maxBytes == -1) { 615fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return removeInterfaceSharedQuota(ifn); 6164a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 6174a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 6184a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* Insert ingress quota. */ 6190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) { 6200dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (*it == ifaceName) 621fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 6224a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 623fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 6240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == sharedQuotaIfaces.end()) { 62526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= prepCostlyIface(ifn, QuotaShared); 6260dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (sharedQuotaIfaces.empty()) { 6270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes); 628a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptJumpReject); 6294a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (res) { 6305ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed set quota rule"); 631fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail; 6324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 633fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = maxBytes; 634fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 6350dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall sharedQuotaIfaces.push_front(ifaceName); 636fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 637fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 638fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 639fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (maxBytes != sharedQuotaBytes) { 6408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= updateQuota(costName, maxBytes); 641fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (res) { 6425ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed update quota for %s", costName); 643fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail; 644fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 645fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = maxBytes; 6464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 6474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return 0; 648fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 649fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall fail: 6504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* 6514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse 6524a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * rules in the kernel to see which ones need cleaning up. 653fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * For now callers needs to choose if they want to "ndc bandwidth enable" 654fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * which resets everything. 6554a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 656fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall removeInterfaceSharedQuota(ifn); 6574a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return -1; 6584a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 6594a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 6608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall/* It will also cleanup any shared alerts */ 661fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeInterfaceSharedQuota(const char *iface) { 6624a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char ifn[MAX_IFACENAME_LEN]; 663fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 66426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 6650dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::list<std::string>::iterator it; 666bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall const char *costName = "shared"; 6674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 6688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 6695ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 67026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 67126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 6728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ifaceName = ifn; 67326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 6740dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) { 6750dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (*it == ifaceName) 676fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 6774a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 6780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == sharedQuotaIfaces.end()) { 6795ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No such iface %s to delete", ifn); 680fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return -1; 6814a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 682fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 68326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= cleanupCostlyIface(ifn, QuotaShared); 6840dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall sharedQuotaIfaces.erase(it); 685fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 6860dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (sharedQuotaIfaces.empty()) { 687fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string quotaCmd; 688bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, sharedQuotaBytes); 689a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptJumpReject); 6908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedQuotaBytes = 0; 6918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (sharedAlertBytes) { 6928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall removeSharedAlert(); 6938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedAlertBytes = 0; 6948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 695fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 6964a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return res; 6974a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 6980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceQuota(const char *iface, int64_t maxBytes) { 7000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char ifn[MAX_IFACENAME_LEN]; 7010dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 70226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 70326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *costName; 70426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<QuotaInfo>::iterator it; 70526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string quotaCmd; 7060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!maxBytes) { 7088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* Don't talk about -1, deprecate it. */ 7095ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 7108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7120dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (maxBytes == -1) { 71326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return removeInterfaceQuota(iface); 7140dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 7150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 7175ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 71826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 71926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 72026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 72126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall costName = iface; 72226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 7230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* Insert ingress quota. */ 7240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 7258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == ifaceName) 7260dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall break; 7270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 7280dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == quotaIfaces.end()) { 730e478873947f995e44e8c559342462c177a420ae0JP Abgrall /* Preparing the iface adds a penalty/happy box check */ 73126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= prepCostlyIface(ifn, QuotaUnique); 732baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall /* 733e478873947f995e44e8c559342462c177a420ae0JP Abgrall * The rejecting quota limit should go after the penalty/happy box checks 734baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * or else a naughty app could just eat up the quota. 735baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * So we append here. 736baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall */ 737109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpAppend, costName, maxBytes); 738a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptJumpReject); 7390dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (res) { 7405ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed set quota rule"); 7410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall goto fail; 7420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 7430dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall quotaIfaces.push_front(QuotaInfo(ifaceName, maxBytes, 0)); 7450dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7460dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } else { 7478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= updateQuota(costName, maxBytes); 7480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (res) { 7495ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed update quota for %s", iface); 7500dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall goto fail; 7510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 7528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall it->quota = maxBytes; 7530dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 7540dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return 0; 7550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7560dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall fail: 7570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* 7580dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse 7590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * rules in the kernel to see which ones need cleaning up. 7600dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * For now callers needs to choose if they want to "ndc bandwidth enable" 7610dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * which resets everything. 7620dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall */ 7630dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall removeInterfaceSharedQuota(ifn); 7640dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return -1; 7650dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 7660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceSharedQuota(int64_t *bytes) { 7688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return getInterfaceQuota("shared", bytes); 7698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceQuota(const char *costName, int64_t *bytes) { 7728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall FILE *fp; 7738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *fname; 7748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int scanRes; 7758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&fname, "/proc/net/xt_quota/%s", costName); 7778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fp = fopen(fname, "r"); 7788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(fname); 7798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!fp) { 7805ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Reading quota %s failed (%s)", costName, strerror(errno)); 7818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall scanRes = fscanf(fp, "%lld", bytes); 7843fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("Read quota res=%d bytes=%lld", scanRes, *bytes); 7858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fclose(fp); 7868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return scanRes == 1 ? 0 : -1; 7878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7890dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::removeInterfaceQuota(const char *iface) { 7900dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7910dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char ifn[MAX_IFACENAME_LEN]; 7920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 79326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 79426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *costName; 79526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<QuotaInfo>::iterator it; 7960dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 7978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 7985ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 79926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 80026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 80126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 80226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall costName = iface; 8030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 8040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 8058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == ifaceName) 8060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall break; 8070dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 8080dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 8090dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == quotaIfaces.end()) { 8105ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No such iface %s to delete", ifn); 8110dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return -1; 8120dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 8130dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 8140dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* This also removes the quota command of CostlyIface chain. */ 81526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= cleanupCostlyIface(ifn, QuotaUnique); 8160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 8170dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaIfaces.erase(it); 8180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 8190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 8200dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 8218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::updateQuota(const char *quotaName, int64_t bytes) { 8238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall FILE *fp; 8248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *fname; 8258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&fname, "/proc/net/xt_quota/%s", quotaName); 8278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fp = fopen(fname, "w"); 8288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(fname); 8298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!fp) { 8305ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Updating quota %s failed (%s)", quotaName, strerror(errno)); 8318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 8328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fprintf(fp, "%lld\n", bytes); 8348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fclose(fp); 8358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return 0; 8368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesAlertCmd(IptOp op, const char *alertName, int64_t bytes) { 8398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 8408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 8418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 8428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall switch (op) { 8448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 8458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 8468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 847109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall case IptOpAppend: 848109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall opFlag = "-A"; 849109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall break; 8508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 8518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 8528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 8538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 8548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 8558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 8568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 8578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 8588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 85992009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_INPUT", 860c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich bytes, alertName); 861a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd); 8628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 86392009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_OUTPUT", 864c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich bytes, alertName); 865a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd); 8668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 8678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 8688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 8698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 870c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::runIptablesAlertFwdCmd(IptOp op, const char *alertName, int64_t bytes) { 871c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall int res = 0; 872c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *opFlag; 8738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 874c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 875c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall switch (op) { 876c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall case IptOpInsert: 877c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall opFlag = "-I"; 878c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall break; 879109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall case IptOpAppend: 880109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall opFlag = "-A"; 881109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall break; 882c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall case IptOpReplace: 883c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall opFlag = "-R"; 884c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall break; 885c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall default: 886c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall case IptOpDelete: 887c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall opFlag = "-D"; 888c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall break; 889c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 890c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 89192009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "bw_FORWARD", 892c2b26cb83d9bf3f91e986625efcc40fc8eb79a13Nick Kralevich bytes, alertName); 893a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res = runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd); 894c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall free(alertQuotaCmd); 895c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return res; 896c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall} 897c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 898c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlert(int64_t bytes) { 899c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 9008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 9018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 9035ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 9048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 9058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (globalAlertBytes) { 9078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = updateQuota(alertName, bytes); 9088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } else { 9098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = runIptablesAlertCmd(IptOpInsert, alertName, bytes); 910c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (globalAlertTetherCount) { 9113fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("setGlobalAlert for %d tether", globalAlertTetherCount); 912c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res |= runIptablesAlertFwdCmd(IptOpInsert, alertName, bytes); 913c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 9148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall globalAlertBytes = bytes; 9168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 9178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 9188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 919c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::setGlobalAlertInForwardChain(void) { 920c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 921c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall int res = 0; 922c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 923c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall globalAlertTetherCount++; 9243fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("setGlobalAlertInForwardChain(): %d tether", globalAlertTetherCount); 925c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 926c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* 927c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is no globalAlert active we are done. 928c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is an active globalAlert but this is not the 1st 929c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * tether, we are also done. 930c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall */ 931c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (!globalAlertBytes || globalAlertTetherCount != 1) { 932c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return 0; 933c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 934c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 935c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* We only add the rule if this was the 1st tether added. */ 936c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res = runIptablesAlertFwdCmd(IptOpInsert, alertName, globalAlertBytes); 937c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return res; 938c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall} 939c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 9408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeGlobalAlert(void) { 9418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 942c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 9438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 9448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!globalAlertBytes) { 9465ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set"); 9478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 9488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = runIptablesAlertCmd(IptOpDelete, alertName, globalAlertBytes); 950c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (globalAlertTetherCount) { 951c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res |= runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes); 952c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 9538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall globalAlertBytes = 0; 9548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 9558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 9568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 957c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrallint BandwidthController::removeGlobalAlertInForwardChain(void) { 958c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall int res = 0; 959c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall const char *alertName = ALERT_GLOBAL_NAME; 960c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 961c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (!globalAlertTetherCount) { 9625ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set"); 963c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return -1; 964c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 965c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 966c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall globalAlertTetherCount--; 967c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* 968c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is no globalAlert active we are done. 969c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * If there is an active globalAlert but there are more 970c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall * tethers, we are also done. 971c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall */ 972c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall if (!globalAlertBytes || globalAlertTetherCount >= 1) { 973c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return 0; 974c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall } 975c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 976c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall /* We only detete the rule if this was the last tether removed. */ 977c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall res = runIptablesAlertFwdCmd(IptOpDelete, alertName, globalAlertBytes); 978c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall return res; 979c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall} 980c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall 9818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setSharedAlert(int64_t bytes) { 9828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!sharedQuotaBytes) { 9835ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Need to have a prior shared quota set to set an alert"); 9848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 9858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 9875ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 9888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 9898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 9908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return setCostlyAlert("shared", bytes, &sharedAlertBytes); 9918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 9928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeSharedAlert(void) { 9948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return removeCostlyAlert("shared", &sharedAlertBytes); 9958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 9968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 9978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setInterfaceAlert(const char *iface, int64_t bytes) { 9988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::list<QuotaInfo>::iterator it; 9998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 10015ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 10028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 10038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 10048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 10058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == iface) 10068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 10078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 10088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it == quotaIfaces.end()) { 10105ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Need to have a prior interface quota set to set an alert"); 10118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 10128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 10138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return setCostlyAlert(iface, bytes, &it->alert); 10158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 10168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeInterfaceAlert(const char *iface) { 10188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::list<QuotaInfo>::iterator it; 10198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 10218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == iface) 10228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 10238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 10248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it == quotaIfaces.end()) { 10265ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set for interface %s", iface); 10278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 10288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 10298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return removeCostlyAlert(iface, &it->alert); 10318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 10328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes) { 10348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 1035109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall char *chainName; 10368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 10378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertName; 10388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 10405ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Invalid bytes value. 1..max_int64."); 10418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 10428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 10438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertName, "%sAlert", costName); 10448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (*alertBytes) { 10458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = updateQuota(alertName, *alertBytes); 10468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } else { 10477e51cde19af016456fff750f745db8132f3124a5JP Abgrall asprintf(&chainName, "bw_costly_%s", costName); 1048109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-A", chainName, bytes, alertName); 1049a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd); 10508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 1051109899bc63139c5260cb9a7dc409f92efaf2c4b7JP Abgrall free(chainName); 10528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 10538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *alertBytes = bytes; 10548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertName); 10558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 10568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 10578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeCostlyAlert(const char *costName, int64_t *alertBytes) { 10598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 10608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *chainName; 10618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertName; 10628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 10638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertName, "%sAlert", costName); 10658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!*alertBytes) { 10665ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("No prior alert set for %s alert", costName); 10678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 10688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 10698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10707e51cde19af016456fff750f745db8132f3124a5JP Abgrall asprintf(&chainName, "bw_costly_%s", costName); 107192009c8effc75c2d70a6c9a1ac33ba2c60b78820JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-D", chainName, *alertBytes, alertName); 1072a9ba4cba3369e07aae05607f82424cc0075c9c34JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptJumpNoAdd); 10738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 10748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(chainName); 10758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 10768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *alertBytes = 0; 10778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertName); 10788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 10798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 1080db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1081db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall/* 1082db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Parse the ptks and bytes out of: 1083baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * Chain natctrl_tether_counters (4 references) 1084baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * pkts bytes target prot opt in out source destination 1085baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * 26 2373 RETURN all -- wlan0 rmnet0 0.0.0.0/0 0.0.0.0/0 counter wlan0_rmnet0: 0 bytes 1086baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * 27 2002 RETURN all -- rmnet0 wlan0 0.0.0.0/0 0.0.0.0/0 counter rmnet0_wlan0: 0 bytes 1087baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * 1040 107471 RETURN all -- bt-pan rmnet0 0.0.0.0/0 0.0.0.0/0 counter bt-pan_rmnet0: 0 bytes 1088baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * 1450 1708806 RETURN all -- rmnet0 bt-pan 0.0.0.0/0 0.0.0.0/0 counter rmnet0_bt-pan: 0 bytes 1089db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */ 1090baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrallint BandwidthController::parseForwardChainStats(SocketClient *cli, const TetherStats filter, 1091baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall FILE *fp, std::string &extraProcessingInfo) { 1092db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall int res; 1093db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN]; 1094db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char iface0[MAX_IPT_OUTPUT_LINE_LEN]; 1095db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char iface1[MAX_IPT_OUTPUT_LINE_LEN]; 1096db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char rest[MAX_IPT_OUTPUT_LINE_LEN]; 1097db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1098baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall TetherStats stats; 1099db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char *buffPtr; 1100db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall int64_t packets, bytes; 1101baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall int statsFound = 0; 1102baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall 1103baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall bool filterPair = filter.intIface[0] && filter.extIface[0]; 1104baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall 1105baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall char *filterMsg = filter.getStatsLine(); 1106baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall ALOGV("filter: %s", filterMsg); 1107baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall free(filterMsg); 1108baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall 1109baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats = filter; 1110db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1111db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) { 1112db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Clean up, so a failed parse can still print info */ 1113db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall iface0[0] = iface1[0] = rest[0] = packets = bytes = 0; 11140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall res = sscanf(buffPtr, "%lld %lld RETURN all -- %s %s 0.%s", 1115db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall &packets, &bytes, iface0, iface1, rest); 11163fb42e026ffebab2c8f282e42501040121e32d83Steve Block ALOGV("parse res=%d iface0=<%s> iface1=<%s> pkts=%lld bytes=%lld rest=<%s> orig line=<%s>", res, 1117db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall iface0, iface1, packets, bytes, rest, buffPtr); 1118a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall extraProcessingInfo += buffPtr; 1119a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall 1120db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall if (res != 5) { 1121db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall continue; 1122db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 1123baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall /* 1124baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * The following assumes that the 1st rule has in:extIface out:intIface, 1125baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * which is what NatController sets up. 1126baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall * If not filtering, the 1st match rx, and sets up the pair for the tx side. 1127baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall */ 1128baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall if (filter.intIface[0] && filter.extIface[0]) { 1129baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall if (filter.intIface == iface0 && filter.extIface == iface1) { 1130baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall ALOGV("2Filter RX iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets); 1131baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.rxPackets = packets; 1132baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.rxBytes = bytes; 1133baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } else if (filter.intIface == iface1 && filter.extIface == iface0) { 1134baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall ALOGV("2Filter TX iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets); 1135baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.txPackets = packets; 1136baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.txBytes = bytes; 1137baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } 1138baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } else if (filter.intIface[0] || filter.extIface[0]) { 1139baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall if (filter.intIface == iface0 || filter.extIface == iface1) { 1140baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall ALOGV("1Filter RX iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets); 1141baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.intIface = iface0; 1142baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.extIface = iface1; 1143baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.rxPackets = packets; 1144baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.rxBytes = bytes; 1145baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } else if (filter.intIface == iface1 || filter.extIface == iface0) { 1146baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall ALOGV("1Filter TX iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets); 1147baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.intIface = iface1; 1148baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.extIface = iface0; 1149baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.txPackets = packets; 1150baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.txBytes = bytes; 1151baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } 1152baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } else /* if (!filter.intFace[0] && !filter.extIface[0]) */ { 1153baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall if (!stats.intIface[0]) { 1154baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall ALOGV("0Filter RX iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets); 1155baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.intIface = iface0; 1156baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.extIface = iface1; 1157baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.rxPackets = packets; 1158baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.rxBytes = bytes; 1159baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } else if (stats.intIface == iface1 && stats.extIface == iface0) { 1160baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall ALOGV("0Filter TX iface_in=%s iface_out=%s rx_bytes=%lld rx_packets=%lld ", iface0, iface1, bytes, packets); 1161baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.txPackets = packets; 1162baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats.txBytes = bytes; 1163baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } 1164baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } 1165baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall if (stats.rxBytes != -1 && stats.txBytes != -1) { 1166baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall ALOGV("rx_bytes=%lld tx_bytes=%lld filterPair=%d", stats.rxBytes, stats.txBytes, filterPair); 1167baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall /* Send out stats, and prep for the next if needed. */ 1168baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall char *msg = stats.getStatsLine(); 1169baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall if (filterPair) { 1170baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall cli->sendMsg(ResponseCode::TetheringStatsResult, msg, false); 1171baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall return 0; 1172baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } else { 1173baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall cli->sendMsg(ResponseCode::TetheringStatsListResult, msg, false); 1174baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall stats = filter; 1175baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } 1176baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall free(msg); 1177baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall statsFound++; 1178db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 1179db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 1180baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall /* We found some stats, and the last one isn't a partial stats. */ 1181baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall if (statsFound && (stats.rxBytes == -1 || stats.txBytes == -1)) { 1182baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false); 1183baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall return 0; 1184baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall } 1185baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall return -1; 1186db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall} 1187db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1188baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrallchar *BandwidthController::TetherStats::getStatsLine(void) const { 1189db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall char *msg; 1190baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall asprintf(&msg, "%s %s %lld %lld %lld %lld", intIface.c_str(), extIface.c_str(), 1191db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall rxBytes, rxPackets, txBytes, txPackets); 1192db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return msg; 1193db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall} 1194db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1195baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrallint BandwidthController::getTetherStats(SocketClient *cli, TetherStats &stats, std::string &extraProcessingInfo) { 1196db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall int res; 1197db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall std::string fullCmd; 1198db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall FILE *iptOutput; 1199db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall const char *cmd; 1200db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1201db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* 1202db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Why not use some kind of lib to talk to iptables? 1203db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * Because the only libs are libiptc and libip6tc in iptables, and they are 1204db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * not easy to use. They require the known iptables match modules to be 1205db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * preloaded/linked, and require apparently a lot of wrapper code to get 1206db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall * the wanted info. 1207db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall */ 1208db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall fullCmd = IPTABLES_PATH; 1209baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall fullCmd += " -nvx -L "; 1210baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall fullCmd += NatController::LOCAL_TETHER_COUNTERS_CHAIN; 1211db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall iptOutput = popen(fullCmd.c_str(), "r"); 1212db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall if (!iptOutput) { 12135ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno)); 1214a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall extraProcessingInfo += "Failed to run iptables."; 1215db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return -1; 1216db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall } 1217baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall res = parseForwardChainStats(cli, stats, iptOutput, extraProcessingInfo); 1218db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall pclose(iptOutput); 1219db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall 1220db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall /* Currently NatController doesn't do ipv6 tethering, so we are done. */ 1221db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall return res; 1222db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall} 12230e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall 12240e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrallvoid BandwidthController::flushExistingCostlyTables(bool doClean) { 12250e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall int res; 12260e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall std::string fullCmd; 12270e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall FILE *iptOutput; 12280e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall const char *cmd; 12290e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall 12300e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall /* Only lookup ip4 table names as ip6 will have the same tables ... */ 12310e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall fullCmd = IPTABLES_PATH; 12320e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall fullCmd += " -S"; 12330e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall iptOutput = popen(fullCmd.c_str(), "r"); 12340e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall if (!iptOutput) { 12350e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall ALOGE("Failed to run %s err=%s", fullCmd.c_str(), strerror(errno)); 12360e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall return; 12370e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall } 12380e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall /* ... then flush/clean both ip4 and ip6 iptables. */ 12390e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall parseAndFlushCostlyTables(iptOutput, doClean); 12400e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall pclose(iptOutput); 12410e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall} 12420e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall 12430e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrallvoid BandwidthController::parseAndFlushCostlyTables(FILE *fp, bool doRemove) { 12440e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall int res; 12450e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall char lineBuffer[MAX_IPT_OUTPUT_LINE_LEN]; 12460e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall char costlyIfaceName[MAX_IPT_OUTPUT_LINE_LEN]; 12470e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall char cmd[MAX_CMD_LEN]; 12480e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall char *buffPtr; 12490e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall 12500e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall while (NULL != (buffPtr = fgets(lineBuffer, MAX_IPT_OUTPUT_LINE_LEN, fp))) { 12510e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall costlyIfaceName[0] = '\0'; /* So that debugging output always works */ 12520e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall res = sscanf(buffPtr, "-N bw_costly_%s", costlyIfaceName); 12530e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall ALOGV("parse res=%d costly=<%s> orig line=<%s>", res, 12540e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall costlyIfaceName, buffPtr); 12550e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall if (res != 1) { 12560e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall continue; 12570e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall } 12580e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall /* Exclusions: "shared" is not an ifacename */ 12590e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall if (!strcmp(costlyIfaceName, "shared")) { 12600e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall continue; 12610e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall } 12620e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall 12630e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall snprintf(cmd, sizeof(cmd), "-F bw_costly_%s", costlyIfaceName); 12640e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide); 12650e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall if (doRemove) { 12660e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall snprintf(cmd, sizeof(cmd), "-X bw_costly_%s", costlyIfaceName); 12670e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall runIpxtablesCmd(cmd, IptJumpNoAdd, IptFailHide); 12680e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall } 12690e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall } 12700e540ec038dfdbcf5cba3d5b9b2765e1dcec062bJP Abgrall} 1271