Home | History | Annotate | Download | only in netd
      1 /*
      2  * Copyright (C) 2012 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 
     17 // #define LOG_NDEBUG 0
     18 
     19 /*
     20  * MODUS OPERANDI
     21  * --------------
     22  *
     23  * IPTABLES command sequence:
     24  *
     25  * iptables -F
     26  *
     27  * iptables -t nat -F idletimer_PREROUTING
     28  * iptables -t nat -F idletimer_POSTROUTING
     29  *
     30  *
     31  * iptables -t nat -N idletimer_PREROUTING
     32  * iptables -t nat -N idletimer_POSTROUTING
     33  *
     34  * iptables -t nat -D PREROUTING -j idletimer_PREROUTING
     35  * iptables -t nat -D POSTROUTING -j idletimer_POSTROUTING
     36  *
     37  *
     38  * iptables -t nat -I PREROUTING -j idletimer_PREROUTING
     39  * iptables -t nat -I POSTROUTING -j idletimer_POSTROUTING
     40  *
     41  * # For notifications to work the lable name must match the name of a valid interface.
     42  * # If the label name does match an interface, the rules will be a no-op.
     43  *
     44  * iptables -t nat -A idletimer_PREROUTING -i rmnet0 -j IDLETIMER  --timeout 5 --label test-chain --send_nl_msg 1
     45  * iptables -t nat -A idletimer_POSTROUTING -o rmnet0 -j IDLETIMER  --timeout 5 --label test-chain --send_nl_msg 1
     46  *
     47  * iptables -nxvL -t nat
     48  *
     49  * =================
     50  *
     51  * ndc command sequence
     52  * ------------------
     53  * ndc idletimer enable
     54  * ndc idletimer add <iface> <timeout>
     55  * ndc idletimer remove <iface> <timeout>
     56  *
     57  * Monitor effect on the iptables chains after each step using:
     58  *     iptables -nxvL -t nat
     59  *
     60  * Remember that the timeout value has to be same at the time of the
     61  * removal.
     62  *
     63  * Note that currently if the name of the iface is incorrect, iptables
     64  * will setup rules without checking if it is the name of a valid
     65  * interface (although no notifications will ever be received).  It is
     66  * the responsibility of code in Java land to ensure that the interface name
     67  * is correct. The benefit of this, is that idletimers can be setup on
     68  * interfaces than come and go.
     69  *
     70  * A remove should be called for each add command issued during cleanup, as duplicate
     71  * entries of the rule may exist and will all have to removed.
     72  *
     73  */
     74 
     75 #include <stdlib.h>
     76 #include <errno.h>
     77 #include <sys/socket.h>
     78 #include <sys/stat.h>
     79 #include <fcntl.h>
     80 #include <netinet/in.h>
     81 #include <arpa/inet.h>
     82 #include <string.h>
     83 #include <cutils/properties.h>
     84 
     85 #define LOG_TAG "IdletimerController"
     86 #include <cutils/log.h>
     87 
     88 #include "IdletimerController.h"
     89 #include "NetdConstants.h"
     90 
     91 extern "C" int system_nosh(const char *command);
     92 
     93 IdletimerController::IdletimerController() {
     94 }
     95 
     96 IdletimerController::~IdletimerController() {
     97 }
     98 /* return 0 or non-zero */
     99 int IdletimerController::runIpxtablesCmd(const char *cmd) {
    100     char *buffer;
    101     size_t len = strnlen(cmd, 255);
    102     int res;
    103 
    104     if (len == 255) {
    105         ALOGE("command too long");
    106         return -1;
    107     }
    108 
    109     asprintf(&buffer, "%s %s", IPTABLES_PATH, cmd);
    110     res = system_nosh(buffer);
    111     ALOGV("%s #%d", buffer, res);
    112     free(buffer);
    113 
    114     return res;
    115 }
    116 
    117 bool IdletimerController::setupIptablesHooks() {
    118     runIpxtablesCmd("-t nat -D PREROUTING -j idletimer_nat_PREROUTING");
    119     runIpxtablesCmd("-t nat -F idletimer_nat_PREROUTING");
    120     runIpxtablesCmd("-t nat -N idletimer_nat_PREROUTING");
    121 
    122     runIpxtablesCmd("-t nat -D POSTROUTING -j idletimer_nat_POSTROUTING");
    123     runIpxtablesCmd("-t nat -F idletimer_nat_POSTROUTING");
    124     runIpxtablesCmd("-t nat -N idletimer_nat_POSTROUTING");
    125 
    126     if (runIpxtablesCmd("-t nat -I PREROUTING -j idletimer_nat_PREROUTING")
    127         || runIpxtablesCmd("-t nat -I POSTROUTING -j idletimer_nat_POSTROUTING")) {
    128         return false;
    129     }
    130     return true;
    131 }
    132 
    133 int IdletimerController::setDefaults() {
    134   if (runIpxtablesCmd("-t nat -F idletimer_nat_PREROUTING")
    135       || runIpxtablesCmd("-t nat -F idletimer_nat_POSTROUTING") )
    136       return -1;
    137   return 0;
    138 }
    139 
    140 int IdletimerController::enableIdletimerControl() {
    141     int res = setDefaults();
    142     return res;
    143 }
    144 
    145 int IdletimerController::disableIdletimerControl() {
    146     int res = setDefaults();
    147     return res;
    148 }
    149 
    150 int IdletimerController::modifyInterfaceIdletimer(IptOp op, const char *iface,
    151                                                   uint32_t timeout) {
    152   int res;
    153   char *buffer;
    154   asprintf(&buffer, "-t nat -%c idletimer_nat_PREROUTING -i %s -j IDLETIMER"
    155            " --timeout %u --label %s --send_nl_msg 1",
    156            (op == IptOpAdd) ? 'A' : 'D', iface, timeout, iface);
    157   res = runIpxtablesCmd(buffer);
    158   free(buffer);
    159 
    160   asprintf(&buffer, "-t nat -%c idletimer_nat_POSTROUTING -o %s -j IDLETIMER"
    161            " --timeout %u --label %s --send_nl_msg 1",
    162            (op == IptOpAdd) ? 'A' : 'D', iface, timeout, iface);
    163   res |= runIpxtablesCmd(buffer);
    164   free(buffer);
    165 
    166   return res;
    167 }
    168 
    169 int IdletimerController::addInterfaceIdletimer(const char *iface, uint32_t timeout) {
    170   return modifyInterfaceIdletimer(IptOpAdd, iface, timeout);
    171 }
    172 
    173 int IdletimerController::removeInterfaceIdletimer(const char *iface, uint32_t timeout) {
    174   return modifyInterfaceIdletimer(IptOpDelete, iface, timeout);
    175 }
    176