OSDN Git Service

Merge "Don't log "Unexpected netlink message" on NDUSEROPT"
[android-x86/system-netd.git] / IdletimerController.cpp
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 <sys/wait.h>
103 #include <fcntl.h>
104 #include <netinet/in.h>
105 #include <arpa/inet.h>
106 #include <string.h>
107 #include <cutils/properties.h>
108
109 #define LOG_TAG "IdletimerController"
110 #include <cutils/log.h>
111 #include <logwrap/logwrap.h>
112
113 #include "IdletimerController.h"
114 #include "NetdConstants.h"
115
116 const char* IdletimerController::LOCAL_RAW_PREROUTING = "idletimer_raw_PREROUTING";
117 const char* IdletimerController::LOCAL_MANGLE_POSTROUTING = "idletimer_mangle_POSTROUTING";
118
119 IdletimerController::IdletimerController() {
120 }
121
122 IdletimerController::~IdletimerController() {
123 }
124 /* return 0 or non-zero */
125 int IdletimerController::runIpxtablesCmd(int argc, const char **argv) {
126     int res;
127
128     res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
129     ALOGV("runCmd() res=%d", res);
130     return res;
131 }
132
133 bool IdletimerController::setupIptablesHooks() {
134     return true;
135 }
136
137 int IdletimerController::setDefaults() {
138   int res;
139   const char *cmd1[] = {
140       IPTABLES_PATH,
141       "-t",
142       "raw",
143       "-F",
144       LOCAL_RAW_PREROUTING
145   };
146   res = runIpxtablesCmd(ARRAY_SIZE(cmd1), cmd1);
147
148   if (res)
149     return res;
150
151   const char *cmd2[] = {
152       IPTABLES_PATH,
153       "-t",
154       "mangle",
155       "-F",
156       LOCAL_MANGLE_POSTROUTING
157   };
158   res = runIpxtablesCmd(ARRAY_SIZE(cmd2), cmd2);
159
160   return res;
161 }
162
163 int IdletimerController::enableIdletimerControl() {
164     int res = setDefaults();
165     return res;
166 }
167
168 int IdletimerController::disableIdletimerControl() {
169     int res = setDefaults();
170     return res;
171 }
172
173 int IdletimerController::modifyInterfaceIdletimer(IptOp op, const char *iface,
174                                                   uint32_t timeout,
175                                                   const char *classLabel) {
176   int res;
177   char timeout_str[11]; //enough to store any 32-bit unsigned decimal
178
179   snprintf(timeout_str, sizeof(timeout_str), "%u", timeout);
180
181   const char *cmd1[] = {
182       IPTABLES_PATH,
183       "-t",
184       "raw",
185       (op == IptOpAdd) ? "-A" : "-D",
186       LOCAL_RAW_PREROUTING,
187       "-i",
188       iface,
189       "-j",
190       "IDLETIMER",
191       "--timeout",
192       timeout_str,
193       "--label",
194       classLabel,
195       "--send_nl_msg",
196       "1"
197   };
198   res = runIpxtablesCmd(ARRAY_SIZE(cmd1), cmd1);
199
200   if (res)
201     return res;
202
203   const char *cmd2[] = {
204       IPTABLES_PATH,
205       "-t",
206       "mangle",
207       (op == IptOpAdd) ? "-A" : "-D",
208       LOCAL_MANGLE_POSTROUTING,
209       "-o",
210       iface,
211       "-j",
212       "IDLETIMER",
213       "--timeout",
214       timeout_str,
215       "--label",
216       classLabel,
217       "--send_nl_msg",
218       "1"
219   };
220   res = runIpxtablesCmd(ARRAY_SIZE(cmd2), cmd2);
221
222   return res;
223 }
224
225 int IdletimerController::addInterfaceIdletimer(const char *iface,
226                                                uint32_t timeout,
227                                                const char *classLabel) {
228   return modifyInterfaceIdletimer(IptOpAdd, iface, timeout, classLabel);
229 }
230
231 int IdletimerController::removeInterfaceIdletimer(const char *iface,
232                                                   uint32_t timeout,
233                                                   const char *classLabel) {
234   return modifyInterfaceIdletimer(IptOpDelete, iface, timeout, classLabel);
235 }