Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #ifndef _BANDWIDTH_CONTROLLER_H
     17 #define _BANDWIDTH_CONTROLLER_H
     18 
     19 #include <map>
     20 #include <set>
     21 #include <string>
     22 #include <utility>
     23 #include <vector>
     24 
     25 #include <sysutils/SocketClient.h>
     26 #include <utils/RWLock.h>
     27 
     28 #include "NetdConstants.h"
     29 
     30 class BandwidthController {
     31 public:
     32     android::RWLock lock;
     33 
     34     class TetherStats {
     35     public:
     36         TetherStats() = default;
     37         TetherStats(std::string intIfn, std::string extIfn,
     38                 int64_t rxB, int64_t rxP,
     39                 int64_t txB, int64_t txP)
     40                         : intIface(intIfn), extIface(extIfn),
     41                             rxBytes(rxB), rxPackets(rxP),
     42                             txBytes(txB), txPackets(txP) {};
     43         /* Internal interface. Same as NatController's notion. */
     44         std::string intIface;
     45         /* External interface. Same as NatController's notion. */
     46         std::string extIface;
     47         int64_t rxBytes = -1;
     48         int64_t rxPackets = -1;
     49         int64_t txBytes = -1;
     50         int64_t txPackets = -1;
     51         /*
     52          * Allocates a new string representing this:
     53          * intIface extIface rx_bytes rx_packets tx_bytes tx_packets
     54          * The caller is responsible for free()'ing the returned ptr.
     55          */
     56         std::string getStatsLine() const;
     57 
     58         bool addStatsIfMatch(const TetherStats& other) {
     59             if (intIface == other.intIface && extIface == other.extIface) {
     60                 rxBytes   += other.rxBytes;
     61                 rxPackets += other.rxPackets;
     62                 txBytes   += other.txBytes;
     63                 txPackets += other.txPackets;
     64                 return true;
     65             }
     66             return false;
     67         }
     68     };
     69 
     70     BandwidthController();
     71 
     72     int setupIptablesHooks();
     73 
     74     int enableBandwidthControl(bool force);
     75     int disableBandwidthControl();
     76     int enableDataSaver(bool enable);
     77 
     78     int setInterfaceSharedQuota(const std::string& iface, int64_t bytes);
     79     int getInterfaceSharedQuota(int64_t *bytes);
     80     int removeInterfaceSharedQuota(const std::string& iface);
     81 
     82     int setInterfaceQuota(const std::string& iface, int64_t bytes);
     83     int getInterfaceQuota(const std::string& iface, int64_t* bytes);
     84     int removeInterfaceQuota(const std::string& iface);
     85 
     86     int addNaughtyApps(int numUids, char *appUids[]);
     87     int removeNaughtyApps(int numUids, char *appUids[]);
     88     int addNiceApps(int numUids, char *appUids[]);
     89     int removeNiceApps(int numUids, char *appUids[]);
     90 
     91     int setGlobalAlert(int64_t bytes);
     92     int removeGlobalAlert();
     93     int setGlobalAlertInForwardChain();
     94     int removeGlobalAlertInForwardChain();
     95 
     96     int setSharedAlert(int64_t bytes);
     97     int removeSharedAlert();
     98 
     99     int setInterfaceAlert(const std::string& iface, int64_t bytes);
    100     int removeInterfaceAlert(const std::string& iface);
    101 
    102     /*
    103      * For single pair of ifaces, stats should have ifaceIn and ifaceOut initialized.
    104      * For all pairs, stats should have ifaceIn=ifaceOut="".
    105      * Sends out to the cli the single stat (TetheringStatsReluts) or a list of stats
    106      * (TetheringStatsListResult+CommandOkay).
    107      * Error is to be handled on the outside.
    108      * It results in an error if invoked and no tethering counter rules exist.
    109      */
    110     int getTetherStats(SocketClient *cli, TetherStats &stats, std::string &extraProcessingInfo);
    111 
    112     static const char LOCAL_INPUT[];
    113     static const char LOCAL_FORWARD[];
    114     static const char LOCAL_OUTPUT[];
    115     static const char LOCAL_RAW_PREROUTING[];
    116     static const char LOCAL_MANGLE_POSTROUTING[];
    117 
    118   private:
    119     struct QuotaInfo {
    120         int64_t quota;
    121         int64_t alert;
    122     };
    123 
    124     enum IptIpVer { IptIpV4, IptIpV6 };
    125     enum IptFullOp { IptFullOpInsert, IptFullOpDelete, IptFullOpAppend };
    126     enum IptJumpOp { IptJumpReject, IptJumpReturn, IptJumpNoAdd };
    127     enum IptOp { IptOpInsert, IptOpDelete };
    128     enum QuotaType { QuotaUnique, QuotaShared };
    129     enum RunCmdErrHandling { RunCmdFailureBad, RunCmdFailureOk };
    130 #if LOG_NDEBUG
    131     enum IptFailureLog { IptFailShow, IptFailHide };
    132 #else
    133     enum IptFailureLog { IptFailShow, IptFailHide = IptFailShow };
    134 #endif
    135 
    136     std::string makeDataSaverCommand(IptablesTarget target, bool enable);
    137 
    138     int manipulateSpecialApps(const std::vector<std::string>& appStrUids, const std::string& chain,
    139                               IptJumpOp jumpHandling, IptOp appOp);
    140 
    141     int runIptablesAlertCmd(IptOp op, const std::string& alertName, int64_t bytes);
    142     int runIptablesAlertFwdCmd(IptOp op, const std::string& alertName, int64_t bytes);
    143 
    144     int updateQuota(const std::string& alertName, int64_t bytes);
    145 
    146     int setCostlyAlert(const std::string& costName, int64_t bytes, int64_t* alertBytes);
    147     int removeCostlyAlert(const std::string& costName, int64_t* alertBytes);
    148 
    149     typedef std::vector<TetherStats> TetherStatsList;
    150 
    151     static void addStats(TetherStatsList& statsList, const TetherStats& stats);
    152 
    153     /*
    154      * stats should never have only intIface initialized. Other 3 combos are ok.
    155      * fp should be a file to the apropriate FORWARD chain of iptables rules.
    156      * extraProcessingInfo: contains raw parsed data, and error info.
    157      * This strongly requires that setup of the rules is in a specific order:
    158      *  in:intIface out:extIface
    159      *  in:extIface out:intIface
    160      * and the rules are grouped in pairs when more that one tethering was setup.
    161      */
    162     static int addForwardChainStats(const TetherStats& filter,
    163                                     TetherStatsList& statsList, const std::string& iptOutput,
    164                                     std::string &extraProcessingInfo);
    165 
    166     /*
    167      * Attempt to find the bw_costly_* tables that need flushing,
    168      * and flush them.
    169      * If doClean then remove the tables also.
    170      * Deals with both ip4 and ip6 tables.
    171      */
    172     void flushExistingCostlyTables(bool doClean);
    173     static void parseAndFlushCostlyTables(const std::string& ruleList, bool doRemove);
    174 
    175     /*
    176      * Attempt to flush our tables.
    177      * If doClean then remove them also.
    178      * Deals with both ip4 and ip6 tables.
    179      */
    180     void flushCleanTables(bool doClean);
    181 
    182     // For testing.
    183     friend class BandwidthControllerTest;
    184     static int (*execFunction)(int, char **, int *, bool, bool);
    185     static FILE *(*popenFunction)(const char *, const char *);
    186     static int (*iptablesRestoreFunction)(IptablesTarget, const std::string&, std::string *);
    187 
    188     static const char *opToString(IptOp op);
    189     static const char *jumpToString(IptJumpOp jumpHandling);
    190 
    191     int64_t mSharedQuotaBytes = 0;
    192     int64_t mSharedAlertBytes = 0;
    193     int64_t mGlobalAlertBytes = 0;
    194     /*
    195      * This tracks the number of tethers setup.
    196      * The FORWARD chain is updated in the following cases:
    197      *  - The 1st time a globalAlert is setup and there are tethers setup.
    198      *  - Anytime a globalAlert is removed and there are tethers setup.
    199      *  - The 1st tether is setup and there is a globalAlert active.
    200      *  - The last tether is removed and there is a globalAlert active.
    201      */
    202     int mGlobalAlertTetherCount = 0;
    203 
    204     std::map<std::string, QuotaInfo> mQuotaIfaces;
    205     std::set<std::string> mSharedQuotaIfaces;
    206 };
    207 
    208 #endif
    209