IdletimerController.cpp revision 0031cead820149e2fe3ccb3cc2fe05758a3cb5c2
10031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall/*
20031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Copyright (C) 2012 The Android Open Source Project
30031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
40031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Licensed under the Apache License, Version 2.0 (the "License");
50031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * you may not use this file except in compliance with the License.
60031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * You may obtain a copy of the License at
70031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
80031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *      http://www.apache.org/licenses/LICENSE-2.0
90031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Unless required by applicable law or agreed to in writing, software
110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * distributed under the License is distributed on an "AS IS" BASIS,
120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * See the License for the specific language governing permissions and
140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * limitations under the License.
150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall */
160031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall// #define LOG_NDEBUG 0
180031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
190031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall/*
200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * MODUS OPERANDI
210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * --------------
220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
230031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * IPTABLES command sequence:
240031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
250031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -F
260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -t nat -F idletimer_PREROUTING
280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -t nat -F idletimer_POSTROUTING
290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -t nat -N idletimer_PREROUTING
320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -t nat -N idletimer_POSTROUTING
330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -t nat -D PREROUTING -j idletimer_PREROUTING
350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -t nat -D POSTROUTING -j idletimer_POSTROUTING
360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -t nat -I PREROUTING -j idletimer_PREROUTING
390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -t nat -I POSTROUTING -j idletimer_POSTROUTING
400031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * # For notifications to work the lable name must match the name of a valid interface.
420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * # If the label name does match an interface, the rules will be a no-op.
430031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -t nat -A idletimer_PREROUTING -i rmnet0 -j IDLETIMER  --timeout 5 --label test-chain --send_nl_msg 1
450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -t nat -A idletimer_POSTROUTING -o rmnet0 -j IDLETIMER  --timeout 5 --label test-chain --send_nl_msg 1
460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * iptables -nxvL -t nat
480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * =================
500031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
510031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * ndc command sequence
520031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * ------------------
530031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * ndc idletimer enable
540031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * ndc idletimer add <iface> <timeout>
550031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * ndc idletimer remove <iface> <timeout>
560031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
570031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Monitor effect on the iptables chains after each step using:
580031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *     iptables -nxvL -t nat
590031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
600031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Remember that the timeout value has to be same at the time of the
610031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * removal.
620031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
630031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Note that currently if the name of the iface is incorrect, iptables
640031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * will setup rules without checking if it is the name of a valid
650031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * interface (although no notifications will ever be received).  It is
660031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * the responsibility of code in Java land to ensure that the interface name
670031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * is correct. The benefit of this, is that idletimers can be setup on
680031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * interfaces than come and go.
690031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
700031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * A remove should be called for each add command issued during cleanup, as duplicate
710031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * entries of the rule may exist and will all have to removed.
720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
730031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall */
740031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
750031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <stdlib.h>
760031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <errno.h>
770031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <sys/socket.h>
780031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <sys/stat.h>
790031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <fcntl.h>
800031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <netinet/in.h>
810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <arpa/inet.h>
820031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <string.h>
830031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <cutils/properties.h>
840031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
850031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#define LOG_TAG "IdletimerController"
860031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <cutils/log.h>
870031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
880031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "IdletimerController.h"
890031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "NetdConstants.h"
900031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
910031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallextern "C" int system_nosh(const char *command);
920031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
930031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP AbgrallIdletimerController::IdletimerController() {
940031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
950031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
960031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP AbgrallIdletimerController::~IdletimerController() {
970031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
980031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall/* return 0 or non-zero */
990031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::runIpxtablesCmd(const char *cmd) {
1000031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    char *buffer;
1010031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    size_t len = strnlen(cmd, 255);
1020031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    int res;
1030031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1040031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (len == 255) {
1050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("command too long");
1060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
1070031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
1080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    asprintf(&buffer, "%s %s", IPTABLES_PATH, cmd);
1100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    res = system_nosh(buffer);
1110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    ALOGV("%s #%d", buffer, res);
1120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    free(buffer);
1130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return res;
1150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1160031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallbool IdletimerController::setupIptablesHooks() {
1180031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runIpxtablesCmd("-t nat -D PREROUTING -j idletimer_nat_PREROUTING");
1190031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runIpxtablesCmd("-t nat -F idletimer_nat_PREROUTING");
1200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runIpxtablesCmd("-t nat -N idletimer_nat_PREROUTING");
1210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runIpxtablesCmd("-t nat -D POSTROUTING -j idletimer_nat_POSTROUTING");
1230031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runIpxtablesCmd("-t nat -F idletimer_nat_POSTROUTING");
1240031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runIpxtablesCmd("-t nat -N idletimer_nat_POSTROUTING");
1250031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (runIpxtablesCmd("-t nat -I PREROUTING -j idletimer_nat_PREROUTING")
1270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        || runIpxtablesCmd("-t nat -I POSTROUTING -j idletimer_nat_POSTROUTING")) {
1280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return false;
1290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
1300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return true;
1310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::setDefaults() {
1340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  if (runIpxtablesCmd("-t nat -F idletimer_nat_PREROUTING")
1350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      || runIpxtablesCmd("-t nat -F idletimer_nat_POSTROUTING") )
1360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      return -1;
1370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  return 0;
1380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1400031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::enableIdletimerControl() {
1410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    int res = setDefaults();
1420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return res;
1430031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::disableIdletimerControl() {
1460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    int res = setDefaults();
1470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return res;
1480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1500031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::modifyInterfaceIdletimer(IptOp op, const char *iface,
1510031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall                                                  uint32_t timeout) {
1520031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  int res;
1530031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  char *buffer;
1540031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  asprintf(&buffer, "-t nat -%c idletimer_nat_PREROUTING -i %s -j IDLETIMER"
1550031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall           " --timeout %u --label %s --send_nl_msg 1",
1560031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall           (op == IptOpAdd) ? 'A' : 'D', iface, timeout, iface);
1570031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  res = runIpxtablesCmd(buffer);
1580031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  free(buffer);
1590031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1600031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  asprintf(&buffer, "-t nat -%c idletimer_nat_POSTROUTING -o %s -j IDLETIMER"
1610031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall           " --timeout %u --label %s --send_nl_msg 1",
1620031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall           (op == IptOpAdd) ? 'A' : 'D', iface, timeout, iface);
1630031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  res |= runIpxtablesCmd(buffer);
1640031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  free(buffer);
1650031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1660031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  return res;
1670031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1680031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1690031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::addInterfaceIdletimer(const char *iface, uint32_t timeout) {
1700031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  return modifyInterfaceIdletimer(IptOpAdd, iface, timeout);
1710031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1730031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::removeInterfaceIdletimer(const char *iface, uint32_t timeout) {
1740031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  return modifyInterfaceIdletimer(IptOpDelete, iface, timeout);
1750031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
176