BandwidthController.cpp revision 11b4e9b26fe7b878992162afb39f5a8acfd143ed
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 178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <errno.h> 184a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <fcntl.h> 198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall#include <stdlib.h> 204a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <string.h> 214a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 224a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/socket.h> 234a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/stat.h> 244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/types.h> 254a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <sys/wait.h> 264a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 274a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/netlink.h> 284a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/rtnetlink.h> 294a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <linux/pkt_sched.h> 304a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 314a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#define LOG_TAG "BandwidthController" 324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/log.h> 334a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <cutils/properties.h> 344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallextern "C" int logwrap(int argc, const char **argv, int background); 364a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 374a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include "BandwidthController.h" 384a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 39fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallconst int BandwidthController::MAX_CMD_LEN = 1024; 404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallconst int BandwidthController::MAX_IFACENAME_LEN = 64; 414a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallconst int BandwidthController::MAX_CMD_ARGS = 32; 424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallconst char BandwidthController::IPTABLES_PATH[] = "/system/bin/iptables"; 43fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallconst char BandwidthController::IP6TABLES_PATH[] = "/system/bin/ip6tables"; 448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallconst char BandwidthController::ALERT_IPT_TEMPLATE[] = "%s %s -m quota2 ! --quota %lld --name %s"; 458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallconst int BandwidthController::ALERT_RULE_POS_IN_COSTLY_CHAIN = 4; 4611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrallbool BandwidthController::useLogwrapCall = false; 474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 484a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall/** 494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Some comments about the rules: 504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * Ordering 514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - when an interface is marked as costly it should be INSERTED into the INPUT/OUTPUT chains. 524a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g. "-I INPUT -i rmnet0 --goto costly" 534a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - quota'd rules in the costly chain should be before penalty_box lookups. 544a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 554a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * global quota vs per interface quota 564a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - global quota for all costly interfaces uses a single costly chain: 574a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * . initial rules 58bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -N costly_shared 59bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I INPUT -i iface0 --goto costly_shared 60bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I OUTPUT -o iface0 --goto costly_shared 61bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I costly_shared -m quota \! --quota 500000 \ 62bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * --jump REJECT --reject-with icmp-net-prohibited 63bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A costly_shared --jump penalty_box 64bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A costly_shared -m owner --socket-exists 658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall * 664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * . adding a new iface to this, E.g.: 67bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I INPUT -i iface1 --goto costly_shared 68bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -I OUTPUT -o iface1 --goto costly_shared 694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - quota per interface. This is achieve by having "costly" chains per quota. 714a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g. adding a new costly interface iface0 with its own quota: 724a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -N costly_iface0 734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I INPUT -i iface0 --goto costly_iface0 744a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I OUTPUT -o iface0 --goto costly_iface0 75bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A costly_iface0 -m quota \! --quota 500000 \ 76bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * --jump REJECT --reject-with icmp-net-prohibited 77bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A costly_iface0 --jump penalty_box 784a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -A costly_iface0 -m owner --socket-exists 794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 804a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * penalty_box handling: 814a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - only one penalty_box for all interfaces 824a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g Adding an app: 83bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * iptables -A penalty_box -m owner --uid-owner app_3 \ 84bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall * --jump REJECT --reject-with icmp-net-prohibited 854a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 864a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallconst char *BandwidthController::cleanupCommands[] = { 870dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* Cleanup rules. */ 880dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-F", 890dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-t raw -F", 9039f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall /* TODO: If at some point we need more user chains than here, then we will need 9139f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall * a different cleanup approach. 9239f8f24246a5dac21be5cc5e32c0f395ee803766JP Abgrall */ 93bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-X", /* Should normally only be costly_shared, penalty_box, and costly_<iface> */ 940dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 954a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 964a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallconst char *BandwidthController::setupCommands[] = { 970dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* Created needed chains. */ 98bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-N costly_shared", 990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-N penalty_box", 1000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1010dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 1020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallconst char *BandwidthController::basicAccountingCommands[] = { 1030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-F INPUT", 1040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-A INPUT -i lo --jump ACCEPT", 1050dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-A INPUT -m owner --socket-exists", /* This is a tracking rule. */ 1060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 1070dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-F OUTPUT", 1080dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-A OUTPUT -o lo --jump ACCEPT", 1090dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall "-A OUTPUT -m owner --socket-exists", /* This is a tracking rule. */ 1100dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 111bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-F costly_shared", 112bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-A costly_shared --jump penalty_box", 113bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-A costly_shared -m owner --socket-exists", /* This is a tracking rule. */ 1140dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* TODO(jpa): Figure out why iptables doesn't correctly return from this 1150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * chain. For now, hack the chain exit with an ACCEPT. 1160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall */ 117bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall "-A costly_shared --jump ACCEPT", 1180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall}; 1194a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1204a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallBandwidthController::BandwidthController(void) { 1214a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char value[PROPERTY_VALUE_MAX]; 1224a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1234a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall property_get("persist.bandwidth.enable", value, "0"); 1244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (!strcmp(value, "1")) { 1254a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall enableBandwidthControl(); 1264a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 1274a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 12811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall property_get("persist.bandwidth.uselogwrap", value, "0"); 12911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall useLogwrapCall = !strcmp(value, "1"); 1304a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 1314a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 13226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling) { 1330dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 1348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 13526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall LOGD("runIpxtablesCmd(cmd=%s)", cmd); 13626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIptablesCmd(cmd, rejectHandling, IptIpV4); 13726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIptablesCmd(cmd, rejectHandling, IptIpV6); 1380dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 1390dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 1400dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 14126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::StrncpyAndCheck(char *buffer, const char *src, size_t buffSize) { 14226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 14326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall memset(buffer, '\0', buffSize); // strncpy() is not filling leftover with '\0' 14426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall strncpy(buffer, src, buffSize); 14526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return buffer[buffSize - 1]; 14626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall} 14726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 1488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesCmd(const char *cmd, IptRejectOp rejectHandling, 1498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall IptIpVer iptVer) { 15026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall char buffer[MAX_CMD_LEN]; 1514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall const char *argv[MAX_CMD_ARGS]; 15226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall int argc = 0; 1534a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char *next = buffer; 1544a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char *tmp; 15511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall int res; 1564a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string fullCmd = cmd; 15826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 15926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (rejectHandling == IptRejectAdd) { 1600dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall fullCmd += " --jump REJECT --reject-with"; 16126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (iptVer) { 16226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case IptIpV4: 1638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fullCmd += " icmp-net-prohibited"; 1648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 16526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case IptIpV6: 1668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fullCmd += " icmp6-adm-prohibited"; 1678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 1680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 1690dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 1700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 17111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall fullCmd.insert(0, " "); 17211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall fullCmd.insert(0, iptVer == IptIpV4 ? IPTABLES_PATH : IP6TABLES_PATH); 1734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 17411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (!useLogwrapCall) { 17511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall res = system(fullCmd.c_str()); 17611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } else { 17711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (StrncpyAndCheck(buffer, fullCmd.c_str(), sizeof(buffer))) { 17811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall LOGE("iptables command too long"); 1794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return -1; 1804a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 181fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 18211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall argc = 0; 18311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall while ((tmp = strsep(&next, " "))) { 18411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall argv[argc++] = tmp; 18511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (argc >= MAX_CMD_ARGS) { 18611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall LOGE("iptables argument overflow"); 18711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall return -1; 18811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 18911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 19011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall 19111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall argv[argc] = NULL; 19211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall res = logwrap(argc, argv, 0); 19311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 19411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall if (res) { 19511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall LOGE("runIptablesCmd(): failed %s res=%d", fullCmd.c_str(), res); 19611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall } 19711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall return res; 1984a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 1994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2004a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::enableBandwidthControl(void) { 201fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res; 202fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* Some of the initialCommands are allowed to fail */ 20326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall runCommands(sizeof(cleanupCommands) / sizeof(char*), cleanupCommands, RunCmdFailureOk); 20426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall runCommands(sizeof(setupCommands) / sizeof(char*), setupCommands, RunCmdFailureOk); 2058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = runCommands(sizeof(basicAccountingCommands) / sizeof(char*), basicAccountingCommands, 2068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall RunCmdFailureBad); 2078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 2088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedQuotaBytes = sharedAlertBytes = 0; 2098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedQuotaIfaces.clear(); 2108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall quotaIfaces.clear(); 2118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall naughtyAppUids.clear(); 2128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 213fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 2144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2154a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2164a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2174a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::disableBandwidthControl(void) { 218fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* The cleanupCommands are allowed to fail. */ 21926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall runCommands(sizeof(cleanupCommands) / sizeof(char*), cleanupCommands, RunCmdFailureOk); 220fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return 0; 2214a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2224a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runCommands(int numCommands, const char *commands[], 2248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall RunCmdErrHandling cmdErrHandling) { 225fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 226fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall LOGD("runCommands(): %d commands", numCommands); 227fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) { 22826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res = runIpxtablesCmd(commands[cmdNum], IptRejectNoAdd); 22926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (res && cmdErrHandling != RunCmdFailureBad) 230fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 231fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 23226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return cmdErrHandling == RunCmdFailureBad ? res : 0; 233fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 234fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 2350dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallstd::string BandwidthController::makeIptablesNaughtyCmd(IptOp op, int uid) { 236fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string res; 2378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *buff; 2388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 239fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 240fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall switch (op) { 2418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 2428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 2438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 2448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 2458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 2468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 2478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 2488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 2498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 2508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 251fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 2528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&buff, "%s penalty_box -m owner --uid-owner %d", opFlag, uid); 2538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = buff; 2548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(buff); 255fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 256fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 257fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 258fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::addNaughtyApps(int numUids, char *appUids[]) { 25926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpAdd); 260fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 261fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 262fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeNaughtyApps(int numUids, char *appUids[]) { 26326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return maninpulateNaughtyApps(numUids, appUids, NaughtyAppOpRemove); 264fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 265fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 26626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::maninpulateNaughtyApps(int numUids, char *appStrUids[], NaughtyAppOp appOp) { 267fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall char cmd[MAX_CMD_LEN]; 268fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int uidNum; 26926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *failLogTemplate; 27026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall IptOp op; 271fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int appUids[numUids]; 27226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string naughtyCmd; 2738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 27426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (appOp) { 27526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case NaughtyAppOpAdd: 2768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall op = IptOpInsert; 2778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall failLogTemplate = "Failed to add app uid %d to penalty box."; 2788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 27926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case NaughtyAppOpRemove: 2808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall op = IptOpDelete; 2818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall failLogTemplate = "Failed to delete app uid %d from penalty box."; 2828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 28326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 28426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 285fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (uidNum = 0; uidNum < numUids; uidNum++) { 286fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall appUids[uidNum] = atol(appStrUids[uidNum]); 287fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (appUids[uidNum] == 0) { 28826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall LOGE(failLogTemplate, appUids[uidNum]); 289fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_parse; 290fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 291fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 292fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 293fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (uidNum = 0; uidNum < numUids; uidNum++) { 29426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall naughtyCmd = makeIptablesNaughtyCmd(op, appUids[uidNum]); 29526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd)) { 29626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall LOGE(failLogTemplate, appUids[uidNum]); 297fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_with_uidNum; 298fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 299fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 300fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return 0; 301fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 30226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_with_uidNum: 303fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* Try to remove the uid that failed in any case*/ 30426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall naughtyCmd = makeIptablesNaughtyCmd(IptOpDelete, appUids[uidNum]); 30526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall runIpxtablesCmd(naughtyCmd.c_str(), IptRejectAdd); 30626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallfail_parse: 30726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 3084a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 3094a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 31026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallstd::string BandwidthController::makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota) { 311fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string res; 3128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *buff; 3138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 3140dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 3158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGD("makeIptablesQuotaCmd(%d, %lld)", op, quota); 3160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 317fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall switch (op) { 3188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 3198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 3208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 3218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 3228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 3238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 3248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 3258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 3268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 3278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 328fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 3298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 330bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall // The requried IP version specific --jump REJECT ... will be added later. 3318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&buff, "%s costly_%s -m quota2 ! --quota %lld --name %s", opFlag, costName, quota, 3328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall costName); 3338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = buff; 3348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(buff); 3350dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 3360dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 3370dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 33826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::prepCostlyIface(const char *ifn, QuotaType quotaType) { 3390dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char cmd[MAX_CMD_LEN]; 3400dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 3418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int ruleInsertPos = 1; 3420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string costString; 3430dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall const char *costCString; 3440dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 3450dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* The "-N costly" is created upfront, no need to handle it here. */ 34626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (quotaType) { 34726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaUnique: 348bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costString = "costly_"; 3490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costString += ifn; 3500dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costCString = costString.c_str(); 3510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-N %s", costCString); 35226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 3530dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-A %s -j penalty_box", costCString); 35426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 3550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-A %s -m owner --socket-exists", costCString); 35626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 3570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* TODO(jpa): Figure out why iptables doesn't correctly return from this 3580dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * chain. For now, hack the chain exit with an ACCEPT. 3590dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall */ 3600dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-A %s --jump ACCEPT", costCString); 36126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 36226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 36326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaShared: 364bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costCString = "costly_shared"; 36526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 3660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 3670dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 3688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (globalAlertBytes) { 3698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* The alert rule comes 1st */ 3708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ruleInsertPos = 2; 3718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 3728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall snprintf(cmd, sizeof(cmd), "-I INPUT %d -i %s --goto %s", ruleInsertPos, ifn, costCString); 37326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 3748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall snprintf(cmd, sizeof(cmd), "-I OUTPUT %d -o %s --goto %s", ruleInsertPos, ifn, costCString); 37526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 3760dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 3770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 3780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 37926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrallint BandwidthController::cleanupCostlyIface(const char *ifn, QuotaType quotaType) { 3800dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char cmd[MAX_CMD_LEN]; 3810dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 3820dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::string costString; 3830dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall const char *costCString; 3840dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 38526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall switch (quotaType) { 38626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaUnique: 387bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costString = "costly_"; 3880dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costString += ifn; 3890dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall costCString = costString.c_str(); 39026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 39126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall case QuotaShared: 392bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall costCString = "costly_shared"; 39326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall break; 3940dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 3950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 3960dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-D INPUT -i %s --goto %s", ifn, costCString); 39726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 3980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-D OUTPUT -o %s --goto %s", ifn, costCString); 39926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 4000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 401bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall /* The "-N costly_shared" is created upfront, no need to handle it here. */ 40226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (quotaType == QuotaUnique) { 4030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall snprintf(cmd, sizeof(cmd), "-F %s", costCString); 40426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 405a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall snprintf(cmd, sizeof(cmd), "-X %s", costCString); 406a9f802c23f4c2c53fa1065b75f712ce46f384c3aJP Abgrall res |= runIpxtablesCmd(cmd, IptRejectNoAdd); 407fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 408fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 409fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 4104a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4110dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceSharedQuota(const char *iface, int64_t maxBytes) { 4124a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char cmd[MAX_CMD_LEN]; 4134a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char ifn[MAX_IFACENAME_LEN]; 414fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 41526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string quotaCmd; 4168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::string ifaceName; 4178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ; 418bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall const char *costName = "shared"; 41926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<std::string>::iterator it; 4204a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!maxBytes) { 4228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* Don't talk about -1, deprecate it. */ 4238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Invalid bytes value. 1..max_int64."); 4248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 4258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 42626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 42726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall LOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 42826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 42926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 43026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 4314a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (maxBytes == -1) { 433fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return removeInterfaceSharedQuota(ifn); 4344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 4354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4364a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* Insert ingress quota. */ 4370dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) { 4380dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (*it == ifaceName) 439fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 4404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 441fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 4420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == sharedQuotaIfaces.end()) { 44326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= prepCostlyIface(ifn, QuotaShared); 4440dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (sharedQuotaIfaces.empty()) { 4450dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes); 44626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd); 4474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (res) { 4488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Failed set quota rule"); 449fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail; 4504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 451fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = maxBytes; 452fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 4530dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall sharedQuotaIfaces.push_front(ifaceName); 454fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 455fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 456fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 457fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (maxBytes != sharedQuotaBytes) { 4588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= updateQuota(costName, maxBytes); 459fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (res) { 4608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Failed update quota for %s", costName); 461fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail; 462fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 463fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = maxBytes; 4644a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 4654a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return 0; 466fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 467fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall fail: 4684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* 4694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse 4704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * rules in the kernel to see which ones need cleaning up. 471fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * For now callers needs to choose if they want to "ndc bandwidth enable" 472fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * which resets everything. 4734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 474fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall removeInterfaceSharedQuota(ifn); 4754a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return -1; 4764a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 4774a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall/* It will also cleanup any shared alerts */ 479fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeInterfaceSharedQuota(const char *iface) { 4804a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char ifn[MAX_IFACENAME_LEN]; 481fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 48226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 4830dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall std::list<std::string>::iterator it; 484bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall const char *costName = "shared"; 4854a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 4868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 48726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall LOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 48826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 48926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 4908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall ifaceName = ifn; 49126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 4920dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = sharedQuotaIfaces.begin(); it != sharedQuotaIfaces.end(); it++) { 4930dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (*it == ifaceName) 494fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 4954a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 4960dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == sharedQuotaIfaces.end()) { 4978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("No such iface %s to delete", ifn); 498fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return -1; 4994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 500fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 50126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= cleanupCostlyIface(ifn, QuotaShared); 5020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall sharedQuotaIfaces.erase(it); 503fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 5040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (sharedQuotaIfaces.empty()) { 505fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string quotaCmd; 506bfa7466b328101a8b04807f26e85c84526c9a774JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, sharedQuotaBytes); 50726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd); 5088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedQuotaBytes = 0; 5098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (sharedAlertBytes) { 5108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall removeSharedAlert(); 5118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall sharedAlertBytes = 0; 5128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 513fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 5144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return res; 5154a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 5160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5170dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::setInterfaceQuota(const char *iface, int64_t maxBytes) { 5180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char ifn[MAX_IFACENAME_LEN]; 5190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 52026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 52126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *costName; 52226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<QuotaInfo>::iterator it; 52326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string quotaCmd; 5240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!maxBytes) { 5268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall /* Don't talk about -1, deprecate it. */ 5278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Invalid bytes value. 1..max_int64."); 5288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 5298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 5300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (maxBytes == -1) { 53126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return removeInterfaceQuota(iface); 5320dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5330dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 53526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall LOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 53626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 53726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 53826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 53926e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall costName = iface; 54026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall 5410dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* Insert ingress quota. */ 5420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 5438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == ifaceName) 5440dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall break; 5450dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5460dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5470dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == quotaIfaces.end()) { 54826e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= prepCostlyIface(ifn, QuotaUnique); 5490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes); 55026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= runIpxtablesCmd(quotaCmd.c_str(), IptRejectAdd); 5510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (res) { 5528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Failed set quota rule"); 5530dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall goto fail; 5540dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall quotaIfaces.push_front(QuotaInfo(ifaceName, maxBytes, 0)); 5570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5580dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } else { 5598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= updateQuota(costName, maxBytes); 5600dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (res) { 5618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Failed update quota for %s", iface); 5620dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall goto fail; 5630dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall it->quota = maxBytes; 5650dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 5660dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return 0; 5670dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall fail: 5690dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* 5700dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse 5710dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * rules in the kernel to see which ones need cleaning up. 5720dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * For now callers needs to choose if they want to "ndc bandwidth enable" 5730dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall * which resets everything. 5740dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall */ 5750dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall removeInterfaceSharedQuota(ifn); 5760dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return -1; 5770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 5780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 5798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceSharedQuota(int64_t *bytes) { 5808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return getInterfaceQuota("shared", bytes); 5818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 5828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 5838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::getInterfaceQuota(const char *costName, int64_t *bytes) { 5848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall FILE *fp; 5858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *fname; 5868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int scanRes; 5878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 5888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&fname, "/proc/net/xt_quota/%s", costName); 5898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fp = fopen(fname, "r"); 5908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(fname); 5918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!fp) { 5928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Reading quota %s failed (%s)", costName, strerror(errno)); 5938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 5948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 5958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall scanRes = fscanf(fp, "%lld", bytes); 5968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGD("Read quota res=%d bytes=%lld", scanRes, *bytes); 5978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fclose(fp); 5988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return scanRes == 1 ? 0 : -1; 5998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 6008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6010dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrallint BandwidthController::removeInterfaceQuota(const char *iface) { 6020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall char ifn[MAX_IFACENAME_LEN]; 6040dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall int res = 0; 60526e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::string ifaceName; 60626e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall const char *costName; 60726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall std::list<QuotaInfo>::iterator it; 6080dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (StrncpyAndCheck(ifn, iface, sizeof(ifn))) { 61026e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall LOGE("Interface name longer than %d", MAX_IFACENAME_LEN); 61126e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall return -1; 61226e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall } 61326e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall ifaceName = ifn; 61426e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall costName = iface; 6150dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 6178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == ifaceName) 6180dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall break; 6190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6200dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6210dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall if (it == quotaIfaces.end()) { 6228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("No such iface %s to delete", ifn); 6230dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return -1; 6240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall } 6250dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6260dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall /* This also removes the quota command of CostlyIface chain. */ 62726e0d49fa743d7881104196a9eda733bd2aac92fJP Abgrall res |= cleanupCostlyIface(ifn, QuotaUnique); 6280dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall quotaIfaces.erase(it); 6300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall 6310dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall return res; 6320dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall} 6338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::updateQuota(const char *quotaName, int64_t bytes) { 6358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall FILE *fp; 6368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *fname; 6378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&fname, "/proc/net/xt_quota/%s", quotaName); 6398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fp = fopen(fname, "w"); 6408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(fname); 6418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!fp) { 6428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Updating quota %s failed (%s)", quotaName, strerror(errno)); 6438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 6448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 6458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fprintf(fp, "%lld\n", bytes); 6468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall fclose(fp); 6478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return 0; 6488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 6498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::runIptablesAlertCmd(IptOp op, const char *alertName, int64_t bytes) { 6518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 6528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *opFlag; 6538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 6548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall switch (op) { 6568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpInsert: 6578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-I"; 6588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 6598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpReplace: 6608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-R"; 6618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 6628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall default: 6638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall case IptOpDelete: 6648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall opFlag = "-D"; 6658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 6668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 6678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "INPUT", bytes, alertName, alertName); 6698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 6708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 6718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, opFlag, "OUTPUT", bytes, alertName, alertName); 6728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 6738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 6748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 6758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 6768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setGlobalAlert(int64_t bytes) { 6788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 6798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *alertName = "globalAlert"; 6808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 6818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 6838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Invalid bytes value. 1..max_int64."); 6848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 6858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 6868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (globalAlertBytes) { 6878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = updateQuota(alertName, bytes); 6888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } else { 6898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = runIptablesAlertCmd(IptOpInsert, alertName, bytes); 6908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 6918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall globalAlertBytes = bytes; 6928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 6938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 6948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeGlobalAlert(void) { 6968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 6978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 6988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall const char *alertName = "globalAlert"; 6998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 7008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!globalAlertBytes) { 7028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("No prior alert set"); 7038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = runIptablesAlertCmd(IptOpDelete, alertName, globalAlertBytes); 7068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall globalAlertBytes = 0; 7078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 7088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setSharedAlert(int64_t bytes) { 7118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!sharedQuotaBytes) { 7128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Need to have a prior shared quota set to set an alert"); 7138a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7148a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 7168a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Invalid bytes value. 1..max_int64."); 7178a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return setCostlyAlert("shared", bytes, &sharedAlertBytes); 7208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeSharedAlert(void) { 7238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return removeCostlyAlert("shared", &sharedAlertBytes); 7248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setInterfaceAlert(const char *iface, int64_t bytes) { 7278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::list<QuotaInfo>::iterator it; 7288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 7308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Invalid bytes value. 1..max_int64."); 7318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7338a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 7348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == iface) 7358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 7368a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it == quotaIfaces.end()) { 7398a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Need to have a prior interface quota set to set an alert"); 7408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7428a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7438a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return setCostlyAlert(iface, bytes, &it->alert); 7448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeInterfaceAlert(const char *iface) { 7478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall std::list<QuotaInfo>::iterator it; 7488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7498a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall for (it = quotaIfaces.begin(); it != quotaIfaces.end(); it++) { 7508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it->ifaceName == iface) 7518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall break; 7528a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7548a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (it == quotaIfaces.end()) { 7558a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("No prior alert set for interface %s", iface); 7568a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7578a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7598a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return removeCostlyAlert(iface, &it->alert); 7608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7628a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes) { 7638a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 7648a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *chainNameAndPos; 7658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 7668a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertName; 7678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7688a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!bytes) { 7698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("Invalid bytes value. 1..max_int64."); 7708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7728a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertName, "%sAlert", costName); 7738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (*alertBytes) { 7748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res = updateQuota(alertName, *alertBytes); 7758a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } else { 7768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&chainNameAndPos, "costly_%s %d", costName, ALERT_RULE_POS_IN_COSTLY_CHAIN); 7778a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-I", chainNameAndPos, bytes, alertName, 7788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall alertName); 7798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 7808a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 7818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(chainNameAndPos); 7828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *alertBytes = bytes; 7848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertName); 7858a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 7868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 7878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7888a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrallint BandwidthController::removeCostlyAlert(const char *costName, int64_t *alertBytes) { 7898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertQuotaCmd; 7908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *chainName; 7918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall char *alertName; 7928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall int res = 0; 7938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 7948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertName, "%sAlert", costName); 7958a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall if (!*alertBytes) { 7968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall LOGE("No prior alert set for %s alert", costName); 7978a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return -1; 7988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall } 7998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&chainName, "costly_%s", costName); 8018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall asprintf(&alertQuotaCmd, ALERT_IPT_TEMPLATE, "-D", chainName, *alertBytes, alertName, alertName); 8028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall res |= runIpxtablesCmd(alertQuotaCmd, IptRejectNoAdd); 8038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertQuotaCmd); 8048a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(chainName); 8058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall 8068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall *alertBytes = 0; 8078a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall free(alertName); 8088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall return res; 8098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall} 810