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