forked from CyanogenMod/android_system_netd
-
Notifications
You must be signed in to change notification settings - Fork 2
/
IdletimerController.cpp
235 lines (211 loc) · 6.58 KB
/
IdletimerController.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// #define LOG_NDEBUG 0
/*
* MODUS OPERANDI
* --------------
*
* IPTABLES command sequence:
*
* iptables -F
*
* iptables -t raw -F idletimer_PREROUTING
* iptables -t mangle -F idletimer_POSTROUTING
*
*
* iptables -t raw -N idletimer_PREROUTING
* iptables -t mangle -N idletimer_POSTROUTING
*
* iptables -t raw -D PREROUTING -j idletimer_PREROUTING
* iptables -t mangle -D POSTROUTING -j idletimer_POSTROUTING
*
*
* iptables -t raw -I PREROUTING -j idletimer_PREROUTING
* iptables -t mangle -I POSTROUTING -j idletimer_POSTROUTING
*
* # For notifications to work the lable name must match the name of a valid interface.
* # If the label name does match an interface, the rules will be a no-op.
*
* iptables -t raw -A idletimer_PREROUTING -i rmnet0 -j IDLETIMER --timeout 5 --label test-chain --send_nl_msg 1
* iptables -t mangle -A idletimer_POSTROUTING -o rmnet0 -j IDLETIMER --timeout 5 --label test-chain --send_nl_msg 1
*
* iptables -nxvL -t raw
* iptables -nxvL -t mangle
*
* =================
*
* ndc command sequence
* ------------------
* ndc idletimer enable
* ndc idletimer add <iface> <timeout> <class label>
* ndc idletimer remove <iface> <timeout> <class label>
*
* Monitor effect on the iptables chains after each step using:
* iptables -nxvL -t raw
* iptables -nxvL -t mangle
*
* Remember that the timeout value has to be same at the time of the
* removal.
*
* =================
*
* Verifying the iptables rule
* ---------------------------
* We want to make sure the iptable rules capture every packet. It can be
* verified with tcpdump. First take a note of the pkts count for the two rules:
*
* adb shell iptables -t mangle -L idletimer_mangle_POSTROUTING -v && adb shell iptables -t raw -L idletimer_raw_PREROUTING -v
*
* And then, before any network traffics happen on the device, run tcpdump:
*
* adb shell tcpdump | tee tcpdump.log
*
* After a while run iptables commands again, you could then count the number
* of incoming and outgoing packets captured by tcpdump, and compare that with
* the numbers reported by iptables command. There shouldn't be too much
* difference on these numbers, i.e., with 2000 packets captured it should
* differ by less than 5.
*
* =================
*
* Note that currently if the name of the iface is incorrect, iptables
* will setup rules without checking if it is the name of a valid
* interface (although no notifications will ever be received). It is
* the responsibility of code in Java land to ensure that the interface name
* is correct. The benefit of this, is that idletimers can be setup on
* interfaces than come and go.
*
* A remove should be called for each add command issued during cleanup, as duplicate
* entries of the rule may exist and will all have to removed.
*
*/
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <cutils/properties.h>
#define LOG_TAG "IdletimerController"
#include <cutils/log.h>
#include <logwrap/logwrap.h>
#include "IdletimerController.h"
#include "NetdConstants.h"
const char* IdletimerController::LOCAL_RAW_PREROUTING = "idletimer_raw_PREROUTING";
const char* IdletimerController::LOCAL_MANGLE_POSTROUTING = "idletimer_mangle_POSTROUTING";
IdletimerController::IdletimerController() {
}
IdletimerController::~IdletimerController() {
}
/* return 0 or non-zero */
int IdletimerController::runIpxtablesCmd(int argc, const char **argv) {
int res;
res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
ALOGV("runCmd() res=%d", res);
return res;
}
bool IdletimerController::setupIptablesHooks() {
return true;
}
int IdletimerController::setDefaults() {
int res;
const char *cmd1[] = {
IPTABLES_PATH,
"-t",
"raw",
"-F",
LOCAL_RAW_PREROUTING
};
res = runIpxtablesCmd(ARRAY_SIZE(cmd1), cmd1);
if (res)
return res;
const char *cmd2[] = {
IPTABLES_PATH,
"-t",
"mangle",
"-F",
LOCAL_MANGLE_POSTROUTING
};
res = runIpxtablesCmd(ARRAY_SIZE(cmd2), cmd2);
return res;
}
int IdletimerController::enableIdletimerControl() {
int res = setDefaults();
return res;
}
int IdletimerController::disableIdletimerControl() {
int res = setDefaults();
return res;
}
int IdletimerController::modifyInterfaceIdletimer(IptOp op, const char *iface,
uint32_t timeout,
const char *classLabel) {
int res;
char timeout_str[11]; //enough to store any 32-bit unsigned decimal
snprintf(timeout_str, sizeof(timeout_str), "%u", timeout);
const char *cmd1[] = {
IPTABLES_PATH,
"-t",
"raw",
(op == IptOpAdd) ? "-A" : "-D",
LOCAL_RAW_PREROUTING,
"-i",
iface,
"-j",
"IDLETIMER",
"--timeout",
timeout_str,
"--label",
classLabel,
"--send_nl_msg",
"1"
};
res = runIpxtablesCmd(ARRAY_SIZE(cmd1), cmd1);
if (res)
return res;
const char *cmd2[] = {
IPTABLES_PATH,
"-t",
"mangle",
(op == IptOpAdd) ? "-A" : "-D",
LOCAL_MANGLE_POSTROUTING,
"-o",
iface,
"-j",
"IDLETIMER",
"--timeout",
timeout_str,
"--label",
classLabel,
"--send_nl_msg",
"1"
};
res = runIpxtablesCmd(ARRAY_SIZE(cmd2), cmd2);
return res;
}
int IdletimerController::addInterfaceIdletimer(const char *iface,
uint32_t timeout,
const char *classLabel) {
return modifyInterfaceIdletimer(IptOpAdd, iface, timeout, classLabel);
}
int IdletimerController::removeInterfaceIdletimer(const char *iface,
uint32_t timeout,
const char *classLabel) {
return modifyInterfaceIdletimer(IptOpDelete, iface, timeout, classLabel);
}