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