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