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 /* 18 * MODUS OPERANDI 19 * -------------- 20 * 21 * IPTABLES command sequence: 22 * 23 * iptables -F 24 * 25 * iptables -t raw -F idletimer_PREROUTING 26 * iptables -t mangle -F idletimer_POSTROUTING 27 * 28 * 29 * iptables -t raw -N idletimer_PREROUTING 30 * iptables -t mangle -N idletimer_POSTROUTING 31 * 32 * iptables -t raw -D PREROUTING -j idletimer_PREROUTING 33 * iptables -t mangle -D POSTROUTING -j idletimer_POSTROUTING 34 * 35 * 36 * iptables -t raw -I PREROUTING -j idletimer_PREROUTING 37 * iptables -t mangle -I POSTROUTING -j idletimer_POSTROUTING 38 * 39 * # For notifications to work the lable name must match the name of a valid interface. 40 * # If the label name does match an interface, the rules will be a no-op. 41 * 42 * iptables -t raw -A idletimer_PREROUTING -i rmnet0 -j IDLETIMER --timeout 5 --label test-chain --send_nl_msg 1 43 * iptables -t mangle -A idletimer_POSTROUTING -o rmnet0 -j IDLETIMER --timeout 5 --label test-chain --send_nl_msg 1 44 * 45 * iptables -nxvL -t raw 46 * iptables -nxvL -t mangle 47 * 48 * ================= 49 * 50 * ndc command sequence 51 * ------------------ 52 * ndc idletimer enable 53 * ndc idletimer add <iface> <timeout> <class label> 54 * ndc idletimer remove <iface> <timeout> <class label> 55 * 56 * Monitor effect on the iptables chains after each step using: 57 * iptables -nxvL -t raw 58 * iptables -nxvL -t mangle 59 * 60 * Remember that the timeout value has to be same at the time of the 61 * removal. 62 * 63 * ================= 64 * 65 * Verifying the iptables rule 66 * --------------------------- 67 * We want to make sure the iptable rules capture every packet. It can be 68 * verified with tcpdump. First take a note of the pkts count for the two rules: 69 * 70 * adb shell iptables -t mangle -L idletimer_mangle_POSTROUTING -v && adb shell iptables -t raw -L idletimer_raw_PREROUTING -v 71 * 72 * And then, before any network traffics happen on the device, run tcpdump: 73 * 74 * adb shell tcpdump | tee tcpdump.log 75 * 76 * After a while run iptables commands again, you could then count the number 77 * of incoming and outgoing packets captured by tcpdump, and compare that with 78 * the numbers reported by iptables command. There shouldn't be too much 79 * difference on these numbers, i.e., with 2000 packets captured it should 80 * differ by less than 5. 81 * 82 * ================= 83 * 84 * Note that currently if the name of the iface is incorrect, iptables 85 * will setup rules without checking if it is the name of a valid 86 * interface (although no notifications will ever be received). It is 87 * the responsibility of code in Java land to ensure that the interface name 88 * is correct. The benefit of this, is that idletimers can be setup on 89 * interfaces than come and go. 90 * 91 * A remove should be called for each add command issued during cleanup, as duplicate 92 * entries of the rule may exist and will all have to removed. 93 * 94 */ 95 96 #define LOG_NDEBUG 0 97 98 #include <string> 99 #include <vector> 100 101 #include <stdint.h> 102 #include <stdlib.h> 103 #include <errno.h> 104 #include <sys/socket.h> 105 #include <sys/stat.h> 106 #include <sys/wait.h> 107 #include <fcntl.h> 108 #include <netinet/in.h> 109 #include <arpa/inet.h> 110 #include <string.h> 111 #include <cutils/properties.h> 112 113 #include <android-base/strings.h> 114 #include <android-base/stringprintf.h> 115 116 #define LOG_TAG "IdletimerController" 117 #include <cutils/log.h> 118 #include <logwrap/logwrap.h> 119 120 #include "IdletimerController.h" 121 #include "NetdConstants.h" 122 123 using android::base::Join; 124 using android::base::StringPrintf; 125 126 const char* IdletimerController::LOCAL_RAW_PREROUTING = "idletimer_raw_PREROUTING"; 127 const char* IdletimerController::LOCAL_MANGLE_POSTROUTING = "idletimer_mangle_POSTROUTING"; 128 129 auto IdletimerController::execIptablesRestore = ::execIptablesRestore; 130 131 IdletimerController::IdletimerController() { 132 } 133 134 IdletimerController::~IdletimerController() { 135 } 136 137 bool IdletimerController::setupIptablesHooks() { 138 return true; 139 } 140 141 int IdletimerController::setDefaults() { 142 std::vector<std::string> cmds = { 143 "*raw", 144 StringPrintf(":%s -", LOCAL_RAW_PREROUTING), 145 "COMMIT", 146 "*mangle", 147 StringPrintf(":%s -", LOCAL_MANGLE_POSTROUTING), 148 "COMMIT\n", 149 }; 150 151 return execIptablesRestore(V4V6, Join(cmds, '\n')); 152 } 153 154 int IdletimerController::enableIdletimerControl() { 155 int res = setDefaults(); 156 return res; 157 } 158 159 int IdletimerController::disableIdletimerControl() { 160 int res = setDefaults(); 161 return res; 162 } 163 164 int IdletimerController::modifyInterfaceIdletimer(IptOp op, const char *iface, 165 uint32_t timeout, 166 const char *classLabel) { 167 if (!isIfaceName(iface)) { 168 errno = ENOENT; 169 return -1; 170 } 171 172 const char *addRemove = (op == IptOpAdd) ? "-A" : "-D"; 173 std::vector<std::string> cmds = { 174 "*raw", 175 StringPrintf("%s %s -i %s -j IDLETIMER --timeout %u --label %s --send_nl_msg 1", 176 addRemove, LOCAL_RAW_PREROUTING, iface, timeout, classLabel), 177 "COMMIT", 178 "*mangle", 179 StringPrintf("%s %s -o %s -j IDLETIMER --timeout %u --label %s --send_nl_msg 1", 180 addRemove, LOCAL_MANGLE_POSTROUTING, iface, timeout, classLabel), 181 "COMMIT\n", 182 }; 183 184 return execIptablesRestore(V4V6, Join(cmds, '\n')); 185 } 186 187 int IdletimerController::addInterfaceIdletimer(const char *iface, 188 uint32_t timeout, 189 const char *classLabel) { 190 return modifyInterfaceIdletimer(IptOpAdd, iface, timeout, classLabel); 191 } 192 193 int IdletimerController::removeInterfaceIdletimer(const char *iface, 194 uint32_t timeout, 195 const char *classLabel) { 196 return modifyInterfaceIdletimer(IptOpDelete, iface, timeout, classLabel); 197 } 198