Home | History | Annotate | Download | only in netd
      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 <list>
     20 #include <string>
     21 #include <utility>  // for pair
     22 
     23 class BandwidthController {
     24 public:
     25     class TetherStats {
     26     public:
     27         TetherStats(void)
     28                 : rxBytes(-1), rxPackets(-1),
     29                     txBytes(-1), txPackets(-1) {};
     30         TetherStats(std::string ifnIn, std::string ifnOut,
     31                 int64_t rxB, int64_t rxP,
     32                 int64_t txB, int64_t txP)
     33                         : ifaceIn(ifnIn), ifaceOut(ifnOut),
     34                             rxBytes(rxB), rxPackets(rxP),
     35                     txBytes(txB), txPackets(txP) {};
     36         std::string ifaceIn;
     37         std::string ifaceOut;
     38         int64_t rxBytes, rxPackets;
     39         int64_t txBytes, txPackets;
     40         /*
     41          * Allocates a new string representing this:
     42          * ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
     43          * The caller is responsible for free()'ing the returned ptr.
     44          */
     45         char *getStatsLine(void);
     46     };
     47 
     48     BandwidthController();
     49 
     50     int setupIptablesHooks(void);
     51 
     52     int enableBandwidthControl(bool force);
     53     int disableBandwidthControl(void);
     54 
     55     int setInterfaceSharedQuota(const char *iface, int64_t bytes);
     56     int getInterfaceSharedQuota(int64_t *bytes);
     57     int removeInterfaceSharedQuota(const char *iface);
     58 
     59     int setInterfaceQuota(const char *iface, int64_t bytes);
     60     int getInterfaceQuota(const char *iface, int64_t *bytes);
     61     int removeInterfaceQuota(const char *iface);
     62 
     63     int addNaughtyApps(int numUids, char *appUids[]);
     64     int removeNaughtyApps(int numUids, char *appUids[]);
     65 
     66     int setGlobalAlert(int64_t bytes);
     67     int removeGlobalAlert(void);
     68     int setGlobalAlertInForwardChain(void);
     69     int removeGlobalAlertInForwardChain(void);
     70 
     71     int setSharedAlert(int64_t bytes);
     72     int removeSharedAlert(void);
     73 
     74     int setInterfaceAlert(const char *iface, int64_t bytes);
     75     int removeInterfaceAlert(const char *iface);
     76 
     77     /*
     78      * stats should have ifaceIn and ifaceOut initialized.
     79      * Byte counts should be left to the default (-1).
     80      */
     81     int getTetherStats(TetherStats &stats, std::string &extraProcessingInfo);
     82 
     83     static const char* LOCAL_INPUT;
     84     static const char* LOCAL_FORWARD;
     85     static const char* LOCAL_OUTPUT;
     86     static const char* LOCAL_RAW_PREROUTING;
     87     static const char* LOCAL_MANGLE_POSTROUTING;
     88 
     89 protected:
     90     class QuotaInfo {
     91     public:
     92       QuotaInfo(std::string ifn, int64_t q, int64_t a)
     93               : ifaceName(ifn), quota(q), alert(a) {};
     94         std::string ifaceName;
     95         int64_t quota;
     96         int64_t alert;
     97     };
     98 
     99     enum IptIpVer { IptIpV4, IptIpV6 };
    100     enum IptOp { IptOpInsert, IptOpReplace, IptOpDelete };
    101     enum IptRejectOp { IptRejectAdd, IptRejectNoAdd };
    102     enum NaughtyAppOp { NaughtyAppOpAdd, NaughtyAppOpRemove };
    103     enum QuotaType { QuotaUnique, QuotaShared };
    104     enum RunCmdErrHandling { RunCmdFailureBad, RunCmdFailureOk };
    105 #if LOG_NDEBUG
    106     enum IptFailureLog { IptFailShow, IptFailHide };
    107 #else
    108     enum IptFailureLog { IptFailShow, IptFailHide = IptFailShow };
    109 #endif
    110     int maninpulateNaughtyApps(int numUids, char *appStrUids[], NaughtyAppOp appOp);
    111 
    112     int prepCostlyIface(const char *ifn, QuotaType quotaType);
    113     int cleanupCostlyIface(const char *ifn, QuotaType quotaType);
    114 
    115     std::string makeIptablesNaughtyCmd(IptOp op, int uid);
    116     std::string makeIptablesQuotaCmd(IptOp op, const char *costName, int64_t quota);
    117 
    118     int runIptablesAlertCmd(IptOp op, const char *alertName, int64_t bytes);
    119     int runIptablesAlertFwdCmd(IptOp op, const char *alertName, int64_t bytes);
    120 
    121     /* Runs for both ipv4 and ipv6 iptables */
    122     int runCommands(int numCommands, const char *commands[], RunCmdErrHandling cmdErrHandling);
    123     /* Runs for both ipv4 and ipv6 iptables, appends -j REJECT --reject-with ...  */
    124     static int runIpxtablesCmd(const char *cmd, IptRejectOp rejectHandling,
    125                                IptFailureLog failureHandling = IptFailShow);
    126     static int runIptablesCmd(const char *cmd, IptRejectOp rejectHandling, IptIpVer iptIpVer,
    127                               IptFailureLog failureHandling = IptFailShow);
    128 
    129 
    130     // Provides strncpy() + check overflow.
    131     static int StrncpyAndCheck(char *buffer, const char *src, size_t buffSize);
    132 
    133     int updateQuota(const char *alertName, int64_t bytes);
    134 
    135     int setCostlyAlert(const char *costName, int64_t bytes, int64_t *alertBytes);
    136     int removeCostlyAlert(const char *costName, int64_t *alertBytes);
    137 
    138     /*
    139      * stats should have ifaceIn and ifaceOut initialized.
    140      * fp should be a file to the FORWARD rules of iptables.
    141      * extraProcessingInfo: contains raw parsed data, and error info.
    142      */
    143     static int parseForwardChainStats(TetherStats &stats, FILE *fp,
    144                                       std::string &extraProcessingInfo);
    145 
    146     /*------------------*/
    147 
    148     std::list<std::string> sharedQuotaIfaces;
    149     int64_t sharedQuotaBytes;
    150     int64_t sharedAlertBytes;
    151     int64_t globalAlertBytes;
    152     /*
    153      * This tracks the number of tethers setup.
    154      * The FORWARD chain is updated in the following cases:
    155      *  - The 1st time a globalAlert is setup and there are tethers setup.
    156      *  - Anytime a globalAlert is removed and there are tethers setup.
    157      *  - The 1st tether is setup and there is a globalAlert active.
    158      *  - The last tether is removed and there is a globalAlert active.
    159      */
    160     int globalAlertTetherCount;
    161 
    162     std::list<QuotaInfo> quotaIfaces;
    163     std::list<int /*appUid*/> naughtyAppUids;
    164 
    165 private:
    166     static const char *IPT_FLUSH_COMMANDS[];
    167     static const char *IPT_CLEANUP_COMMANDS[];
    168     static const char *IPT_SETUP_COMMANDS[];
    169     static const char *IPT_BASIC_ACCOUNTING_COMMANDS[];
    170 
    171     /* Alphabetical */
    172     static const int  ALERT_RULE_POS_IN_COSTLY_CHAIN;
    173     static const char ALERT_GLOBAL_NAME[];
    174     static const int  MAX_CMD_ARGS;
    175     static const int  MAX_CMD_LEN;
    176     static const int  MAX_IFACENAME_LEN;
    177     static const int  MAX_IPT_OUTPUT_LINE_LEN;
    178 
    179     /*
    180      * When false, it will directly use system() instead of logwrap()
    181      */
    182     static bool useLogwrapCall;
    183 };
    184 
    185 #endif
    186