xref: /aosp_15_r20/system/netd/server/IdletimerController.cpp (revision 8542734a0dd1db395a4d42aae09c37f3c3c3e7a1)
1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker  * Copyright (C) 2012 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker  *
4*8542734aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker  *
8*8542734aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker  *
10*8542734aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker  * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker  */
16*8542734aSAndroid Build Coastguard Worker 
17*8542734aSAndroid Build Coastguard Worker /*
18*8542734aSAndroid Build Coastguard Worker  * MODUS OPERANDI
19*8542734aSAndroid Build Coastguard Worker  * --------------
20*8542734aSAndroid Build Coastguard Worker  *
21*8542734aSAndroid Build Coastguard Worker  * IPTABLES command sequence:
22*8542734aSAndroid Build Coastguard Worker  *
23*8542734aSAndroid Build Coastguard Worker  * iptables -F
24*8542734aSAndroid Build Coastguard Worker  *
25*8542734aSAndroid Build Coastguard Worker  * iptables -t raw -F idletimer_PREROUTING
26*8542734aSAndroid Build Coastguard Worker  * iptables -t mangle -F idletimer_POSTROUTING
27*8542734aSAndroid Build Coastguard Worker  *
28*8542734aSAndroid Build Coastguard Worker  *
29*8542734aSAndroid Build Coastguard Worker  * iptables -t raw -N idletimer_PREROUTING
30*8542734aSAndroid Build Coastguard Worker  * iptables -t mangle -N idletimer_POSTROUTING
31*8542734aSAndroid Build Coastguard Worker  *
32*8542734aSAndroid Build Coastguard Worker  * iptables -t raw -D PREROUTING -j idletimer_PREROUTING
33*8542734aSAndroid Build Coastguard Worker  * iptables -t mangle -D POSTROUTING -j idletimer_POSTROUTING
34*8542734aSAndroid Build Coastguard Worker  *
35*8542734aSAndroid Build Coastguard Worker  *
36*8542734aSAndroid Build Coastguard Worker  * iptables -t raw -I PREROUTING -j idletimer_PREROUTING
37*8542734aSAndroid Build Coastguard Worker  * iptables -t mangle -I POSTROUTING -j idletimer_POSTROUTING
38*8542734aSAndroid Build Coastguard Worker  *
39*8542734aSAndroid Build Coastguard Worker  * # For notifications to work the lable name must match the name of a valid interface.
40*8542734aSAndroid Build Coastguard Worker  * # If the label name does match an interface, the rules will be a no-op.
41*8542734aSAndroid Build Coastguard Worker  *
42*8542734aSAndroid Build Coastguard Worker  * iptables -t raw -A idletimer_PREROUTING -i rmnet0 -j IDLETIMER  --timeout 5 --label test-chain --send_nl_msg
43*8542734aSAndroid Build Coastguard Worker  * iptables -t mangle -A idletimer_POSTROUTING -o rmnet0 -j IDLETIMER  --timeout 5 --label test-chain --send_nl_msg
44*8542734aSAndroid Build Coastguard Worker  *
45*8542734aSAndroid Build Coastguard Worker  * iptables -nxvL -t raw
46*8542734aSAndroid Build Coastguard Worker  * iptables -nxvL -t mangle
47*8542734aSAndroid Build Coastguard Worker  *
48*8542734aSAndroid Build Coastguard Worker  * =================
49*8542734aSAndroid Build Coastguard Worker  *
50*8542734aSAndroid Build Coastguard Worker  * ndc command sequence
51*8542734aSAndroid Build Coastguard Worker  * ------------------
52*8542734aSAndroid Build Coastguard Worker  * ndc idletimer enable
53*8542734aSAndroid Build Coastguard Worker  * ndc idletimer add <iface> <timeout> <class label>
54*8542734aSAndroid Build Coastguard Worker  * ndc idletimer remove <iface> <timeout> <class label>
55*8542734aSAndroid Build Coastguard Worker  *
56*8542734aSAndroid Build Coastguard Worker  * Monitor effect on the iptables chains after each step using:
57*8542734aSAndroid Build Coastguard Worker  *     iptables -nxvL -t raw
58*8542734aSAndroid Build Coastguard Worker  *     iptables -nxvL -t mangle
59*8542734aSAndroid Build Coastguard Worker  *
60*8542734aSAndroid Build Coastguard Worker  * Remember that the timeout value has to be same at the time of the
61*8542734aSAndroid Build Coastguard Worker  * removal.
62*8542734aSAndroid Build Coastguard Worker  *
63*8542734aSAndroid Build Coastguard Worker  * =================
64*8542734aSAndroid Build Coastguard Worker  *
65*8542734aSAndroid Build Coastguard Worker  * Verifying the iptables rule
66*8542734aSAndroid Build Coastguard Worker  * ---------------------------
67*8542734aSAndroid Build Coastguard Worker  * We want to make sure the iptable rules capture every packet. It can be
68*8542734aSAndroid Build Coastguard Worker  * verified with tcpdump. First take a note of the pkts count for the two rules:
69*8542734aSAndroid Build Coastguard Worker  *
70*8542734aSAndroid Build Coastguard Worker  * adb shell iptables -t mangle -L idletimer_mangle_POSTROUTING -v && adb shell iptables -t raw -L idletimer_raw_PREROUTING -v
71*8542734aSAndroid Build Coastguard Worker  *
72*8542734aSAndroid Build Coastguard Worker  * And then, before any network traffics happen on the device, run tcpdump:
73*8542734aSAndroid Build Coastguard Worker  *
74*8542734aSAndroid Build Coastguard Worker  * adb shell tcpdump | tee tcpdump.log
75*8542734aSAndroid Build Coastguard Worker  *
76*8542734aSAndroid Build Coastguard Worker  * After a while run iptables commands again, you could then count the number
77*8542734aSAndroid Build Coastguard Worker  * of incoming and outgoing packets captured by tcpdump, and compare that with
78*8542734aSAndroid Build Coastguard Worker  * the numbers reported by iptables command. There shouldn't be too much
79*8542734aSAndroid Build Coastguard Worker  * difference on these numbers, i.e., with 2000 packets captured it should
80*8542734aSAndroid Build Coastguard Worker  * differ by less than 5.
81*8542734aSAndroid Build Coastguard Worker  *
82*8542734aSAndroid Build Coastguard Worker  * =================
83*8542734aSAndroid Build Coastguard Worker  *
84*8542734aSAndroid Build Coastguard Worker  * Note that currently if the name of the iface is incorrect, iptables
85*8542734aSAndroid Build Coastguard Worker  * will setup rules without checking if it is the name of a valid
86*8542734aSAndroid Build Coastguard Worker  * interface (although no notifications will ever be received).  It is
87*8542734aSAndroid Build Coastguard Worker  * the responsibility of code in Java land to ensure that the interface name
88*8542734aSAndroid Build Coastguard Worker  * is correct. The benefit of this, is that idletimers can be setup on
89*8542734aSAndroid Build Coastguard Worker  * interfaces than come and go.
90*8542734aSAndroid Build Coastguard Worker  *
91*8542734aSAndroid Build Coastguard Worker  * A remove should be called for each add command issued during cleanup, as duplicate
92*8542734aSAndroid Build Coastguard Worker  * entries of the rule may exist and will all have to removed.
93*8542734aSAndroid Build Coastguard Worker  *
94*8542734aSAndroid Build Coastguard Worker  */
95*8542734aSAndroid Build Coastguard Worker 
96*8542734aSAndroid Build Coastguard Worker #define LOG_NDEBUG 0
97*8542734aSAndroid Build Coastguard Worker 
98*8542734aSAndroid Build Coastguard Worker #include <string>
99*8542734aSAndroid Build Coastguard Worker #include <vector>
100*8542734aSAndroid Build Coastguard Worker 
101*8542734aSAndroid Build Coastguard Worker #include <stdint.h>
102*8542734aSAndroid Build Coastguard Worker #include <stdlib.h>
103*8542734aSAndroid Build Coastguard Worker #include <errno.h>
104*8542734aSAndroid Build Coastguard Worker #include <sys/socket.h>
105*8542734aSAndroid Build Coastguard Worker #include <sys/stat.h>
106*8542734aSAndroid Build Coastguard Worker #include <sys/wait.h>
107*8542734aSAndroid Build Coastguard Worker #include <fcntl.h>
108*8542734aSAndroid Build Coastguard Worker #include <netinet/in.h>
109*8542734aSAndroid Build Coastguard Worker #include <arpa/inet.h>
110*8542734aSAndroid Build Coastguard Worker #include <string.h>
111*8542734aSAndroid Build Coastguard Worker #include <cutils/properties.h>
112*8542734aSAndroid Build Coastguard Worker 
113*8542734aSAndroid Build Coastguard Worker #include <android-base/strings.h>
114*8542734aSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
115*8542734aSAndroid Build Coastguard Worker 
116*8542734aSAndroid Build Coastguard Worker #define LOG_TAG "IdletimerController"
117*8542734aSAndroid Build Coastguard Worker #include <log/log.h>
118*8542734aSAndroid Build Coastguard Worker 
119*8542734aSAndroid Build Coastguard Worker #include "IdletimerController.h"
120*8542734aSAndroid Build Coastguard Worker #include "NetdConstants.h"
121*8542734aSAndroid Build Coastguard Worker 
122*8542734aSAndroid Build Coastguard Worker using android::base::Join;
123*8542734aSAndroid Build Coastguard Worker using android::base::StringPrintf;
124*8542734aSAndroid Build Coastguard Worker 
125*8542734aSAndroid Build Coastguard Worker const char* IdletimerController::LOCAL_RAW_PREROUTING = "idletimer_raw_PREROUTING";
126*8542734aSAndroid Build Coastguard Worker const char* IdletimerController::LOCAL_MANGLE_POSTROUTING = "idletimer_mangle_POSTROUTING";
127*8542734aSAndroid Build Coastguard Worker 
128*8542734aSAndroid Build Coastguard Worker auto IdletimerController::execIptablesRestore = ::execIptablesRestore;
129*8542734aSAndroid Build Coastguard Worker 
IdletimerController()130*8542734aSAndroid Build Coastguard Worker IdletimerController::IdletimerController() {
131*8542734aSAndroid Build Coastguard Worker }
132*8542734aSAndroid Build Coastguard Worker 
~IdletimerController()133*8542734aSAndroid Build Coastguard Worker IdletimerController::~IdletimerController() {
134*8542734aSAndroid Build Coastguard Worker }
135*8542734aSAndroid Build Coastguard Worker 
setupIptablesHooks()136*8542734aSAndroid Build Coastguard Worker bool IdletimerController::setupIptablesHooks() {
137*8542734aSAndroid Build Coastguard Worker     return true;
138*8542734aSAndroid Build Coastguard Worker }
139*8542734aSAndroid Build Coastguard Worker 
modifyInterfaceIdletimer(IptOp op,const char * iface,uint32_t timeout,const char * classLabel)140*8542734aSAndroid Build Coastguard Worker int IdletimerController::modifyInterfaceIdletimer(IptOp op, const char *iface,
141*8542734aSAndroid Build Coastguard Worker                                                   uint32_t timeout,
142*8542734aSAndroid Build Coastguard Worker                                                   const char *classLabel) {
143*8542734aSAndroid Build Coastguard Worker     if (!isIfaceName(iface)) {
144*8542734aSAndroid Build Coastguard Worker         errno = ENOENT;
145*8542734aSAndroid Build Coastguard Worker         return -1;
146*8542734aSAndroid Build Coastguard Worker     }
147*8542734aSAndroid Build Coastguard Worker 
148*8542734aSAndroid Build Coastguard Worker     const char *addRemove = (op == IptOpAdd) ? "-A" : "-D";
149*8542734aSAndroid Build Coastguard Worker     std::vector<std::string> cmds = {
150*8542734aSAndroid Build Coastguard Worker             "*raw",
151*8542734aSAndroid Build Coastguard Worker             StringPrintf("%s %s -i %s -j IDLETIMER --timeout %u --label %s --send_nl_msg",
152*8542734aSAndroid Build Coastguard Worker                          addRemove, LOCAL_RAW_PREROUTING, iface, timeout, classLabel),
153*8542734aSAndroid Build Coastguard Worker             "COMMIT",
154*8542734aSAndroid Build Coastguard Worker             "*mangle",
155*8542734aSAndroid Build Coastguard Worker             StringPrintf("%s %s -o %s -j IDLETIMER --timeout %u --label %s --send_nl_msg",
156*8542734aSAndroid Build Coastguard Worker                          addRemove, LOCAL_MANGLE_POSTROUTING, iface, timeout, classLabel),
157*8542734aSAndroid Build Coastguard Worker             "COMMIT\n",
158*8542734aSAndroid Build Coastguard Worker     };
159*8542734aSAndroid Build Coastguard Worker 
160*8542734aSAndroid Build Coastguard Worker     return (execIptablesRestore(V4V6, Join(cmds, '\n')) == 0) ? 0 : -EREMOTEIO;
161*8542734aSAndroid Build Coastguard Worker }
162*8542734aSAndroid Build Coastguard Worker 
addInterfaceIdletimer(const char * iface,uint32_t timeout,const char * classLabel)163*8542734aSAndroid Build Coastguard Worker int IdletimerController::addInterfaceIdletimer(const char *iface,
164*8542734aSAndroid Build Coastguard Worker                                                uint32_t timeout,
165*8542734aSAndroid Build Coastguard Worker                                                const char *classLabel) {
166*8542734aSAndroid Build Coastguard Worker     return modifyInterfaceIdletimer(IptOpAdd, iface, timeout, classLabel);
167*8542734aSAndroid Build Coastguard Worker }
168*8542734aSAndroid Build Coastguard Worker 
removeInterfaceIdletimer(const char * iface,uint32_t timeout,const char * classLabel)169*8542734aSAndroid Build Coastguard Worker int IdletimerController::removeInterfaceIdletimer(const char *iface,
170*8542734aSAndroid Build Coastguard Worker                                                   uint32_t timeout,
171*8542734aSAndroid Build Coastguard Worker                                                   const char *classLabel) {
172*8542734aSAndroid Build Coastguard Worker     return modifyInterfaceIdletimer(IptOpDelete, iface, timeout, classLabel);
173*8542734aSAndroid Build Coastguard Worker }
174