BandwidthController.cpp revision fa6f46d3370ae5475fc3bc8273bbe04ee7348d60
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 174a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <stdlib.h> 184a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <errno.h> 194a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include <fcntl.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"; 444a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 454a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall/** 464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Some comments about the rules: 474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * Ordering 484a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - when an interface is marked as costly it should be INSERTED into the INPUT/OUTPUT chains. 494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g. "-I INPUT -i rmnet0 --goto costly" 504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - quota'd rules in the costly chain should be before penalty_box lookups. 514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 524a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * global quota vs per interface quota 534a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - global quota for all costly interfaces uses a single costly chain: 544a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * . initial rules 554a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -N costly 564a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I INPUT -i iface0 --goto costly 574a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I OUTPUT -o iface0 --goto costly 584a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I costly -m quota \! --quota 500000 --jump REJECT --reject-with icmp-net-prohibited 594a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -A costly --jump penalty_box 604a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -A costly -m owner --socket-exists 614a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * . adding a new iface to this, E.g.: 624a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I INPUT -i iface1 --goto costly 634a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I OUTPUT -o iface1 --goto costly 644a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 654a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - quota per interface. This is achieve by having "costly" chains per quota. 664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g. adding a new costly interface iface0 with its own quota: 674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -N costly_iface0 684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I INPUT -i iface0 --goto costly_iface0 694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -I OUTPUT -o iface0 --goto costly_iface0 704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -A costly_iface0 -m quota \! --quota 500000 --jump REJECT --reject-with icmp-net-prohibited 714a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -A costly_iface0 --jump penalty_box 724a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -A costly_iface0 -m owner --socket-exists 734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * 744a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * * penalty_box handling: 754a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * - only one penalty_box for all interfaces 764a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * E.g Adding an app: 774a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * iptables -A penalty_box -m owner --uid-owner app_3 --jump REJECT --reject-with icmp-net-prohibited 784a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallconst char *BandwidthController::cleanupCommands[] = { 80fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall/* Cleanup rules. */ 81fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall"-F", "-t raw -F", "-X costly", "-X penalty_box", }; 824a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 834a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallconst char *BandwidthController::setupCommands[] = { 84fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall/* Created needed chains. */ 85fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall"-N costly", "-N penalty_box", }; 86fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 87fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallconst char *BandwidthController::basicAccountingCommands[] = { "-F INPUT", 88fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall "-A INPUT -i lo --jump ACCEPT", "-A INPUT -m owner --socket-exists", /* This is a tracking rule. */ 89fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 90fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall "-F OUTPUT", "-A OUTPUT -o lo --jump ACCEPT", "-A OUTPUT -m owner --socket-exists", /* This is a tracking rule. */ 914a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 92fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall "-F costly", "-A costly --jump penalty_box", "-A costly -m owner --socket-exists", /* This is a tracking rule. */ 93fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* TODO(jpa): Figure out why iptables doesn't correctly return from this 94fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * chain. For now, hack the chain exit with an ACCEPT. 95fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall */ 96fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall "-A costly --jump ACCEPT", }; 974a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 984a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallBandwidthController::BandwidthController(void) { 994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1004a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char value[PROPERTY_VALUE_MAX]; 1014a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1024a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall property_get("persist.bandwidth.enable", value, "0"); 1034a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (!strcmp(value, "1")) { 1044a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall enableBandwidthControl(); 1054a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 1064a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1074a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 1084a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 109fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::runIptablesCmd(const char *cmd, bool isIp6) { 1104a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char buffer[MAX_CMD_LEN]; 1114a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall const char *argv[MAX_CMD_ARGS]; 112fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int argc = 1; 1134a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char *next = buffer; 1144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char *tmp; 1154a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 116fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall argv[0] = isIp6 ? IP6TABLES_PATH : IPTABLES_PATH; 117fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall LOGD("About to run: %s %s", argv[0], cmd); 118fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 119fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall strncpy(buffer, cmd, sizeof(buffer) - 1); 1204a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1214a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall while ((tmp = strsep(&next, " "))) { 1224a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall argv[argc++] = tmp; 1234a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (argc == MAX_CMD_ARGS) { 1244a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall LOGE("iptables argument overflow"); 1254a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall errno = E2BIG; 1264a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return -1; 1274a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 1284a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 129fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 1304a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall argv[argc] = NULL; 1314a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* TODO(jpa): Once this stabilizes, remove logwrap() as it tends to wedge netd 1324a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * Then just talk directly to the kernel via rtnetlink. 1334a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 1344a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return logwrap(argc, argv, 0); 1354a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 1364a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1374a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::enableBandwidthControl(void) { 138fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res; 139fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* Some of the initialCommands are allowed to fail */ 140fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall runCommands(sizeof(cleanupCommands) / sizeof(char*), cleanupCommands, true, false); 141fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall runCommands(sizeof(cleanupCommands) / sizeof(char*), cleanupCommands, true, true); 142fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall runCommands(sizeof(setupCommands) / sizeof(char*), setupCommands, true, false); 143fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall runCommands(sizeof(setupCommands) / sizeof(char*), setupCommands, true, true); 144fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res = runCommands(sizeof(basicAccountingCommands) / sizeof(char*), basicAccountingCommands, 145fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall false, false); 146fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runCommands(sizeof(basicAccountingCommands) / sizeof(char*), basicAccountingCommands, 147fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall false, true); 148fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 1494a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 1514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 1524a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrallint BandwidthController::disableBandwidthControl(void) { 153fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* The cleanupCommands are allowed to fail. */ 154fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall runCommands(sizeof(cleanupCommands) / sizeof(char*), cleanupCommands, true); 155fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall runCommands(sizeof(cleanupCommands) / sizeof(char*), cleanupCommands, true, true); 156fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return 0; 1574a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 1584a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 159fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::runCommands(int numCommands, const char *commands[], bool allowFailure, 160fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall bool isIp6) { 161fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 162fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall LOGD("runCommands(): %d commands", numCommands); 163fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (int cmdNum = 0; cmdNum < numCommands; cmdNum++) { 164fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res = runIptablesCmd(commands[cmdNum], isIp6); 165fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (res && !allowFailure) 166fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 167fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 168fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return allowFailure ? res : 0; 169fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 170fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 171fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallstd::string BandwidthController::makeIptablesNaughtyCmd(IptOp op, int uid, bool isIp6) { 172fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string res; 173fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall char convBuff[21]; // log10(2^64) ~ 20 174fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 175fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall switch (op) { 176fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall case IptOpInsert: 177fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res = "-I"; 178fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 179fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall case IptOpReplace: 180fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res = "-R"; 181fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 182fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall default: 183fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall case IptOpDelete: 184fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res = "-D"; 185fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 186fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 187fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += " penalty_box"; 188fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sprintf(convBuff, "%d", uid); 189fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += " -m owner --uid-owner "; 190fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += convBuff; 191fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += " --jump REJECT --reject-with"; 192fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (isIp6) { 193fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += " icmp6-adm-prohibited"; 194fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } else { 195fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += " icmp-net-prohibited"; 196fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 197fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 198fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 199fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 200fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::addNaughtyApps(int numUids, char *appUids[]) { 201fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return maninpulateNaughtyApps(numUids, appUids, true); 202fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 203fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 204fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeNaughtyApps(int numUids, char *appUids[]) { 205fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return maninpulateNaughtyApps(numUids, appUids, false); 206fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 207fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 208fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::maninpulateNaughtyApps(int numUids, char *appStrUids[], bool doAdd) { 209fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall char cmd[MAX_CMD_LEN]; 210fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int uidNum; 211fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall const char *addFailedTemplate = "Failed to add app uid %d to penalty box."; 212fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall const char *deleteFailedTemplate = "Failed to delete app uid %d from penalty box."; 213fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall IptOp op = doAdd ? IptOpInsert : IptOpDelete; 214fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 215fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int appUids[numUids]; 216fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (uidNum = 0; uidNum < numUids; uidNum++) { 217fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall appUids[uidNum] = atol(appStrUids[uidNum]); 218fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (appUids[uidNum] == 0) { 219fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall LOGE((doAdd ? addFailedTemplate : deleteFailedTemplate), appUids[uidNum]); 220fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_parse; 221fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 222fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 223fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 224fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (uidNum = 0; uidNum < numUids; uidNum++) { 225fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string naughtyCmd = makeIptablesNaughtyCmd(op, appUids[uidNum], false); 226fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (runIptablesCmd(naughtyCmd.c_str())) { 227fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall LOGE((doAdd ? addFailedTemplate : deleteFailedTemplate), appUids[uidNum]); 228fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_with_uidNum; 2294a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 230fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall naughtyCmd = makeIptablesNaughtyCmd(op, appUids[uidNum], true); 231fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (runIptablesCmd(naughtyCmd.c_str(), true)) { 232fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall LOGE((doAdd ? addFailedTemplate : deleteFailedTemplate), appUids[uidNum]); 233fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail_with_uidNum; 234fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 235fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 236fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return 0; 237fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 238fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall fail_with_uidNum: 239fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* Try to remove the uid that failed in any case*/ 240fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall runIptablesCmd(makeIptablesNaughtyCmd(IptOpDelete, appUids[uidNum], false).c_str()); 241fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall runIptablesCmd(makeIptablesNaughtyCmd(IptOpDelete, appUids[uidNum], true).c_str(), true); 242fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall fail_parse: return -1; 2434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 2444a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 245fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallstd::string BandwidthController::makeIptablesQuotaCmd(IptOp op, char *costName, int64_t quota, bool isIp6) { 246fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string res; 247fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall char convBuff[21]; // log10(2^64) ~ 20 248fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall LOGD("makeIptablesQuotaCmd(%d, %llu, %d)", op, quota, isIp6); 249fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall switch (op) { 250fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall case IptOpInsert: 251fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res = "-I"; 252fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 253fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall case IptOpReplace: 254fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res = "-R"; 255fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 256fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall default: 257fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall case IptOpDelete: 258fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res = "-D"; 259fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 260fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 261fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += " costly"; 262fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (costName) { 263fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += costName; 264fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 265fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sprintf(convBuff, "%lld", quota); 266fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += " -m quota ! --quota "; 267fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += convBuff; 268fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall ; 269fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += " --jump REJECT --reject-with"; 270fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (isIp6) { 271fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += " icmp6-adm-prohibited"; 272fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } else { 273fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res += " icmp-net-prohibited"; 274fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 275fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return res; 276fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall} 2774a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 278fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::setInterfaceSharedQuota(int64_t maxBytes, const char *iface) { 2794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char cmd[MAX_CMD_LEN]; 2804a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char ifn[MAX_IFACENAME_LEN]; 281fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 2824a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2834a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall memset(ifn, 0, sizeof(ifn)); 284fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall strncpy(ifn, iface, sizeof(ifn) - 1); 2854a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 2864a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (maxBytes == -1) { 287fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return removeInterfaceSharedQuota(ifn); 2884a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 2894a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 290fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall char *costName = NULL; /* Shared quota */ 291fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 2924a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* Insert ingress quota. */ 2934a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall std::string ifaceName(ifn); 294fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::list<QuotaInfo>::iterator it; 295fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (it = ifaceRules.begin(); it != ifaceRules.end(); it++) { 296fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (it->first == ifaceName) 297fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 2984a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 299fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 300fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (it == ifaceRules.end()) { 301fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall snprintf(cmd, sizeof(cmd), "-I INPUT -i %s --goto costly", ifn); 302fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(cmd); 303fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(cmd, true); 304fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall snprintf(cmd, sizeof(cmd), "-I OUTPUT -o %s --goto costly", ifn); 305fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(cmd); 306fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(cmd, true); 307fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 308fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (ifaceRules.empty()) { 309fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string quotaCmd; 310fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes, false); 311fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(quotaCmd.c_str()); 312fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes, true); 313fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(quotaCmd.c_str(), true); 3144a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall if (res) { 315fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall LOGE("Failed set quota rule."); 316fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail; 3174a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 318fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = maxBytes; 319fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 320fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 321fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall ifaceRules.push_front(QuotaInfo(ifaceName, maxBytes)); 322fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 323fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 324fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 325fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (maxBytes != sharedQuotaBytes) { 326fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall /* Instead of replacing, which requires being aware of the rules in 327fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * the kernel, we just add a new one, then delete the older one. 328fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall */ 329fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string quotaCmd; 330fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 331fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes, false); 332fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(quotaCmd.c_str()); 333fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpInsert, costName, maxBytes, true); 334fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(quotaCmd.c_str(), true); 335fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 336fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, sharedQuotaBytes, false); 337fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(quotaCmd.c_str()); 338fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpDelete, costName, sharedQuotaBytes, true); 339fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(quotaCmd.c_str(), true); 340fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 341fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (res) { 342fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall LOGE("Failed replace quota rule."); 343fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall goto fail; 344fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 345fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = maxBytes; 3464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 3474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return 0; 348fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 349fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall fail: 3504a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall /* 3514a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * TODO(jpa): once we get rid of iptables in favor of rtnetlink, reparse 3524a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall * rules in the kernel to see which ones need cleaning up. 353fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * For now callers needs to choose if they want to "ndc bandwidth enable" 354fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall * which resets everything. 3554a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall */ 356fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall removeInterfaceSharedQuota(ifn); 3574a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return -1; 3584a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 3594a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 360fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint BandwidthController::removeInterfaceSharedQuota(const char *iface) { 3614a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char cmd[MAX_CMD_LEN]; 3624a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall char ifn[MAX_IFACENAME_LEN]; 363fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall int res = 0; 3644a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 3654a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall memset(ifn, 0, sizeof(ifn)); 366fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall strncpy(ifn, iface, sizeof(ifn) - 1); 3674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 3684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall std::string ifaceName(ifn); 369fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::list<QuotaInfo>::iterator it; 3704a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall 371fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall for (it = ifaceRules.begin(); it != ifaceRules.end(); it++) { 372fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (it->first == ifaceName) 373fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall break; 3744a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 375fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (it == ifaceRules.end()) { 376fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall LOGE("No such iface %s to delete.", ifn); 377fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall return -1; 3784a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall } 379fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 3804a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall snprintf(cmd, sizeof(cmd), "--delete INPUT -i %s --goto costly", ifn); 3814a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall res |= runIptablesCmd(cmd); 382fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(cmd, true); 383fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall snprintf(cmd, sizeof(cmd), "--delete OUTPUT -o %s --goto costly", ifn); 3844a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall res |= runIptablesCmd(cmd); 385fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(cmd, true); 386fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 387fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall ifaceRules.erase(it); 388fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall if (ifaceRules.empty()) { 389fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall std::string quotaCmd; 390fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpDelete, NULL, sharedQuotaBytes, false); 391fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(quotaCmd.c_str()); 392fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 393fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall quotaCmd = makeIptablesQuotaCmd(IptOpDelete, NULL, sharedQuotaBytes, true); 394fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall res |= runIptablesCmd(quotaCmd.c_str(), true); 395fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall sharedQuotaBytes = -1; 396fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall } 397fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall 3984a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall return res; 3994a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall} 400