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 *
275c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * iptables -t raw -F idletimer_PREROUTING
285c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * iptables -t mangle -F idletimer_POSTROUTING
290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
315c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * iptables -t raw -N idletimer_PREROUTING
325c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * iptables -t mangle -N idletimer_POSTROUTING
330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
345c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * iptables -t raw -D PREROUTING -j idletimer_PREROUTING
355c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * iptables -t mangle -D POSTROUTING -j idletimer_POSTROUTING
360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
385c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * iptables -t raw -I PREROUTING -j idletimer_PREROUTING
395c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu 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 *
445c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * iptables -t raw -A idletimer_PREROUTING -i rmnet0 -j IDLETIMER  --timeout 5 --label test-chain --send_nl_msg 1
455c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * iptables -t mangle -A idletimer_POSTROUTING -o rmnet0 -j IDLETIMER  --timeout 5 --label test-chain --send_nl_msg 1
460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall *
475c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * iptables -nxvL -t raw
485c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu 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:
595c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai *     iptables -nxvL -t raw
605c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu 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 *
655c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * =================
665c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai *
675c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * Verifying the iptables rule
685c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * ---------------------------
695c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * We want to make sure the iptable rules capture every packet. It can be
705c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * verified with tcpdump. First take a note of the pkts count for the two rules:
715c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai *
725c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * adb shell iptables -t mangle -L idletimer_mangle_POSTROUTING -v && adb shell iptables -t raw -L idletimer_raw_PREROUTING -v
735c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai *
745c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * And then, before any network traffics happen on the device, run tcpdump:
755c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai *
765c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * adb shell tcpdump | tee tcpdump.log
775c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai *
785c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * After a while run iptables commands again, you could then count the number
795c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * of incoming and outgoing packets captured by tcpdump, and compare that with
805c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * the numbers reported by iptables command. There shouldn't be too much
815c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * difference on these numbers, i.e., with 2000 packets captured it should
825c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * differ by less than 5.
835c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai *
845c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai * =================
855c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu 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
1165c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Baiconst char* IdletimerController::LOCAL_RAW_PREROUTING = "idletimer_raw_PREROUTING";
1175c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu 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() {
1485c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  int res;
1495c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  char *buffer;
1505c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  asprintf(&buffer, "-t raw -F %s", LOCAL_RAW_PREROUTING);
1515c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  res = runIpxtablesCmd(buffer);
1525c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  free(buffer);
1535c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai
1545c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  if (res)
1555c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai    return res;
1565c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai
1575c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  asprintf(&buffer, "-t mangle -F %s", LOCAL_MANGLE_POSTROUTING);
1585c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  res = runIpxtablesCmd(buffer);
1595c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  free(buffer);
1605c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu 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;
1785c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  asprintf(&buffer, "-t raw -%c %s -i %s -j IDLETIMER"
1790031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall           " --timeout %u --label %s --send_nl_msg 1",
1805c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai           (op == IptOpAdd) ? 'A' : 'D', LOCAL_RAW_PREROUTING, iface, timeout, classLabel);
1810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  res = runIpxtablesCmd(buffer);
1820031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  free(buffer);
1830031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1845c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  if (res)
1855c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai    return res;
1865c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai
1875c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai  asprintf(&buffer, "-t mangle -%c %s -o %s -j IDLETIMER"
1880031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall           " --timeout %u --label %s --send_nl_msg 1",
1895c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai           (op == IptOpAdd) ? 'A' : 'D', LOCAL_MANGLE_POSTROUTING, iface, timeout, classLabel);
1905c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu 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