IdletimerController.cpp revision 8c54ec5de3818ff0c0cfc735c817be2516454415
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 *
278c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -t raw -F idletimer_PREROUTING
288c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -t mangle -F idletimer_POSTROUTING
290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
318c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -t raw -N idletimer_PREROUTING
328c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -t mangle -N idletimer_POSTROUTING
330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
348c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -t raw -D PREROUTING -j idletimer_PREROUTING
358c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -t mangle -D POSTROUTING -j idletimer_POSTROUTING
360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
388c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -t raw -I PREROUTING -j idletimer_PREROUTING
398c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -t mangle -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 *
448c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -t raw -A idletimer_PREROUTING -i rmnet0 -j IDLETIMER  --timeout 5 --label test-chain --send_nl_msg 1
458c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -t mangle -A idletimer_POSTROUTING -o rmnet0 -j IDLETIMER  --timeout 5 --label test-chain --send_nl_msg 1
460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
478c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -nxvL -t raw
488c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * iptables -nxvL -t mangle
490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
500031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * =================
510031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
520031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * ndc command sequence
530031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * ------------------
540031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * ndc idletimer enable
5598f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai * ndc idletimer add <iface> <timeout> <class label>
5698f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai * ndc idletimer remove <iface> <timeout> <class label>
570031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
580031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Monitor effect on the iptables chains after each step using:
598c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai *     iptables -nxvL -t raw
608c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai *     iptables -nxvL -t mangle
610031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
620031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Remember that the timeout value has to be same at the time of the
630031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * removal.
640031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
658c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * =================
668c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai *
678c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * Verifying the iptables rule
688c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * ---------------------------
698c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * We want to make sure the iptable rules capture every packet. It can be
708c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * verified with tcpdump. First take a note of the pkts count for the two rules:
718c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai *
728c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * adb shell iptables -t mangle -L idletimer_mangle_POSTROUTING -v && adb shell iptables -t raw -L idletimer_raw_PREROUTING -v
738c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai *
748c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * And then, before any network traffics happen on the device, run tcpdump:
758c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai *
768c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * adb shell tcpdump | tee tcpdump.log
778c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai *
788c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * After a while run iptables commands again, you could then count the number
798c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * of incoming and outgoing packets captured by tcpdump, and compare that with
808c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * the numbers reported by iptables command. There shouldn't be too much
818c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * difference on these numbers, i.e., with 2000 packets captured it should
828c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * differ by less than 5.
838c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai *
848c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai * =================
858c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai *
860031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * Note that currently if the name of the iface is incorrect, iptables
870031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * will setup rules without checking if it is the name of a valid
880031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * interface (although no notifications will ever be received).  It is
890031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * the responsibility of code in Java land to ensure that the interface name
900031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * is correct. The benefit of this, is that idletimers can be setup on
910031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * interfaces than come and go.
920031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
930031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * A remove should be called for each add command issued during cleanup, as duplicate
940031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall * entries of the rule may exist and will all have to removed.
950031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
960031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall */
970031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
980031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <stdlib.h>
990031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <errno.h>
1000031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <sys/socket.h>
1010031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <sys/stat.h>
1020031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <fcntl.h>
1030031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <netinet/in.h>
1040031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <arpa/inet.h>
1050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <string.h>
1060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <cutils/properties.h>
1070031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#define LOG_TAG "IdletimerController"
1090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include <cutils/log.h>
1100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "IdletimerController.h"
1120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "NetdConstants.h"
1130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallextern "C" int system_nosh(const char *command);
1150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1168c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Baiconst char* IdletimerController::LOCAL_RAW_PREROUTING = "idletimer_raw_PREROUTING";
1178c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Baiconst char* IdletimerController::LOCAL_MANGLE_POSTROUTING = "idletimer_mangle_POSTROUTING";
1188e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1190031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP AbgrallIdletimerController::IdletimerController() {
1200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP AbgrallIdletimerController::~IdletimerController() {
1230031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1240031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall/* return 0 or non-zero */
1250031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::runIpxtablesCmd(const char *cmd) {
1260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    char *buffer;
1270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    size_t len = strnlen(cmd, 255);
1280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    int res;
1290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (len == 255) {
1310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        ALOGE("command too long");
1320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
1330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
1340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    asprintf(&buffer, "%s %s", IPTABLES_PATH, cmd);
1360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    res = system_nosh(buffer);
1370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    ALOGV("%s #%d", buffer, res);
1380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    free(buffer);
1390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1400031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return res;
1410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1430031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallbool IdletimerController::setupIptablesHooks() {
1440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return true;
1450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::setDefaults() {
1488c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  int res;
1498c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  char *buffer;
1508c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  asprintf(&buffer, "-t raw -F %s", LOCAL_RAW_PREROUTING);
1518c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  res = runIpxtablesCmd(buffer);
1528c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  free(buffer);
1538c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai
1548c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  if (res)
1558c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai    return res;
1568c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai
1578c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  asprintf(&buffer, "-t mangle -F %s", LOCAL_MANGLE_POSTROUTING);
1588c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  res = runIpxtablesCmd(buffer);
1598c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  free(buffer);
1608c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  return res;
1610031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1620031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1630031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::enableIdletimerControl() {
1640031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    int res = setDefaults();
1650031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return res;
1660031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1670031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1680031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::disableIdletimerControl() {
1690031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    int res = setDefaults();
1700031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return res;
1710031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1730031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint IdletimerController::modifyInterfaceIdletimer(IptOp op, const char *iface,
17498f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai                                                  uint32_t timeout,
17598f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai                                                  const char *classLabel) {
1760031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  int res;
1770031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  char *buffer;
1788c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  asprintf(&buffer, "-t raw -%c %s -i %s -j IDLETIMER"
1790031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall           " --timeout %u --label %s --send_nl_msg 1",
1808c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai           (op == IptOpAdd) ? 'A' : 'D', LOCAL_RAW_PREROUTING, iface, timeout, classLabel);
1810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  res = runIpxtablesCmd(buffer);
1820031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  free(buffer);
1830031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1848c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  if (res)
1858c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai    return res;
1868c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai
1878c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  asprintf(&buffer, "-t mangle -%c %s -o %s -j IDLETIMER"
1880031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall           " --timeout %u --label %s --send_nl_msg 1",
1898c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai           (op == IptOpAdd) ? 'A' : 'D', LOCAL_MANGLE_POSTROUTING, iface, timeout, classLabel);
1908c54ec5de3818ff0c0cfc735c817be2516454415Haoyu Bai  res = runIpxtablesCmd(buffer);
1910031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  free(buffer);
1920031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1930031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  return res;
1940031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1950031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
19698f65d32b1530b4da6050e38d52f955710577efbHaoyu Baiint IdletimerController::addInterfaceIdletimer(const char *iface,
19798f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai                                               uint32_t timeout,
19898f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai                                               const char *classLabel) {
19998f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai  return modifyInterfaceIdletimer(IptOpAdd, iface, timeout, classLabel);
2000031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
2010031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
20298f65d32b1530b4da6050e38d52f955710577efbHaoyu Baiint IdletimerController::removeInterfaceIdletimer(const char *iface,
20398f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai                                                  uint32_t timeout,
20498f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai                                                  const char *classLabel) {
20598f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai  return modifyInterfaceIdletimer(IptOpDelete, iface, timeout, classLabel);
2060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
207