blob: 8a15ded2960f69db789c21f10a5fd5ecb7521f8c [file] [log] [blame]
San Mehat873f2142010-01-14 10:25:07 -08001/*
2 * Copyright (C) 2007 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
17package com.android.server;
18
Jeff Sharkey4529bb62011-12-14 10:31:54 -080019import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
Jeff Sharkey47eb1022011-08-25 17:48:52 -070020import static android.Manifest.permission.DUMP;
Lorenzo Colitti07f13042017-07-10 19:06:57 +090021import static android.Manifest.permission.NETWORK_STACK;
Jeff Sharkeyaf75c332011-11-18 12:41:12 -080022import static android.Manifest.permission.SHUTDOWN;
Erik Kline4d092232017-10-30 15:29:44 +090023import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
24import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
25import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070026import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
27import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
28import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
Felipe Leme011b98f2016-02-10 17:28:31 -080029import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070030import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
31import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
Felipe Leme011b98f2016-02-10 17:28:31 -080032import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070033import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
Sudheer Shanka62f5c172017-03-17 16:25:55 -070034import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070035import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
Sudheer Shanka62f5c172017-03-17 16:25:55 -070036import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070037import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
38import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070039import static android.net.NetworkStats.SET_DEFAULT;
Lorenzo Colitti5356a352017-08-17 19:23:08 +090040import static android.net.NetworkStats.STATS_PER_UID;
Dianne Hackbornd0c5b9a2014-02-21 16:19:05 -080041import static android.net.NetworkStats.TAG_ALL;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070042import static android.net.NetworkStats.TAG_NONE;
43import static android.net.NetworkStats.UID_ALL;
Jeff Sharkeyae2c1812011-10-04 13:11:40 -070044import static android.net.TrafficStats.UID_TETHERING;
Lorenzo Colitti79751842013-02-28 16:16:03 +090045import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -080046import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
47import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -080048import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult;
49import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult;
50import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult;
51import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult;
Jeff Sharkeye4984be2013-09-10 21:03:27 -070052import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -080053import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
Jeff Sharkeya63ba592011-07-19 23:47:12 -070054import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
Erik Klineb2cfdfb2017-01-18 20:54:14 +090055
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070056import android.annotation.NonNull;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080057import android.app.ActivityManager;
Pierre Imai8e48e672016-04-21 13:30:43 +090058import android.content.ContentResolver;
San Mehat873f2142010-01-14 10:25:07 -080059import android.content.Context;
Dianne Hackborn77b987f2014-02-26 16:20:52 -080060import android.net.ConnectivityManager;
Lorenzo Colitti58967ba2016-02-02 17:21:21 +090061import android.net.INetd;
San Mehat4d02d002010-01-22 16:07:46 -080062import android.net.INetworkManagementEventObserver;
Lorenzo Colitti07f13042017-07-10 19:06:57 +090063import android.net.ITetheringStatsProvider;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070064import android.net.InterfaceConfiguration;
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +090065import android.net.IpPrefix;
Robert Greenwalted126402011-01-28 15:34:55 -080066import android.net.LinkAddress;
Lorenzo Colittib57edc52014-08-22 17:10:50 -070067import android.net.Network;
Amith Yamasani15e472352015-04-24 19:06:07 -070068import android.net.NetworkPolicyManager;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070069import android.net.NetworkStats;
Robert Greenwalted126402011-01-28 15:34:55 -080070import android.net.NetworkUtils;
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070071import android.net.RouteInfo;
Paul Jensen6bc2c2c2014-05-07 15:27:40 -040072import android.net.UidRange;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +090073import android.net.util.NetdService;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080074import android.net.wifi.WifiConfiguration;
75import android.net.wifi.WifiConfiguration.KeyMgmt;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070076import android.os.BatteryStats;
Jeff Sharkeyf56e2432012-09-06 17:54:29 -070077import android.os.Binder;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -070078import android.os.Handler;
Lorenzo Colittia0868002017-07-11 02:29:28 +090079import android.os.IBinder;
Dianne Hackborn77b987f2014-02-26 16:20:52 -080080import android.os.INetworkActivityListener;
San Mehat873f2142010-01-14 10:25:07 -080081import android.os.INetworkManagementService;
Lorenzo Colitti563dc452017-09-01 17:12:34 +090082import android.os.PersistableBundle;
Dianne Hackborn77b987f2014-02-26 16:20:52 -080083import android.os.PowerManager;
Jeff Sharkeyf56e2432012-09-06 17:54:29 -070084import android.os.Process;
Jeff Sharkey3df273e2011-12-15 15:47:12 -080085import android.os.RemoteCallbackList;
86import android.os.RemoteException;
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -070087import android.os.ServiceManager;
Lorenzo Colitti4cb42402016-04-24 12:52:00 +090088import android.os.ServiceSpecificException;
Jeff Sharkey605eb792014-11-04 13:34:06 -080089import android.os.StrictMode;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070090import android.os.SystemClock;
Marco Nelissen62dbb222010-02-18 10:56:30 -080091import android.os.SystemProperties;
Felipe Leme29e72ea2016-09-08 13:26:55 -070092import android.os.Trace;
Pierre Imai8e48e672016-04-21 13:30:43 +090093import android.provider.Settings;
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -070094import android.telephony.DataConnectionRealTimeInfo;
95import android.telephony.PhoneStateListener;
Wink Savillefb40dd42014-06-12 17:02:31 -070096import android.telephony.SubscriptionManager;
Wink Saville67e07892014-06-18 16:43:14 -070097import android.telephony.TelephonyManager;
Erik Kline4d092232017-10-30 15:29:44 +090098import android.text.TextUtils;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080099import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800100import android.util.Slog;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700101import android.util.SparseBooleanArray;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800102import android.util.SparseIntArray;
San Mehat873f2142010-01-14 10:25:07 -0800103
Jeff Sharkey605eb792014-11-04 13:34:06 -0800104import com.android.internal.annotations.GuardedBy;
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700105import com.android.internal.annotations.VisibleForTesting;
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -0700106import com.android.internal.app.IBatteryStats;
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700107import com.android.internal.net.NetworkStatsFactory;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600108import com.android.internal.util.DumpUtils;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800109import com.android.internal.util.HexDump;
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700110import com.android.internal.util.Preconditions;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800111import com.android.server.NativeDaemonConnector.Command;
Jeff Sharkey56cd6462013-06-07 15:09:15 -0700112import com.android.server.NativeDaemonConnector.SensitiveArg;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700113import com.google.android.collect.Maps;
Jeff Sharkey4414cea2011-06-24 17:05:24 -0700114
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700115import java.io.BufferedReader;
116import java.io.DataInputStream;
San Mehat873f2142010-01-14 10:25:07 -0800117import java.io.File;
Jeff Sharkey47eb1022011-08-25 17:48:52 -0700118import java.io.FileDescriptor;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700119import java.io.FileInputStream;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700120import java.io.IOException;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700121import java.io.InputStreamReader;
Jeff Sharkey47eb1022011-08-25 17:48:52 -0700122import java.io.PrintWriter;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -0700123import java.net.InetAddress;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700124import java.net.InterfaceAddress;
125import java.net.NetworkInterface;
126import java.net.SocketException;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -0700127import java.util.ArrayList;
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400128import java.util.Arrays;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700129import java.util.HashMap;
jiaguo1da35f72014-01-09 16:39:59 +0800130import java.util.List;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700131import java.util.Map;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -0700132import java.util.NoSuchElementException;
133import java.util.StringTokenizer;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700134import java.util.concurrent.CountDownLatch;
San Mehat873f2142010-01-14 10:25:07 -0800135
136/**
137 * @hide
138 */
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700139public class NetworkManagementService extends INetworkManagementService.Stub
140 implements Watchdog.Monitor {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900141
142 /**
143 * Helper class that encapsulates NetworkManagementService dependencies and makes them
144 * easier to mock in unit tests.
145 */
146 static class SystemServices {
147 public IBinder getService(String name) {
148 return ServiceManager.getService(name);
149 }
150 public void registerLocalService(NetworkManagementInternal nmi) {
151 LocalServices.addService(NetworkManagementInternal.class, nmi);
152 }
153 public INetd getNetd() {
154 return NetdService.get();
155 }
156 }
157
Amith Yamasani15e472352015-04-24 19:06:07 -0700158 private static final String TAG = "NetworkManagement";
159 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
Kenny Root305bcbf2010-09-03 07:56:38 -0700160 private static final String NETD_TAG = "NetdConnector";
Lorenzo Colittia0868002017-07-11 02:29:28 +0900161 static final String NETD_SERVICE_NAME = "netd";
Kenny Root305bcbf2010-09-03 07:56:38 -0700162
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400163 private static final int MAX_UID_RANGES_PER_COMMAND = 10;
164
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700165 /**
166 * Name representing {@link #setGlobalAlert(long)} limit when delivered to
167 * {@link INetworkManagementEventObserver#limitReached(String, String)}.
168 */
169 public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
170
Paul Jensen487ffe72015-07-24 15:57:11 -0400171 /**
172 * String to pass to netd to indicate that a network is only accessible
173 * to apps that have the CHANGE_NETWORK_STATE permission.
174 */
175 public static final String PERMISSION_NETWORK = "NETWORK";
176
177 /**
178 * String to pass to netd to indicate that a network is only
179 * accessible to system apps and those with the CONNECTIVITY_INTERNAL
180 * permission.
181 */
182 public static final String PERMISSION_SYSTEM = "SYSTEM";
183
Andrew Scull45f533c2017-05-19 15:37:20 +0100184 static class NetdResponseCode {
Sreeram Ramachandran03666c72014-07-19 23:21:46 -0700185 /* Keep in sync with system/netd/server/ResponseCode.h */
San Mehat873f2142010-01-14 10:25:07 -0800186 public static final int InterfaceListResult = 110;
187 public static final int TetherInterfaceListResult = 111;
188 public static final int TetherDnsFwdTgtListResult = 112;
San Mehat72759df2010-01-19 13:50:37 -0800189 public static final int TtyListResult = 113;
Jeff Sharkeye4984be2013-09-10 21:03:27 -0700190 public static final int TetheringStatsListResult = 114;
San Mehat873f2142010-01-14 10:25:07 -0800191
192 public static final int TetherStatusResult = 210;
193 public static final int IpFwdStatusResult = 211;
San Mehated4fc8a2010-01-22 12:28:36 -0800194 public static final int InterfaceGetCfgResult = 213;
Robert Greenwalte3253922010-02-18 09:23:25 -0800195 public static final int SoftapStatusResult = 214;
San Mehat91cac642010-03-31 14:31:36 -0700196 public static final int InterfaceRxCounterResult = 216;
197 public static final int InterfaceTxCounterResult = 217;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700198 public static final int QuotaCounterResult = 220;
199 public static final int TetheringStatsResult = 221;
Selim Gurun84c00c62012-02-27 15:42:38 -0800200 public static final int DnsProxyQueryResult = 222;
Lorenzo Colitti79751842013-02-28 16:16:03 +0900201 public static final int ClatdStatusResult = 223;
Robert Greenwalte3253922010-02-18 09:23:25 -0800202
203 public static final int InterfaceChange = 600;
JP Abgrall12b933d2011-07-14 18:09:22 -0700204 public static final int BandwidthControl = 601;
Haoyu Bai6b7358d2012-07-17 16:36:50 -0700205 public static final int InterfaceClassActivity = 613;
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900206 public static final int InterfaceAddressChange = 614;
Lorenzo Colitti5ae4a532013-10-31 11:59:46 +0900207 public static final int InterfaceDnsServerInfo = 615;
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +0900208 public static final int RouteChange = 616;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800209 public static final int StrictCleartext = 617;
San Mehat873f2142010-01-14 10:25:07 -0800210 }
211
Pierre Imai8e48e672016-04-21 13:30:43 +0900212 /* Defaults for resolver parameters. */
213 public static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
214 public static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
215 public static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
216 public static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
217
Rebecca Silbersteine2ec94f2016-03-24 13:29:00 -0700218 /**
219 * String indicating a softap command.
220 */
221 static final String SOFT_AP_COMMAND = "softap";
222
223 /**
224 * String passed back to netd connector indicating softap command success.
225 */
226 static final String SOFT_AP_COMMAND_SUCCESS = "Ok";
227
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700228 static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
229
San Mehat873f2142010-01-14 10:25:07 -0800230 /**
231 * Binder context for this service
232 */
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700233 private final Context mContext;
San Mehat873f2142010-01-14 10:25:07 -0800234
235 /**
236 * connector object for communicating with netd
237 */
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700238 private final NativeDaemonConnector mConnector;
San Mehat873f2142010-01-14 10:25:07 -0800239
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700240 private final Handler mFgHandler;
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700241 private final Handler mDaemonHandler;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700242
Lorenzo Colittia0868002017-07-11 02:29:28 +0900243 private final SystemServices mServices;
244
Lorenzo Colitti58967ba2016-02-02 17:21:21 +0900245 private INetd mNetdService;
246
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800247 private IBatteryStats mBatteryStats;
248
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700249 private final Thread mThread;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700250 private CountDownLatch mConnectedSignal = new CountDownLatch(1);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700251
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800252 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
Christopher Wiley212b95f2016-08-02 11:38:57 -0700253 new RemoteCallbackList<>();
San Mehat4d02d002010-01-22 16:07:46 -0800254
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700255 private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
256
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900257 @GuardedBy("mTetheringStatsProviders")
258 private final HashMap<ITetheringStatsProvider, String>
259 mTetheringStatsProviders = Maps.newHashMap();
260
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700261 /**
262 * If both locks need to be held, then they should be obtained in the order:
263 * first {@link #mQuotaLock} and then {@link #mRulesLock}.
264 */
Andrew Scull45f533c2017-05-19 15:37:20 +0100265 private final Object mQuotaLock = new Object();
Andrew Scull519291f2017-05-23 13:11:03 +0100266 private final Object mRulesLock = new Object();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800267
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700268 /** Set of interfaces with active quotas. */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800269 @GuardedBy("mQuotaLock")
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700270 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700271 /** Set of interfaces with active alerts. */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800272 @GuardedBy("mQuotaLock")
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700273 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
Felipe Leme65be3022016-03-22 14:53:13 -0700274 /** Set of UIDs blacklisted on metered networks. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700275 @GuardedBy("mRulesLock")
Felipe Leme65be3022016-03-22 14:53:13 -0700276 private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
277 /** Set of UIDs whitelisted on metered networks. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700278 @GuardedBy("mRulesLock")
Felipe Leme65be3022016-03-22 14:53:13 -0700279 private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800280 /** Set of UIDs with cleartext penalties. */
281 @GuardedBy("mQuotaLock")
282 private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
Amith Yamasani15e472352015-04-24 19:06:07 -0700283 /** Set of UIDs that are to be blocked/allowed by firewall controller. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700284 @GuardedBy("mRulesLock")
Amith Yamasani15e472352015-04-24 19:06:07 -0700285 private SparseIntArray mUidFirewallRules = new SparseIntArray();
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700286 /**
287 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
288 * to application idles.
289 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700290 @GuardedBy("mRulesLock")
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700291 private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
292 /**
293 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
294 * to device idles.
295 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700296 @GuardedBy("mRulesLock")
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700297 private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
Felipe Leme011b98f2016-02-10 17:28:31 -0800298 /**
299 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
300 * to device on power-save mode.
301 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700302 @GuardedBy("mRulesLock")
Felipe Leme011b98f2016-02-10 17:28:31 -0800303 private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -0700304 /** Set of states for the child firewall chains. True if the chain is active. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700305 @GuardedBy("mRulesLock")
Xiaohui Chen8dca36d2015-06-19 12:44:59 -0700306 final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700307
Felipe Leme65be3022016-03-22 14:53:13 -0700308 @GuardedBy("mQuotaLock")
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700309 private volatile boolean mDataSaverMode;
Felipe Leme65be3022016-03-22 14:53:13 -0700310
Andrew Scull45f533c2017-05-19 15:37:20 +0100311 private final Object mIdleTimerLock = new Object();
Haoyu Bai04124232012-06-28 15:26:19 -0700312 /** Set of interfaces with active idle timers. */
313 private static class IdleTimerParams {
314 public final int timeout;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800315 public final int type;
Haoyu Bai04124232012-06-28 15:26:19 -0700316 public int networkCount;
317
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800318 IdleTimerParams(int timeout, int type) {
Haoyu Bai04124232012-06-28 15:26:19 -0700319 this.timeout = timeout;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800320 this.type = type;
Haoyu Bai04124232012-06-28 15:26:19 -0700321 this.networkCount = 1;
322 }
323 }
324 private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
325
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700326 private volatile boolean mBandwidthControlEnabled;
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700327 private volatile boolean mFirewallEnabled;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800328 private volatile boolean mStrictEnabled;
Jeff Sharkey350083e2011-06-29 10:45:16 -0700329
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700330 private boolean mMobileActivityFromRadio = false;
331 private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
Adam Lesinskie08af192015-03-25 16:42:59 -0700332 private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700333
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800334 private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
Christopher Wiley212b95f2016-08-02 11:38:57 -0700335 new RemoteCallbackList<>();
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800336 private boolean mNetworkActive;
337
San Mehat873f2142010-01-14 10:25:07 -0800338 /**
339 * Constructs a new NetworkManagementService instance
340 *
341 * @param context Binder context for this service
342 */
Lorenzo Colittia0868002017-07-11 02:29:28 +0900343 private NetworkManagementService(
344 Context context, String socket, SystemServices services) {
San Mehat873f2142010-01-14 10:25:07 -0800345 mContext = context;
Lorenzo Colittia0868002017-07-11 02:29:28 +0900346 mServices = services;
San Mehat4d02d002010-01-22 16:07:46 -0800347
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700348 // make sure this is on the same looper as our NativeDaemonConnector for sync purposes
349 mFgHandler = new Handler(FgThread.get().getLooper());
350
Dianne Hackborn4590e522014-03-24 13:36:46 -0700351 // Don't need this wake lock, since we now have a time stamp for when
352 // the network actually went inactive. (It might be nice to still do this,
353 // but I don't want to do it through the power manager because that pollutes the
354 // battery stats history with pointless noise.)
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700355 //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
Dianne Hackborn4590e522014-03-24 13:36:46 -0700356 PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800357
San Mehat873f2142010-01-14 10:25:07 -0800358 mConnector = new NativeDaemonConnector(
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700359 new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
360 FgThread.get().getLooper());
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700361 mThread = new Thread(mConnector, NETD_TAG);
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700362
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700363 mDaemonHandler = new Handler(FgThread.get().getLooper());
Wink Saville67e07892014-06-18 16:43:14 -0700364
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700365 // Add ourself to the Watchdog monitors.
366 Watchdog.getInstance().addMonitor(this);
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700367
Lorenzo Colittia0868002017-07-11 02:29:28 +0900368 mServices.registerLocalService(new LocalService());
Lorenzo Colitti8228eb32017-07-19 06:17:33 +0900369
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900370 synchronized (mTetheringStatsProviders) {
371 mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
372 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700373 }
374
375 @VisibleForTesting
376 NetworkManagementService() {
377 mConnector = null;
378 mContext = null;
379 mDaemonHandler = null;
380 mFgHandler = null;
381 mThread = null;
Lorenzo Colittia0868002017-07-11 02:29:28 +0900382 mServices = null;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700383 }
384
Lorenzo Colittia0868002017-07-11 02:29:28 +0900385 static NetworkManagementService create(Context context, String socket, SystemServices services)
Felipe Leme03e689d2016-03-02 16:17:38 -0800386 throws InterruptedException {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900387 final NetworkManagementService service =
388 new NetworkManagementService(context, socket, services);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700389 final CountDownLatch connectedSignal = service.mConnectedSignal;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700390 if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
391 service.mThread.start();
392 if (DBG) Slog.d(TAG, "Awaiting socket connection");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700393 connectedSignal.await();
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700394 if (DBG) Slog.d(TAG, "Connected");
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900395 if (DBG) Slog.d(TAG, "Connecting native netd service");
bohu07cc3bb2016-05-03 15:58:01 -0700396 service.connectNativeNetdService();
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900397 if (DBG) Slog.d(TAG, "Connected");
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700398 return service;
San Mehat873f2142010-01-14 10:25:07 -0800399 }
400
Lorenzo Colitti7421a012013-08-20 22:51:24 +0900401 public static NetworkManagementService create(Context context) throws InterruptedException {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900402 return create(context, NETD_SERVICE_NAME, new SystemServices());
Lorenzo Colitti7421a012013-08-20 22:51:24 +0900403 }
404
Jeff Sharkey350083e2011-06-29 10:45:16 -0700405 public void systemReady() {
Felipe Leme03e689d2016-03-02 16:17:38 -0800406 if (DBG) {
407 final long start = System.currentTimeMillis();
408 prepareNativeDaemon();
409 final long delta = System.currentTimeMillis() - start;
410 Slog.d(TAG, "Prepared in " + delta + "ms");
411 return;
412 } else {
413 prepareNativeDaemon();
414 }
Jeff Sharkey350083e2011-06-29 10:45:16 -0700415 }
416
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800417 private IBatteryStats getBatteryStats() {
418 synchronized (this) {
419 if (mBatteryStats != null) {
420 return mBatteryStats;
421 }
Lorenzo Colittia0868002017-07-11 02:29:28 +0900422 mBatteryStats =
423 IBatteryStats.Stub.asInterface(mServices.getService(BatteryStats.SERVICE_NAME));
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800424 return mBatteryStats;
425 }
426 }
427
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800428 @Override
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800429 public void registerObserver(INetworkManagementEventObserver observer) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800430 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800431 mObservers.register(observer);
San Mehat4d02d002010-01-22 16:07:46 -0800432 }
433
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800434 @Override
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800435 public void unregisterObserver(INetworkManagementEventObserver observer) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800436 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800437 mObservers.unregister(observer);
San Mehat4d02d002010-01-22 16:07:46 -0800438 }
439
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900440 @FunctionalInterface
441 private interface NetworkManagementEventCallback {
442 public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
443 }
444
445 private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800446 final int length = mObservers.beginBroadcast();
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700447 try {
448 for (int i = 0; i < length; i++) {
449 try {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900450 eventCallback.sendCallback(mObservers.getBroadcastItem(i));
Felipe Leme03e689d2016-03-02 16:17:38 -0800451 } catch (RemoteException | RuntimeException e) {
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700452 }
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700453 }
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700454 } finally {
455 mObservers.finishBroadcast();
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700456 }
457 }
458
459 /**
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900460 * Notify our observers of an interface status change
461 */
462 private void notifyInterfaceStatusChanged(String iface, boolean up) {
463 invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
464 }
465
466 /**
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700467 * Notify our observers of an interface link state change
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700468 * (typically, an Ethernet cable has been plugged-in or unplugged).
469 */
470 private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900471 invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
San Mehat4d02d002010-01-22 16:07:46 -0800472 }
473
474 /**
475 * Notify our observers of an interface addition.
476 */
477 private void notifyInterfaceAdded(String iface) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900478 invokeForAllObservers(o -> o.interfaceAdded(iface));
San Mehat4d02d002010-01-22 16:07:46 -0800479 }
480
481 /**
482 * Notify our observers of an interface removal.
483 */
484 private void notifyInterfaceRemoved(String iface) {
Jeff Sharkey89b8a212011-10-11 11:58:11 -0700485 // netd already clears out quota and alerts for removed ifaces; update
486 // our sanity-checking state.
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700487 mActiveAlerts.remove(iface);
488 mActiveQuotas.remove(iface);
Jeff Sharkey89b8a212011-10-11 11:58:11 -0700489
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900490 invokeForAllObservers(o -> o.interfaceRemoved(iface));
San Mehat4d02d002010-01-22 16:07:46 -0800491 }
492
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700493 /**
JP Abgrall12b933d2011-07-14 18:09:22 -0700494 * Notify our observers of a limit reached.
495 */
496 private void notifyLimitReached(String limitName, String iface) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900497 invokeForAllObservers(o -> o.limitReached(limitName, iface));
JP Abgrall12b933d2011-07-14 18:09:22 -0700498 }
499
500 /**
Haoyu Baidb3c8672012-06-20 14:29:57 -0700501 * Notify our observers of a change in the data activity state of the interface
502 */
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700503 private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos,
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700504 int uid, boolean fromRadio) {
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700505 final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
506 if (isMobile) {
507 if (!fromRadio) {
508 if (mMobileActivityFromRadio) {
509 // If this call is not coming from a report from the radio itself, but we
510 // have previously received reports from the radio, then we will take the
511 // power state to just be whatever the radio last reported.
512 powerState = mLastPowerStateFromRadio;
513 }
514 } else {
515 mMobileActivityFromRadio = true;
516 }
517 if (mLastPowerStateFromRadio != powerState) {
518 mLastPowerStateFromRadio = powerState;
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700519 try {
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700520 getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700521 } catch (RemoteException e) {
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700522 }
Haoyu Baidb3c8672012-06-20 14:29:57 -0700523 }
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700524 }
525
Adam Lesinskie08af192015-03-25 16:42:59 -0700526 if (ConnectivityManager.isNetworkTypeWifi(type)) {
527 if (mLastPowerStateFromWifi != powerState) {
528 mLastPowerStateFromWifi = powerState;
529 try {
Adam Lesinski5f056f62016-07-14 16:56:08 -0700530 getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
Adam Lesinskie08af192015-03-25 16:42:59 -0700531 } catch (RemoteException e) {
532 }
533 }
534 }
535
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700536 boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
537 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
538
539 if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
540 // Report the change in data activity. We don't do this if this is a change
541 // on the mobile network, that is not coming from the radio itself, and we
542 // have previously seen change reports from the radio. In that case only
543 // the radio is the authority for the current state.
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900544 final boolean active = isActive;
545 invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
546 Integer.toString(type), active, tsNanos));
Haoyu Baidb3c8672012-06-20 14:29:57 -0700547 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800548
549 boolean report = false;
550 synchronized (mIdleTimerLock) {
551 if (mActiveIdleTimers.isEmpty()) {
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700552 // If there are no idle timers, we are not monitoring activity, so we
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800553 // are always considered active.
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700554 isActive = true;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800555 }
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700556 if (mNetworkActive != isActive) {
557 mNetworkActive = isActive;
558 report = isActive;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800559 }
560 }
561 if (report) {
562 reportNetworkActive();
563 }
Haoyu Baidb3c8672012-06-20 14:29:57 -0700564 }
565
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900566 @Override
567 public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
568 mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
569 Preconditions.checkNotNull(provider);
570 synchronized(mTetheringStatsProviders) {
571 mTetheringStatsProviders.put(provider, name);
572 }
573 }
574
575 @Override
576 public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
577 mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
578 synchronized(mTetheringStatsProviders) {
579 mTetheringStatsProviders.remove(provider);
580 }
581 }
582
Lorenzo Colittid66cf562017-08-15 19:25:51 +0900583 @Override
584 public void tetherLimitReached(ITetheringStatsProvider provider) {
585 mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
586 synchronized(mTetheringStatsProviders) {
587 if (!mTetheringStatsProviders.containsKey(provider)) {
588 return;
589 }
590 // No current code examines the interface parameter in a global alert. Just pass null.
591 notifyLimitReached(LIMIT_GLOBAL_ALERT, null);
592 }
593 }
594
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900595 // Sync the state of the given chain with the native daemon.
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700596 private void syncFirewallChainLocked(int chain, String name) {
597 SparseIntArray rules;
598 synchronized (mRulesLock) {
599 final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900600 // Make a copy of the current rules, and then clear them. This is because
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700601 // setFirewallUidRuleInternal only pushes down rules to the native daemon if they
602 // are different from the current rules stored in the mUidFirewall*Rules array for
603 // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal
604 // will do nothing.
605 rules = uidFirewallRules.clone();
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900606 uidFirewallRules.clear();
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700607 }
608 if (rules.size() > 0) {
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900609 // Now push the rules. setFirewallUidRuleInternal will push each of these down to the
610 // native daemon, and also add them to the mUidFirewall*Rules array for the specified
611 // chain.
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700612 if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall "
613 + name + "UID rules");
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900614 for (int i = 0; i < rules.size(); i++) {
Felipe Lemea701cad2016-05-12 09:58:14 -0700615 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i));
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900616 }
617 }
618 }
619
bohu07cc3bb2016-05-03 15:58:01 -0700620 private void connectNativeNetdService() {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900621 mNetdService = mServices.getNetd();
bohu07cc3bb2016-05-03 15:58:01 -0700622 }
623
624 /**
625 * Prepare native daemon once connected, enabling modules and pushing any
626 * existing in-memory rules.
627 */
628 private void prepareNativeDaemon() {
Lorenzo Colitti58967ba2016-02-02 17:21:21 +0900629
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700630 mBandwidthControlEnabled = false;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700631
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700632 // only enable bandwidth control when support exists
633 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800634
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700635 // push any existing quota or UID rules
636 synchronized (mQuotaLock) {
Felipe Leme65be3022016-03-22 14:53:13 -0700637
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900638 if (hasKernelSupport) {
639 Slog.d(TAG, "enabling bandwidth control");
640 try {
641 mConnector.execute("bandwidth", "enable");
642 mBandwidthControlEnabled = true;
643 } catch (NativeDaemonConnectorException e) {
644 Log.wtf(TAG, "problem enabling bandwidth controls", e);
645 }
646 } else {
647 Slog.i(TAG, "not enabling bandwidth control");
648 }
649
650 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
651
652 try {
653 mConnector.execute("strict", "enable");
654 mStrictEnabled = true;
655 } catch (NativeDaemonConnectorException e) {
656 Log.wtf(TAG, "Failed strict enable", e);
657 }
658
Felipe Leme65be3022016-03-22 14:53:13 -0700659 setDataSaverModeEnabled(mDataSaverMode);
660
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700661 int size = mActiveQuotas.size();
662 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800663 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700664 final HashMap<String, Long> activeQuotas = mActiveQuotas;
665 mActiveQuotas = Maps.newHashMap();
666 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
667 setInterfaceQuota(entry.getKey(), entry.getValue());
668 }
669 }
670
671 size = mActiveAlerts.size();
672 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800673 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700674 final HashMap<String, Long> activeAlerts = mActiveAlerts;
675 mActiveAlerts = Maps.newHashMap();
676 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
677 setInterfaceAlert(entry.getKey(), entry.getValue());
678 }
679 }
680
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700681 SparseBooleanArray uidRejectOnQuota = null;
682 SparseBooleanArray uidAcceptOnQuota = null;
683 synchronized (mRulesLock) {
684 size = mUidRejectOnMetered.size();
685 if (size > 0) {
686 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
687 uidRejectOnQuota = mUidRejectOnMetered;
688 mUidRejectOnMetered = new SparseBooleanArray();
689 }
690
691 size = mUidAllowOnMetered.size();
692 if (size > 0) {
693 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
694 uidAcceptOnQuota = mUidAllowOnMetered;
695 mUidAllowOnMetered = new SparseBooleanArray();
696 }
697 }
698 if (uidRejectOnQuota != null) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700699 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
Felipe Leme65be3022016-03-22 14:53:13 -0700700 setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
701 uidRejectOnQuota.valueAt(i));
702 }
703 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700704 if (uidAcceptOnQuota != null) {
Felipe Leme65be3022016-03-22 14:53:13 -0700705 for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
706 setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
707 uidAcceptOnQuota.valueAt(i));
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700708 }
709 }
Jeff Sharkey605eb792014-11-04 13:34:06 -0800710
711 size = mUidCleartextPolicy.size();
712 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800713 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
Jeff Sharkey605eb792014-11-04 13:34:06 -0800714 final SparseIntArray local = mUidCleartextPolicy;
715 mUidCleartextPolicy = new SparseIntArray();
716 for (int i = 0; i < local.size(); i++) {
717 setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
718 }
719 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700720
Robin Leec3736bc2017-03-10 16:19:54 +0000721 setFirewallEnabled(mFirewallEnabled);
Amith Yamasani15e472352015-04-24 19:06:07 -0700722
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700723 syncFirewallChainLocked(FIREWALL_CHAIN_NONE, "");
724 syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
725 syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
726 syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700727
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700728 final int[] chains =
729 {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
730 for (int chain : chains) {
731 if (getFirewallChainState(chain)) {
732 setFirewallChainEnabled(chain, true);
733 }
Felipe Leme011b98f2016-02-10 17:28:31 -0800734 }
Amith Yamasani15e472352015-04-24 19:06:07 -0700735 }
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900736
737 if (mBandwidthControlEnabled) {
738 try {
739 getBatteryStats().noteNetworkStatsEnabled();
740 } catch (RemoteException e) {
741 }
742 }
743
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700744 }
San Mehat4d02d002010-01-22 16:07:46 -0800745
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900746 /**
747 * Notify our observers of a new or updated interface address.
748 */
Lorenzo Colitti64483942013-11-15 18:43:52 +0900749 private void notifyAddressUpdated(String iface, LinkAddress address) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900750 invokeForAllObservers(o -> o.addressUpdated(iface, address));
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900751 }
752
753 /**
754 * Notify our observers of a deleted interface address.
755 */
Lorenzo Colitti64483942013-11-15 18:43:52 +0900756 private void notifyAddressRemoved(String iface, LinkAddress address) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900757 invokeForAllObservers(o -> o.addressRemoved(iface, address));
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900758 }
759
Lorenzo Colitti5ae4a532013-10-31 11:59:46 +0900760 /**
761 * Notify our observers of DNS server information received.
762 */
763 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900764 invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
Lorenzo Colitti5ae4a532013-10-31 11:59:46 +0900765 }
766
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +0900767 /**
768 * Notify our observers of a route change.
769 */
770 private void notifyRouteChange(String action, RouteInfo route) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900771 if (action.equals("updated")) {
772 invokeForAllObservers(o -> o.routeUpdated(route));
773 } else {
774 invokeForAllObservers(o -> o.routeRemoved(route));
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +0900775 }
776 }
777
San Mehat873f2142010-01-14 10:25:07 -0800778 //
779 // Netd Callback handling
780 //
781
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700782 private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
783 @Override
San Mehat873f2142010-01-14 10:25:07 -0800784 public void onDaemonConnected() {
Felipe Leme65be3022016-03-22 14:53:13 -0700785 Slog.i(TAG, "onDaemonConnected()");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700786 // event is dispatched from internal NDC thread, so we prepare the
787 // daemon back on main thread.
788 if (mConnectedSignal != null) {
bohu07cc3bb2016-05-03 15:58:01 -0700789 // The system is booting and we're connecting to netd for the first time.
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700790 mConnectedSignal.countDown();
791 mConnectedSignal = null;
792 } else {
bohu07cc3bb2016-05-03 15:58:01 -0700793 // We're reconnecting to netd after the socket connection
794 // was interrupted (e.g., if it crashed).
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700795 mFgHandler.post(new Runnable() {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700796 @Override
797 public void run() {
bohu07cc3bb2016-05-03 15:58:01 -0700798 connectNativeNetdService();
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700799 prepareNativeDaemon();
800 }
801 });
802 }
San Mehat873f2142010-01-14 10:25:07 -0800803 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700804
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700805 @Override
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800806 public boolean onCheckHoldWakeLock(int code) {
807 return code == NetdResponseCode.InterfaceClassActivity;
808 }
809
810 @Override
San Mehat873f2142010-01-14 10:25:07 -0800811 public boolean onEvent(int code, String raw, String[] cooked) {
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900812 String errorMessage = String.format("Invalid event from daemon (%s)", raw);
JP Abgrall12b933d2011-07-14 18:09:22 -0700813 switch (code) {
814 case NetdResponseCode.InterfaceChange:
815 /*
816 * a network interface change occured
817 * Format: "NNN Iface added <name>"
818 * "NNN Iface removed <name>"
819 * "NNN Iface changed <name> <up/down>"
820 * "NNN Iface linkstatus <name> <up/down>"
821 */
822 if (cooked.length < 4 || !cooked[1].equals("Iface")) {
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900823 throw new IllegalStateException(errorMessage);
JP Abgrall12b933d2011-07-14 18:09:22 -0700824 }
825 if (cooked[2].equals("added")) {
826 notifyInterfaceAdded(cooked[3]);
827 return true;
828 } else if (cooked[2].equals("removed")) {
829 notifyInterfaceRemoved(cooked[3]);
830 return true;
831 } else if (cooked[2].equals("changed") && cooked.length == 5) {
832 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
833 return true;
834 } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
835 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
836 return true;
837 }
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900838 throw new IllegalStateException(errorMessage);
JP Abgrall12b933d2011-07-14 18:09:22 -0700839 // break;
840 case NetdResponseCode.BandwidthControl:
841 /*
842 * Bandwidth control needs some attention
843 * Format: "NNN limit alert <alertName> <ifaceName>"
844 */
845 if (cooked.length < 5 || !cooked[1].equals("limit")) {
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900846 throw new IllegalStateException(errorMessage);
JP Abgrall12b933d2011-07-14 18:09:22 -0700847 }
848 if (cooked[2].equals("alert")) {
849 notifyLimitReached(cooked[3], cooked[4]);
850 return true;
851 }
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900852 throw new IllegalStateException(errorMessage);
JP Abgrall12b933d2011-07-14 18:09:22 -0700853 // break;
Haoyu Baidb3c8672012-06-20 14:29:57 -0700854 case NetdResponseCode.InterfaceClassActivity:
855 /*
856 * An network interface class state changed (active/idle)
857 * Format: "NNN IfaceClass <active/idle> <label>"
858 */
859 if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900860 throw new IllegalStateException(errorMessage);
Haoyu Baidb3c8672012-06-20 14:29:57 -0700861 }
Ashish Sharma0535a9f2014-03-12 18:42:23 -0700862 long timestampNanos = 0;
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700863 int processUid = -1;
864 if (cooked.length >= 5) {
Ashish Sharma0535a9f2014-03-12 18:42:23 -0700865 try {
866 timestampNanos = Long.parseLong(cooked[4]);
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700867 if (cooked.length == 6) {
868 processUid = Integer.parseInt(cooked[5]);
869 }
Ashish Sharma0535a9f2014-03-12 18:42:23 -0700870 } catch(NumberFormatException ne) {}
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700871 } else {
872 timestampNanos = SystemClock.elapsedRealtimeNanos();
Ashish Sharma0535a9f2014-03-12 18:42:23 -0700873 }
Haoyu Baidb3c8672012-06-20 14:29:57 -0700874 boolean isActive = cooked[2].equals("active");
Ashish Sharma0535a9f2014-03-12 18:42:23 -0700875 notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700876 isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700877 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
878 timestampNanos, processUid, false);
Haoyu Baidb3c8672012-06-20 14:29:57 -0700879 return true;
880 // break;
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900881 case NetdResponseCode.InterfaceAddressChange:
882 /*
883 * A network address change occurred
884 * Format: "NNN Address updated <addr> <iface> <flags> <scope>"
885 * "NNN Address removed <addr> <iface> <flags> <scope>"
886 */
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900887 if (cooked.length < 7 || !cooked[1].equals("Address")) {
888 throw new IllegalStateException(errorMessage);
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900889 }
890
Lorenzo Colitti64483942013-11-15 18:43:52 +0900891 String iface = cooked[4];
Lorenzo Colitti5ad421a2013-11-17 15:05:02 +0900892 LinkAddress address;
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900893 try {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900894 int flags = Integer.parseInt(cooked[5]);
895 int scope = Integer.parseInt(cooked[6]);
896 address = new LinkAddress(cooked[3], flags, scope);
Lorenzo Colitti5ad421a2013-11-17 15:05:02 +0900897 } catch(NumberFormatException e) { // Non-numeric lifetime or scope.
898 throw new IllegalStateException(errorMessage, e);
Lorenzo Colitti64483942013-11-15 18:43:52 +0900899 } catch(IllegalArgumentException e) { // Malformed/invalid IP address.
Lorenzo Colitti5ad421a2013-11-17 15:05:02 +0900900 throw new IllegalStateException(errorMessage, e);
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900901 }
902
903 if (cooked[2].equals("updated")) {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900904 notifyAddressUpdated(iface, address);
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900905 } else {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900906 notifyAddressRemoved(iface, address);
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900907 }
908 return true;
909 // break;
Lorenzo Colitti5ae4a532013-10-31 11:59:46 +0900910 case NetdResponseCode.InterfaceDnsServerInfo:
911 /*
912 * Information about available DNS servers has been received.
913 * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>"
914 */
915 long lifetime; // Actually a 32-bit unsigned integer.
916
917 if (cooked.length == 6 &&
918 cooked[1].equals("DnsInfo") &&
919 cooked[2].equals("servers")) {
920 try {
921 lifetime = Long.parseLong(cooked[4]);
922 } catch (NumberFormatException e) {
923 throw new IllegalStateException(errorMessage);
924 }
925 String[] servers = cooked[5].split(",");
926 notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
927 }
928 return true;
929 // break;
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +0900930 case NetdResponseCode.RouteChange:
931 /*
932 * A route has been updated or removed.
933 * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]"
934 */
935 if (!cooked[1].equals("Route") || cooked.length < 6) {
936 throw new IllegalStateException(errorMessage);
937 }
938
939 String via = null;
940 String dev = null;
941 boolean valid = true;
942 for (int i = 4; (i + 1) < cooked.length && valid; i += 2) {
943 if (cooked[i].equals("dev")) {
944 if (dev == null) {
945 dev = cooked[i+1];
946 } else {
947 valid = false; // Duplicate interface.
948 }
949 } else if (cooked[i].equals("via")) {
950 if (via == null) {
951 via = cooked[i+1];
952 } else {
953 valid = false; // Duplicate gateway.
954 }
955 } else {
956 valid = false; // Unknown syntax.
957 }
958 }
959 if (valid) {
960 try {
961 // InetAddress.parseNumericAddress(null) inexplicably returns ::1.
962 InetAddress gateway = null;
963 if (via != null) gateway = InetAddress.parseNumericAddress(via);
964 RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
965 notifyRouteChange(cooked[2], route);
966 return true;
967 } catch (IllegalArgumentException e) {}
968 }
969 throw new IllegalStateException(errorMessage);
970 // break;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800971 case NetdResponseCode.StrictCleartext:
972 final int uid = Integer.parseInt(cooked[1]);
973 final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]);
974 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800975 ActivityManager.getService().notifyCleartextNetwork(uid, firstPacket);
Jeff Sharkey605eb792014-11-04 13:34:06 -0800976 } catch (RemoteException ignored) {
977 }
978 break;
JP Abgrall12b933d2011-07-14 18:09:22 -0700979 default: break;
Robert Greenwalte3253922010-02-18 09:23:25 -0800980 }
981 return false;
San Mehat873f2142010-01-14 10:25:07 -0800982 }
983 }
984
San Mehated4fc8a2010-01-22 12:28:36 -0800985
San Mehat873f2142010-01-14 10:25:07 -0800986 //
987 // INetworkManagementService members
988 //
Erik Kline4e37b702016-07-05 11:34:21 +0900989 @Override
990 public INetd getNetdService() throws RemoteException {
991 final CountDownLatch connectedSignal = mConnectedSignal;
992 if (connectedSignal != null) {
993 try {
994 connectedSignal.await();
995 } catch (InterruptedException ignored) {}
996 }
997
998 return mNetdService;
999 }
San Mehat873f2142010-01-14 10:25:07 -08001000
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001001 @Override
1002 public String[] listInterfaces() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001003 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001004 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001005 return NativeDaemonEvent.filterMessageList(
1006 mConnector.executeForList("interface", "list"), InterfaceListResult);
Kenny Roota80ce062010-06-01 13:23:53 -07001007 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001008 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001009 }
San Mehated4fc8a2010-01-22 12:28:36 -08001010 }
1011
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001012 @Override
1013 public InterfaceConfiguration getInterfaceConfig(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001014 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001015
1016 final NativeDaemonEvent event;
Kenny Roota80ce062010-06-01 13:23:53 -07001017 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001018 event = mConnector.execute("interface", "getcfg", iface);
Kenny Roota80ce062010-06-01 13:23:53 -07001019 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001020 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001021 }
San Mehated4fc8a2010-01-22 12:28:36 -08001022
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001023 event.checkCode(InterfaceGetCfgResult);
1024
1025 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3
1026 final StringTokenizer st = new StringTokenizer(event.getMessage());
San Mehated4fc8a2010-01-22 12:28:36 -08001027
Kenny Roota80ce062010-06-01 13:23:53 -07001028 InterfaceConfiguration cfg;
San Mehated4fc8a2010-01-22 12:28:36 -08001029 try {
Kenny Roota80ce062010-06-01 13:23:53 -07001030 cfg = new InterfaceConfiguration();
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001031 cfg.setHardwareAddress(st.nextToken(" "));
Robert Greenwalted126402011-01-28 15:34:55 -08001032 InetAddress addr = null;
Robert Greenwalt2d2afd12011-02-01 15:30:46 -08001033 int prefixLength = 0;
Kenny Roota80ce062010-06-01 13:23:53 -07001034 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001035 addr = NetworkUtils.numericToInetAddress(st.nextToken());
Robert Greenwalte5903732011-02-22 16:00:42 -08001036 } catch (IllegalArgumentException iae) {
1037 Slog.e(TAG, "Failed to parse ipaddr", iae);
Kenny Roota80ce062010-06-01 13:23:53 -07001038 }
1039
1040 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001041 prefixLength = Integer.parseInt(st.nextToken());
Robert Greenwalt2d2afd12011-02-01 15:30:46 -08001042 } catch (NumberFormatException nfe) {
1043 Slog.e(TAG, "Failed to parse prefixLength", nfe);
Kenny Roota80ce062010-06-01 13:23:53 -07001044 }
Robert Greenwalt04808c22010-12-13 17:01:41 -08001045
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001046 cfg.setLinkAddress(new LinkAddress(addr, prefixLength));
1047 while (st.hasMoreTokens()) {
1048 cfg.setFlag(st.nextToken());
1049 }
Kenny Roota80ce062010-06-01 13:23:53 -07001050 } catch (NoSuchElementException nsee) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001051 throw new IllegalStateException("Invalid response from daemon: " + event);
San Mehated4fc8a2010-01-22 12:28:36 -08001052 }
San Mehated4fc8a2010-01-22 12:28:36 -08001053 return cfg;
1054 }
1055
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001056 @Override
1057 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001058 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001059 LinkAddress linkAddr = cfg.getLinkAddress();
Robert Greenwalt2d2afd12011-02-01 15:30:46 -08001060 if (linkAddr == null || linkAddr.getAddress() == null) {
1061 throw new IllegalStateException("Null LinkAddress given");
Robert Greenwalted126402011-01-28 15:34:55 -08001062 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001063
1064 final Command cmd = new Command("interface", "setcfg", iface,
Robert Greenwalt2d2afd12011-02-01 15:30:46 -08001065 linkAddr.getAddress().getHostAddress(),
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +09001066 linkAddr.getPrefixLength());
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001067 for (String flag : cfg.getFlags()) {
1068 cmd.appendArg(flag);
1069 }
1070
Kenny Roota80ce062010-06-01 13:23:53 -07001071 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001072 mConnector.execute(cmd);
Kenny Roota80ce062010-06-01 13:23:53 -07001073 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001074 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001075 }
San Mehat873f2142010-01-14 10:25:07 -08001076 }
1077
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001078 @Override
1079 public void setInterfaceDown(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001080 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001081 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001082 ifcg.setInterfaceDown();
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001083 setInterfaceConfig(iface, ifcg);
Irfan Sheriff7244c972011-08-05 20:40:45 -07001084 }
1085
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001086 @Override
1087 public void setInterfaceUp(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001088 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001089 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001090 ifcg.setInterfaceUp();
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001091 setInterfaceConfig(iface, ifcg);
Irfan Sheriff7244c972011-08-05 20:40:45 -07001092 }
1093
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001094 @Override
1095 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001096 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Irfan Sheriff73293612011-09-14 12:31:56 -07001097 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001098 mConnector.execute(
1099 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable");
Irfan Sheriff73293612011-09-14 12:31:56 -07001100 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001101 throw e.rethrowAsParcelableException();
Irfan Sheriff73293612011-09-14 12:31:56 -07001102 }
1103 }
1104
Irfan Sherifff5600612011-06-16 10:26:28 -07001105 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
1106 IPv6 addresses on interface down, but we need to do full clean up here */
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001107 @Override
1108 public void clearInterfaceAddresses(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001109 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Irfan Sherifff5600612011-06-16 10:26:28 -07001110 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001111 mConnector.execute("interface", "clearaddrs", iface);
Irfan Sherifff5600612011-06-16 10:26:28 -07001112 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001113 throw e.rethrowAsParcelableException();
Irfan Sherifff5600612011-06-16 10:26:28 -07001114 }
1115 }
1116
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001117 @Override
1118 public void enableIpv6(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001119 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
repo sync7960d9f2011-09-29 12:40:02 -07001120 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001121 mConnector.execute("interface", "ipv6", iface, "enable");
repo sync7960d9f2011-09-29 12:40:02 -07001122 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001123 throw e.rethrowAsParcelableException();
repo sync7960d9f2011-09-29 12:40:02 -07001124 }
1125 }
1126
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001127 @Override
Joel Scherpelz2db10742017-06-07 15:38:38 +09001128 public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
1129 try {
1130 mNetdService.setIPv6AddrGenMode(iface, mode);
1131 } catch (RemoteException e) {
1132 throw e.rethrowAsRuntimeException();
1133 }
1134 }
1135
1136 @Override
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001137 public void disableIpv6(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001138 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
repo sync7960d9f2011-09-29 12:40:02 -07001139 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001140 mConnector.execute("interface", "ipv6", iface, "disable");
repo sync7960d9f2011-09-29 12:40:02 -07001141 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001142 throw e.rethrowAsParcelableException();
repo sync7960d9f2011-09-29 12:40:02 -07001143 }
1144 }
1145
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001146 @Override
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -07001147 public void addRoute(int netId, RouteInfo route) {
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07001148 modifyRoute("add", "" + netId, route);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -07001149 }
1150
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001151 @Override
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -07001152 public void removeRoute(int netId, RouteInfo route) {
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07001153 modifyRoute("remove", "" + netId, route);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -07001154 }
1155
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07001156 private void modifyRoute(String action, String netId, RouteInfo route) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001157 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001158
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -07001159 final Command cmd = new Command("network", "route", action, netId);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001160
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -07001161 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -07001162 cmd.appendArg(route.getInterface());
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +09001163 cmd.appendArg(route.getDestination().toString());
1164
1165 switch (route.getType()) {
1166 case RouteInfo.RTN_UNICAST:
1167 if (route.hasGateway()) {
1168 cmd.appendArg(route.getGateway().getHostAddress());
1169 }
1170 break;
1171 case RouteInfo.RTN_UNREACHABLE:
1172 cmd.appendArg("unreachable");
1173 break;
1174 case RouteInfo.RTN_THROW:
1175 cmd.appendArg("throw");
1176 break;
Sreeram Ramachandran1fbcb272014-05-22 16:30:48 -07001177 }
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -07001178
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001179 try {
1180 mConnector.execute(cmd);
1181 } catch (NativeDaemonConnectorException e) {
1182 throw e.rethrowAsParcelableException();
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -07001183 }
1184 }
1185
1186 private ArrayList<String> readRouteList(String filename) {
1187 FileInputStream fstream = null;
Christopher Wiley212b95f2016-08-02 11:38:57 -07001188 ArrayList<String> list = new ArrayList<>();
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -07001189
1190 try {
1191 fstream = new FileInputStream(filename);
1192 DataInputStream in = new DataInputStream(fstream);
1193 BufferedReader br = new BufferedReader(new InputStreamReader(in));
1194 String s;
1195
1196 // throw away the title line
1197
1198 while (((s = br.readLine()) != null) && (s.length() != 0)) {
1199 list.add(s);
1200 }
1201 } catch (IOException ex) {
1202 // return current list, possibly empty
1203 } finally {
1204 if (fstream != null) {
1205 try {
1206 fstream.close();
1207 } catch (IOException ex) {}
1208 }
1209 }
1210
1211 return list;
1212 }
1213
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001214 @Override
sy.yun9d9b74a2013-09-02 05:24:09 +09001215 public void setMtu(String iface, int mtu) {
1216 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1217
1218 final NativeDaemonEvent event;
1219 try {
1220 event = mConnector.execute("interface", "setmtu", iface, mtu);
1221 } catch (NativeDaemonConnectorException e) {
1222 throw e.rethrowAsParcelableException();
1223 }
1224 }
1225
1226 @Override
San Mehat873f2142010-01-14 10:25:07 -08001227 public void shutdown() {
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001228 // TODO: remove from aidl if nobody calls externally
1229 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
San Mehat873f2142010-01-14 10:25:07 -08001230
Felipe Leme03e689d2016-03-02 16:17:38 -08001231 Slog.i(TAG, "Shutting down");
San Mehat873f2142010-01-14 10:25:07 -08001232 }
1233
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001234 @Override
San Mehat873f2142010-01-14 10:25:07 -08001235 public boolean getIpForwardingEnabled() throws IllegalStateException{
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001236 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat873f2142010-01-14 10:25:07 -08001237
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001238 final NativeDaemonEvent event;
Kenny Roota80ce062010-06-01 13:23:53 -07001239 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001240 event = mConnector.execute("ipfwd", "status");
Kenny Roota80ce062010-06-01 13:23:53 -07001241 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001242 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001243 }
San Mehat873f2142010-01-14 10:25:07 -08001244
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001245 // 211 Forwarding enabled
1246 event.checkCode(IpFwdStatusResult);
1247 return event.getMessage().endsWith("enabled");
San Mehat873f2142010-01-14 10:25:07 -08001248 }
1249
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001250 @Override
1251 public void setIpForwardingEnabled(boolean enable) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001252 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001253 try {
Nilesh Poddarf3d4a582015-02-24 12:11:11 -08001254 mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering");
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001255 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001256 throw e.rethrowAsParcelableException();
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001257 }
San Mehat873f2142010-01-14 10:25:07 -08001258 }
1259
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001260 @Override
1261 public void startTethering(String[] dhcpRange) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001262 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -07001263 // cmd is "tether start first_start first_stop second_start second_stop ..."
1264 // an odd number of addrs will fail
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001265
1266 final Command cmd = new Command("tether", "start");
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -07001267 for (String d : dhcpRange) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001268 cmd.appendArg(d);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -07001269 }
Kenny Roota80ce062010-06-01 13:23:53 -07001270
1271 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001272 mConnector.execute(cmd);
Kenny Roota80ce062010-06-01 13:23:53 -07001273 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001274 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001275 }
San Mehat873f2142010-01-14 10:25:07 -08001276 }
1277
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001278 @Override
1279 public void stopTethering() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001280 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001281 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001282 mConnector.execute("tether", "stop");
Kenny Roota80ce062010-06-01 13:23:53 -07001283 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001284 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001285 }
San Mehat873f2142010-01-14 10:25:07 -08001286 }
1287
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001288 @Override
1289 public boolean isTetheringStarted() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001290 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat873f2142010-01-14 10:25:07 -08001291
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001292 final NativeDaemonEvent event;
Kenny Roota80ce062010-06-01 13:23:53 -07001293 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001294 event = mConnector.execute("tether", "status");
Kenny Roota80ce062010-06-01 13:23:53 -07001295 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001296 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001297 }
San Mehat873f2142010-01-14 10:25:07 -08001298
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001299 // 210 Tethering services started
1300 event.checkCode(TetherStatusResult);
1301 return event.getMessage().endsWith("started");
San Mehat873f2142010-01-14 10:25:07 -08001302 }
Matthew Xiefe19f122012-07-12 16:03:32 -07001303
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001304 @Override
1305 public void tetherInterface(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001306 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001307 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001308 mConnector.execute("tether", "interface", "add", iface);
Kenny Roota80ce062010-06-01 13:23:53 -07001309 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001310 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001311 }
Christopher Wiley212b95f2016-08-02 11:38:57 -07001312 List<RouteInfo> routes = new ArrayList<>();
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07001313 // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
1314 // suitable to use as a route destination.
1315 routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
1316 addInterfaceToLocalNetwork(iface, routes);
San Mehat873f2142010-01-14 10:25:07 -08001317 }
1318
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001319 @Override
San Mehat873f2142010-01-14 10:25:07 -08001320 public void untetherInterface(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001321 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001322 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001323 mConnector.execute("tether", "interface", "remove", iface);
Kenny Roota80ce062010-06-01 13:23:53 -07001324 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001325 throw e.rethrowAsParcelableException();
Erik Kline1f4278a2016-08-16 16:46:33 +09001326 } finally {
1327 removeInterfaceFromLocalNetwork(iface);
Kenny Roota80ce062010-06-01 13:23:53 -07001328 }
San Mehat873f2142010-01-14 10:25:07 -08001329 }
1330
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001331 @Override
1332 public String[] listTetheredInterfaces() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001333 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001334 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001335 return NativeDaemonEvent.filterMessageList(
1336 mConnector.executeForList("tether", "interface", "list"),
1337 TetherInterfaceListResult);
Kenny Roota80ce062010-06-01 13:23:53 -07001338 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001339 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001340 }
San Mehat873f2142010-01-14 10:25:07 -08001341 }
1342
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001343 @Override
Lorenzo Colittib57edc52014-08-22 17:10:50 -07001344 public void setDnsForwarders(Network network, String[] dns) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001345 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001346
Lorenzo Colittib57edc52014-08-22 17:10:50 -07001347 int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
1348 final Command cmd = new Command("tether", "dns", "set", netId);
1349
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001350 for (String s : dns) {
1351 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
1352 }
1353
San Mehat873f2142010-01-14 10:25:07 -08001354 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001355 mConnector.execute(cmd);
1356 } catch (NativeDaemonConnectorException e) {
1357 throw e.rethrowAsParcelableException();
San Mehat873f2142010-01-14 10:25:07 -08001358 }
1359 }
1360
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001361 @Override
1362 public String[] getDnsForwarders() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001363 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001364 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001365 return NativeDaemonEvent.filterMessageList(
1366 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult);
Kenny Roota80ce062010-06-01 13:23:53 -07001367 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001368 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001369 }
San Mehat873f2142010-01-14 10:25:07 -08001370 }
1371
jiaguo1da35f72014-01-09 16:39:59 +08001372 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
Christopher Wiley212b95f2016-08-02 11:38:57 -07001373 ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
jiaguo1da35f72014-01-09 16:39:59 +08001374 for (InterfaceAddress ia : addresses) {
1375 if (!ia.getAddress().isLinkLocalAddress())
1376 filtered.add(ia);
1377 }
1378 return filtered;
1379 }
1380
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001381 private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
1382 final Command cmd = new Command("ipfwd", add ? "add" : "remove", fromIface, toIface);
1383 try {
1384 mConnector.execute(cmd);
1385 } catch (NativeDaemonConnectorException e) {
1386 throw e.rethrowAsParcelableException();
1387 }
1388 }
1389
1390 @Override
1391 public void startInterfaceForwarding(String fromIface, String toIface) {
1392 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1393 modifyInterfaceForward(true, fromIface, toIface);
1394 }
1395
1396 @Override
1397 public void stopInterfaceForwarding(String fromIface, String toIface) {
1398 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1399 modifyInterfaceForward(false, fromIface, toIface);
1400 }
1401
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001402 private void modifyNat(String action, String internalInterface, String externalInterface)
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001403 throws SocketException {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001404 final Command cmd = new Command("nat", action, internalInterface, externalInterface);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001405
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001406 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName(
1407 internalInterface);
Robert Greenwalte83d1812011-11-21 14:44:39 -08001408 if (internalNetworkInterface == null) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001409 cmd.appendArg("0");
Robert Greenwalte83d1812011-11-21 14:44:39 -08001410 } else {
jiaguo1da35f72014-01-09 16:39:59 +08001411 // Don't touch link-local routes, as link-local addresses aren't routable,
1412 // kernel creates link-local routes on all interfaces automatically
1413 List<InterfaceAddress> interfaceAddresses = excludeLinkLocal(
1414 internalNetworkInterface.getInterfaceAddresses());
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001415 cmd.appendArg(interfaceAddresses.size());
Robert Greenwalte83d1812011-11-21 14:44:39 -08001416 for (InterfaceAddress ia : interfaceAddresses) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001417 InetAddress addr = NetworkUtils.getNetworkPart(
1418 ia.getAddress(), ia.getNetworkPrefixLength());
1419 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength());
Robert Greenwalte83d1812011-11-21 14:44:39 -08001420 }
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001421 }
1422
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001423 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001424 mConnector.execute(cmd);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001425 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001426 throw e.rethrowAsParcelableException();
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001427 }
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001428 }
1429
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001430 @Override
1431 public void enableNat(String internalInterface, String externalInterface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001432 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001433 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001434 modifyNat("enable", internalInterface, externalInterface);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001435 } catch (SocketException e) {
1436 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001437 }
San Mehat873f2142010-01-14 10:25:07 -08001438 }
1439
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001440 @Override
1441 public void disableNat(String internalInterface, String externalInterface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001442 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001443 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001444 modifyNat("disable", internalInterface, externalInterface);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001445 } catch (SocketException e) {
1446 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001447 }
San Mehat873f2142010-01-14 10:25:07 -08001448 }
San Mehat72759df2010-01-19 13:50:37 -08001449
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001450 @Override
1451 public String[] listTtys() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001452 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001453 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001454 return NativeDaemonEvent.filterMessageList(
1455 mConnector.executeForList("list_ttys"), TtyListResult);
Kenny Roota80ce062010-06-01 13:23:53 -07001456 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001457 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001458 }
San Mehat72759df2010-01-19 13:50:37 -08001459 }
1460
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001461 @Override
1462 public void attachPppd(
1463 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001464 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat72759df2010-01-19 13:50:37 -08001465 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001466 mConnector.execute("pppd", "attach", tty,
Robert Greenwalte5903732011-02-22 16:00:42 -08001467 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
1468 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
1469 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001470 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress());
Kenny Roota80ce062010-06-01 13:23:53 -07001471 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001472 throw e.rethrowAsParcelableException();
San Mehat72759df2010-01-19 13:50:37 -08001473 }
1474 }
1475
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001476 @Override
1477 public void detachPppd(String tty) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001478 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001479 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001480 mConnector.execute("pppd", "detach", tty);
Kenny Roota80ce062010-06-01 13:23:53 -07001481 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001482 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001483 }
San Mehat72759df2010-01-19 13:50:37 -08001484 }
Robert Greenwaltce1200d2010-02-18 11:25:54 -08001485
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001486 @Override
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001487 public void addIdleTimer(String iface, int timeout, final int type) {
Haoyu Bai04124232012-06-28 15:26:19 -07001488 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1489
1490 if (DBG) Slog.d(TAG, "Adding idletimer");
1491
1492 synchronized (mIdleTimerLock) {
1493 IdleTimerParams params = mActiveIdleTimers.get(iface);
1494 if (params != null) {
1495 // the interface already has idletimer, update network count
1496 params.networkCount++;
1497 return;
1498 }
1499
1500 try {
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001501 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout),
1502 Integer.toString(type));
Haoyu Bai04124232012-06-28 15:26:19 -07001503 } catch (NativeDaemonConnectorException e) {
1504 throw e.rethrowAsParcelableException();
1505 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001506 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
1507
Dianne Hackborne13c4c02014-02-11 17:18:35 -08001508 // Networks start up.
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001509 if (ConnectivityManager.isNetworkTypeMobile(type)) {
1510 mNetworkActive = false;
1511 }
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07001512 mDaemonHandler.post(new Runnable() {
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001513 @Override public void run() {
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07001514 notifyInterfaceClassActivity(type,
1515 DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -07001516 SystemClock.elapsedRealtimeNanos(), -1, false);
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001517 }
1518 });
Haoyu Bai04124232012-06-28 15:26:19 -07001519 }
1520 }
1521
1522 @Override
1523 public void removeIdleTimer(String iface) {
1524 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1525
1526 if (DBG) Slog.d(TAG, "Removing idletimer");
1527
1528 synchronized (mIdleTimerLock) {
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001529 final IdleTimerParams params = mActiveIdleTimers.get(iface);
Haoyu Bai04124232012-06-28 15:26:19 -07001530 if (params == null || --(params.networkCount) > 0) {
1531 return;
1532 }
1533
1534 try {
1535 mConnector.execute("idletimer", "remove", iface,
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001536 Integer.toString(params.timeout), Integer.toString(params.type));
Haoyu Bai04124232012-06-28 15:26:19 -07001537 } catch (NativeDaemonConnectorException e) {
1538 throw e.rethrowAsParcelableException();
1539 }
1540 mActiveIdleTimers.remove(iface);
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07001541 mDaemonHandler.post(new Runnable() {
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001542 @Override public void run() {
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07001543 notifyInterfaceClassActivity(params.type,
1544 DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -07001545 SystemClock.elapsedRealtimeNanos(), -1, false);
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001546 }
1547 });
Haoyu Bai04124232012-06-28 15:26:19 -07001548 }
1549 }
1550
1551 @Override
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001552 public NetworkStats getNetworkStatsSummaryDev() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001553 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001554 try {
1555 return mStatsFactory.readNetworkStatsSummaryDev();
1556 } catch (IOException e) {
1557 throw new IllegalStateException(e);
1558 }
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001559 }
1560
1561 @Override
1562 public NetworkStats getNetworkStatsSummaryXt() {
1563 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001564 try {
1565 return mStatsFactory.readNetworkStatsSummaryXt();
1566 } catch (IOException e) {
1567 throw new IllegalStateException(e);
1568 }
Jeff Sharkeyae2c1812011-10-04 13:11:40 -07001569 }
1570
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001571 @Override
Jeff Sharkey9a13f362011-04-26 16:25:36 -07001572 public NetworkStats getNetworkStatsDetail() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001573 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001574 try {
Dianne Hackbornd0c5b9a2014-02-21 16:19:05 -08001575 return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001576 } catch (IOException e) {
1577 throw new IllegalStateException(e);
1578 }
San Mehat91cac642010-03-31 14:31:36 -07001579 }
1580
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001581 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001582 public void setInterfaceQuota(String iface, long quotaBytes) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001583 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001584
Jeff Sharkey350083e2011-06-29 10:45:16 -07001585 // silently discard when control disabled
1586 // TODO: eventually migrate to be always enabled
1587 if (!mBandwidthControlEnabled) return;
1588
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001589 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001590 if (mActiveQuotas.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001591 throw new IllegalStateException("iface " + iface + " already has quota");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001592 }
1593
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001594 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001595 // TODO: support quota shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001596 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001597 mActiveQuotas.put(iface, quotaBytes);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001598 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001599 throw e.rethrowAsParcelableException();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001600 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001601
1602 synchronized (mTetheringStatsProviders) {
1603 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1604 try {
1605 provider.setInterfaceQuota(iface, quotaBytes);
1606 } catch (RemoteException e) {
1607 Log.e(TAG, "Problem setting tethering data limit on provider " +
1608 mTetheringStatsProviders.get(provider) + ": " + e);
1609 }
1610 }
1611 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001612 }
1613 }
1614
1615 @Override
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001616 public void removeInterfaceQuota(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001617 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001618
Jeff Sharkey350083e2011-06-29 10:45:16 -07001619 // silently discard when control disabled
1620 // TODO: eventually migrate to be always enabled
1621 if (!mBandwidthControlEnabled) return;
1622
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001623 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001624 if (!mActiveQuotas.containsKey(iface)) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001625 // TODO: eventually consider throwing
1626 return;
1627 }
1628
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001629 mActiveQuotas.remove(iface);
1630 mActiveAlerts.remove(iface);
Jeff Sharkey38ddeaa2011-11-08 13:04:22 -08001631
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001632 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001633 // TODO: support quota shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001634 mConnector.execute("bandwidth", "removeiquota", iface);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001635 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001636 throw e.rethrowAsParcelableException();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001637 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001638
1639 synchronized (mTetheringStatsProviders) {
1640 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1641 try {
1642 provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
1643 } catch (RemoteException e) {
1644 Log.e(TAG, "Problem removing tethering data limit on provider " +
1645 mTetheringStatsProviders.get(provider) + ": " + e);
1646 }
1647 }
1648 }
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001649 }
1650 }
1651
1652 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001653 public void setInterfaceAlert(String iface, long alertBytes) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001654 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001655
1656 // silently discard when control disabled
1657 // TODO: eventually migrate to be always enabled
1658 if (!mBandwidthControlEnabled) return;
1659
1660 // quick sanity check
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001661 if (!mActiveQuotas.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001662 throw new IllegalStateException("setting alert requires existing quota on iface");
1663 }
1664
1665 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001666 if (mActiveAlerts.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001667 throw new IllegalStateException("iface " + iface + " already has alert");
1668 }
1669
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001670 try {
1671 // TODO: support alert shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001672 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001673 mActiveAlerts.put(iface, alertBytes);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001674 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001675 throw e.rethrowAsParcelableException();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001676 }
1677 }
1678 }
1679
1680 @Override
1681 public void removeInterfaceAlert(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001682 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001683
1684 // silently discard when control disabled
1685 // TODO: eventually migrate to be always enabled
1686 if (!mBandwidthControlEnabled) return;
1687
1688 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001689 if (!mActiveAlerts.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001690 // TODO: eventually consider throwing
1691 return;
1692 }
1693
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001694 try {
1695 // TODO: support alert shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001696 mConnector.execute("bandwidth", "removeinterfacealert", iface);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001697 mActiveAlerts.remove(iface);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001698 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001699 throw e.rethrowAsParcelableException();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001700 }
1701 }
1702 }
1703
1704 @Override
1705 public void setGlobalAlert(long alertBytes) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001706 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001707
1708 // silently discard when control disabled
1709 // TODO: eventually migrate to be always enabled
1710 if (!mBandwidthControlEnabled) return;
1711
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001712 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001713 mConnector.execute("bandwidth", "setglobalalert", alertBytes);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001714 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001715 throw e.rethrowAsParcelableException();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001716 }
1717 }
1718
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001719 private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001720 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001721
Jeff Sharkey350083e2011-06-29 10:45:16 -07001722 // silently discard when control disabled
1723 // TODO: eventually migrate to be always enabled
1724 if (!mBandwidthControlEnabled) return;
1725
Felipe Leme65be3022016-03-22 14:53:13 -07001726 final String chain = blacklist ? "naughtyapps" : "niceapps";
1727 final String suffix = enable ? "add" : "remove";
1728
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001729 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001730 boolean oldEnable;
1731 SparseBooleanArray quotaList;
1732 synchronized (mRulesLock) {
1733 quotaList = blacklist ? mUidRejectOnMetered : mUidAllowOnMetered;
1734 oldEnable = quotaList.get(uid, false);
1735 }
Felipe Leme65be3022016-03-22 14:53:13 -07001736 if (oldEnable == enable) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001737 // TODO: eventually consider throwing
1738 return;
1739 }
1740
Felipe Leme29e72ea2016-09-08 13:26:55 -07001741 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001742 try {
Felipe Leme65be3022016-03-22 14:53:13 -07001743 mConnector.execute("bandwidth", suffix + chain, uid);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001744 synchronized (mRulesLock) {
1745 if (enable) {
1746 quotaList.put(uid, true);
1747 } else {
1748 quotaList.delete(uid);
1749 }
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001750 }
1751 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001752 throw e.rethrowAsParcelableException();
Felipe Leme29e72ea2016-09-08 13:26:55 -07001753 } finally {
1754 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001755 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001756 }
1757 }
1758
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001759 @Override
Felipe Leme65be3022016-03-22 14:53:13 -07001760 public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001761 setUidOnMeteredNetworkList(uid, true, enable);
Felipe Leme65be3022016-03-22 14:53:13 -07001762 }
1763
1764 @Override
1765 public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001766 setUidOnMeteredNetworkList(uid, false, enable);
Felipe Leme65be3022016-03-22 14:53:13 -07001767 }
1768
1769 @Override
1770 public boolean setDataSaverModeEnabled(boolean enable) {
1771 if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
1772 synchronized (mQuotaLock) {
1773 if (mDataSaverMode == enable) {
1774 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
1775 return true;
1776 }
Felipe Leme29e72ea2016-09-08 13:26:55 -07001777 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
Felipe Leme65be3022016-03-22 14:53:13 -07001778 try {
1779 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
1780 if (changed) {
1781 mDataSaverMode = enable;
1782 } else {
1783 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
1784 }
1785 return changed;
1786 } catch (RemoteException e) {
1787 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
1788 return false;
Felipe Leme29e72ea2016-09-08 13:26:55 -07001789 } finally {
1790 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
Felipe Leme65be3022016-03-22 14:53:13 -07001791 }
1792 }
1793 }
1794
1795 @Override
Robin Lee17e61832016-05-09 13:46:28 +01001796 public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
1797 throws ServiceSpecificException {
1798 try {
1799 mNetdService.networkRejectNonSecureVpn(add, uidRanges);
1800 } catch (ServiceSpecificException e) {
1801 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1802 + ": netd command failed", e);
1803 throw e;
1804 } catch (RemoteException e) {
1805 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1806 + ": netd command failed", e);
1807 throw e.rethrowAsRuntimeException();
1808 }
1809 }
1810
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001811 private void applyUidCleartextNetworkPolicy(int uid, int policy) {
1812 final String policyString;
1813 switch (policy) {
1814 case StrictMode.NETWORK_POLICY_ACCEPT:
1815 policyString = "accept";
1816 break;
1817 case StrictMode.NETWORK_POLICY_LOG:
1818 policyString = "log";
1819 break;
1820 case StrictMode.NETWORK_POLICY_REJECT:
1821 policyString = "reject";
1822 break;
1823 default:
1824 throw new IllegalArgumentException("Unknown policy " + policy);
1825 }
1826
1827 try {
1828 mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString);
1829 mUidCleartextPolicy.put(uid, policy);
1830 } catch (NativeDaemonConnectorException e) {
1831 throw e.rethrowAsParcelableException();
1832 }
1833 }
1834
Robin Lee17e61832016-05-09 13:46:28 +01001835 @Override
Jeff Sharkey605eb792014-11-04 13:34:06 -08001836 public void setUidCleartextNetworkPolicy(int uid, int policy) {
1837 if (Binder.getCallingUid() != uid) {
1838 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1839 }
1840
1841 synchronized (mQuotaLock) {
1842 final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1843 if (oldPolicy == policy) {
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001844 // This also ensures we won't needlessly apply an ACCEPT policy if we've just
1845 // enabled strict and the underlying iptables rules are empty.
Jeff Sharkey605eb792014-11-04 13:34:06 -08001846 return;
1847 }
1848
1849 if (!mStrictEnabled) {
1850 // Module isn't enabled yet; stash the requested policy away to
1851 // apply later once the daemon is connected.
1852 mUidCleartextPolicy.put(uid, policy);
1853 return;
1854 }
1855
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001856 // netd does not keep state on strict mode policies, and cannot replace a non-accept
1857 // policy without deleting it first. Rather than add state to netd, just always send
1858 // it an accept policy when switching between two non-accept policies.
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001859 // TODO: consider keeping state in netd so we can simplify this code.
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001860 if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT &&
1861 policy != StrictMode.NETWORK_POLICY_ACCEPT) {
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001862 applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001863 }
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001864
1865 applyUidCleartextNetworkPolicy(uid, policy);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001866 }
1867 }
1868
1869 @Override
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001870 public boolean isBandwidthControlEnabled() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001871 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001872 return mBandwidthControlEnabled;
1873 }
1874
1875 @Override
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001876 public NetworkStats getNetworkStatsUidDetail(int uid) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001877 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001878 try {
Dianne Hackbornd0c5b9a2014-02-21 16:19:05 -08001879 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001880 } catch (IOException e) {
1881 throw new IllegalStateException(e);
1882 }
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001883 }
1884
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001885 private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
1886 @Override
Lorenzo Colitti5356a352017-08-17 19:23:08 +09001887 public NetworkStats getTetherStats(int how) {
1888 // We only need to return per-UID stats. Per-device stats are already counted by
1889 // interface counters.
1890 if (how != STATS_PER_UID) {
1891 return new NetworkStats(SystemClock.elapsedRealtime(), 0);
1892 }
1893
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001894 final PersistableBundle bundle;
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001895 try {
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001896 bundle = mNetdService.tetherGetStats();
1897 } catch (RemoteException | ServiceSpecificException e) {
1898 throw new IllegalStateException("problem parsing tethering stats: ", e);
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001899 }
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001900
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001901 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
1902 bundle.size());
1903 final NetworkStats.Entry entry = new NetworkStats.Entry();
1904
1905 for (String iface : bundle.keySet()) {
1906 long[] statsArray = bundle.getLongArray(iface);
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001907 try {
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001908 entry.iface = iface;
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001909 entry.uid = UID_TETHERING;
1910 entry.set = SET_DEFAULT;
1911 entry.tag = TAG_NONE;
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001912 entry.rxBytes = statsArray[INetd.TETHER_STATS_RX_BYTES];
1913 entry.rxPackets = statsArray[INetd.TETHER_STATS_RX_PACKETS];
1914 entry.txBytes = statsArray[INetd.TETHER_STATS_TX_BYTES];
1915 entry.txPackets = statsArray[INetd.TETHER_STATS_TX_PACKETS];
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001916 stats.combineValues(entry);
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001917 } catch (ArrayIndexOutOfBoundsException e) {
1918 throw new IllegalStateException("invalid tethering stats for " + iface, e);
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001919 }
1920 }
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001921
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001922 return stats;
1923 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001924
1925 @Override
1926 public void setInterfaceQuota(String iface, long quotaBytes) {
1927 // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
1928 }
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001929 }
1930
1931 @Override
Lorenzo Colitti5356a352017-08-17 19:23:08 +09001932 public NetworkStats getNetworkStatsTethering(int how) {
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001933 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1934
1935 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1936 synchronized (mTetheringStatsProviders) {
1937 for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
1938 try {
Lorenzo Colitti5356a352017-08-17 19:23:08 +09001939 stats.combineAllValues(provider.getTetherStats(how));
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001940 } catch (RemoteException e) {
1941 Log.e(TAG, "Problem reading tethering stats from " +
1942 mTetheringStatsProviders.get(provider) + ": " + e);
1943 }
1944 }
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001945 }
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001946 return stats;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001947 }
1948
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001949 @Override
Pierre Imai8e48e672016-04-21 13:30:43 +09001950 public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) {
1951 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1952
Erik Kline4d092232017-10-30 15:29:44 +09001953 final ContentResolver cr = mContext.getContentResolver();
Pierre Imai8e48e672016-04-21 13:30:43 +09001954
Erik Kline4d092232017-10-30 15:29:44 +09001955 int sampleValidity = Settings.Global.getInt(cr,
Pierre Imai8e48e672016-04-21 13:30:43 +09001956 Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
1957 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
1958 if (sampleValidity < 0 || sampleValidity > 65535) {
1959 Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" +
1960 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
1961 sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
1962 }
1963
Erik Kline4d092232017-10-30 15:29:44 +09001964 int successThreshold = Settings.Global.getInt(cr,
Pierre Imai8e48e672016-04-21 13:30:43 +09001965 Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
1966 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
1967 if (successThreshold < 0 || successThreshold > 100) {
1968 Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" +
1969 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
1970 successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
1971 }
1972
Erik Kline4d092232017-10-30 15:29:44 +09001973 int minSamples = Settings.Global.getInt(cr,
Pierre Imai8e48e672016-04-21 13:30:43 +09001974 Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
Erik Kline4d092232017-10-30 15:29:44 +09001975 int maxSamples = Settings.Global.getInt(cr,
Pierre Imai8e48e672016-04-21 13:30:43 +09001976 Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
1977 if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) {
1978 Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples +
1979 "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
1980 DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
1981 minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
1982 maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
1983 }
1984
1985 final String[] domainStrs = domains == null ? new String[0] : domains.split(" ");
1986 final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples };
Erik Kline4d092232017-10-30 15:29:44 +09001987 final boolean useTls = shouldUseTls(cr);
1988 // TODO: Populate tlsHostname once it's decided how the hostname's IP
1989 // addresses will be resolved:
1990 //
1991 // [1] network-provided DNS servers are included here with the
1992 // hostname and netd will use the network-provided servers to
1993 // resolve the hostname and fix up its internal structures, or
1994 //
1995 // [2] network-provided DNS servers are included here without the
1996 // hostname, the ConnectivityService layer resolves the given
1997 // hostname, and then reconfigures netd with this information.
1998 //
1999 // In practice, there will always be a need for ConnectivityService or
2000 // the captive portal app to use the network-provided services to make
2001 // some queries. This argues in favor of [1], in concert with another
2002 // mechanism, perhaps setting a high bit in the netid, to indicate
2003 // via existing DNS APIs which set of servers (network-provided or
2004 // non-network-provided private DNS) should be queried.
Ben Schwartz6ec28df2017-10-02 13:08:06 -04002005 final String tlsHostname = "";
2006 final String[] tlsFingerprints = new String[0];
Pierre Imai8e48e672016-04-21 13:30:43 +09002007 try {
Ben Schwartz6ec28df2017-10-02 13:08:06 -04002008 mNetdService.setResolverConfiguration(netId, servers, domainStrs, params,
2009 useTls, tlsHostname, tlsFingerprints);
Pierre Imai8e48e672016-04-21 13:30:43 +09002010 } catch (RemoteException e) {
2011 throw new RuntimeException(e);
2012 }
2013 }
2014
Erik Kline4d092232017-10-30 15:29:44 +09002015 private static boolean shouldUseTls(ContentResolver cr) {
2016 String privateDns = Settings.Global.getString(cr, Settings.Global.PRIVATE_DNS_MODE);
2017 if (TextUtils.isEmpty(privateDns)) {
2018 privateDns = PRIVATE_DNS_DEFAULT_MODE;
2019 }
2020 return privateDns.equals(PRIVATE_DNS_MODE_OPPORTUNISTIC) ||
2021 privateDns.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
2022 }
2023
Pierre Imai8e48e672016-04-21 13:30:43 +09002024 @Override
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002025 public void addVpnUidRanges(int netId, UidRange[] ranges) {
Chad Brubaker3277620a2013-06-12 13:37:30 -07002026 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002027 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2028 argv[0] = "users";
2029 argv[1] = "add";
2030 argv[2] = netId;
2031 int argc = 3;
2032 // Avoid overly long commands by limiting number of UID ranges per command.
2033 for (int i = 0; i < ranges.length; i++) {
2034 argv[argc++] = ranges[i].toString();
2035 if (i == (ranges.length - 1) || argc == argv.length) {
2036 try {
2037 mConnector.execute("network", Arrays.copyOf(argv, argc));
2038 } catch (NativeDaemonConnectorException e) {
2039 throw e.rethrowAsParcelableException();
2040 }
2041 argc = 3;
2042 }
Chad Brubaker3277620a2013-06-12 13:37:30 -07002043 }
2044 }
2045
2046 @Override
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002047 public void removeVpnUidRanges(int netId, UidRange[] ranges) {
Chad Brubaker3277620a2013-06-12 13:37:30 -07002048 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002049 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2050 argv[0] = "users";
2051 argv[1] = "remove";
2052 argv[2] = netId;
2053 int argc = 3;
2054 // Avoid overly long commands by limiting number of UID ranges per command.
2055 for (int i = 0; i < ranges.length; i++) {
2056 argv[argc++] = ranges[i].toString();
2057 if (i == (ranges.length - 1) || argc == argv.length) {
2058 try {
2059 mConnector.execute("network", Arrays.copyOf(argv, argc));
2060 } catch (NativeDaemonConnectorException e) {
2061 throw e.rethrowAsParcelableException();
2062 }
2063 argc = 3;
2064 }
Chad Brubakercca54c42013-06-27 17:41:38 -07002065 }
2066 }
2067
2068 @Override
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002069 public void setFirewallEnabled(boolean enabled) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07002070 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002071 try {
Amith Yamasani15e472352015-04-24 19:06:07 -07002072 mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist");
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002073 mFirewallEnabled = enabled;
2074 } catch (NativeDaemonConnectorException e) {
2075 throw e.rethrowAsParcelableException();
2076 }
2077 }
2078
2079 @Override
2080 public boolean isFirewallEnabled() {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07002081 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002082 return mFirewallEnabled;
2083 }
2084
2085 @Override
Jeff Sharkey2c092982012-08-24 11:44:40 -07002086 public void setFirewallInterfaceRule(String iface, boolean allow) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07002087 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002088 Preconditions.checkState(mFirewallEnabled);
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002089 final String rule = allow ? "allow" : "deny";
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002090 try {
2091 mConnector.execute("firewall", "set_interface_rule", iface, rule);
2092 } catch (NativeDaemonConnectorException e) {
2093 throw e.rethrowAsParcelableException();
2094 }
2095 }
2096
Lorenzo Colitti3fef7232016-04-29 18:00:03 +09002097 private void closeSocketsForFirewallChainLocked(int chain, String chainName) {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002098 // UID ranges to close sockets on.
2099 UidRange[] ranges;
2100 // UID ranges whose sockets we won't touch.
2101 int[] exemptUids;
2102
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002103 int numUids = 0;
2104
2105 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
2106 // Close all sockets on all non-system UIDs...
2107 ranges = new UidRange[] {
2108 // TODO: is there a better way of finding all existing users? If so, we could
2109 // specify their ranges here.
2110 new UidRange(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
2111 };
2112 // ... except for the UIDs that have allow rules.
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002113 synchronized (mRulesLock) {
2114 final SparseIntArray rules = getUidFirewallRulesLR(chain);
2115 exemptUids = new int[rules.size()];
2116 for (int i = 0; i < exemptUids.length; i++) {
2117 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
2118 exemptUids[numUids] = rules.keyAt(i);
2119 numUids++;
2120 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002121 }
2122 }
2123 // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
2124 // But the code does not guarantee this in any way, and at least in one case - if we add
2125 // a UID rule to the firewall, and then disable the firewall - the chains can contain
2126 // the wrong type of rule. In this case, don't close connections that we shouldn't.
2127 //
2128 // TODO: tighten up this code by ensuring we never set the wrong type of rule, and
2129 // fix setFirewallEnabled to grab mQuotaLock and clear rules.
2130 if (numUids != exemptUids.length) {
2131 exemptUids = Arrays.copyOf(exemptUids, numUids);
2132 }
2133 } else {
2134 // Close sockets for every UID that has a deny rule...
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002135 synchronized (mRulesLock) {
2136 final SparseIntArray rules = getUidFirewallRulesLR(chain);
2137 ranges = new UidRange[rules.size()];
2138 for (int i = 0; i < ranges.length; i++) {
2139 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_DENY) {
2140 int uid = rules.keyAt(i);
2141 ranges[numUids] = new UidRange(uid, uid);
2142 numUids++;
2143 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002144 }
2145 }
2146 // As above; usually numUids == ranges.length, but not always.
2147 if (numUids != ranges.length) {
2148 ranges = Arrays.copyOf(ranges, numUids);
2149 }
2150 // ... with no exceptions.
2151 exemptUids = new int[0];
2152 }
2153
2154 try {
2155 mNetdService.socketDestroy(ranges, exemptUids);
2156 } catch(RemoteException | ServiceSpecificException e) {
2157 Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e);
2158 }
2159 }
2160
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002161 @Override
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002162 public void setFirewallChainEnabled(int chain, boolean enable) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07002163 enforceSystemUid();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002164 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002165 synchronized (mRulesLock) {
2166 if (getFirewallChainState(chain) == enable) {
2167 // All is the same, nothing to do. This relies on the fact that netd has child
2168 // chains default detached.
2169 return;
2170 }
2171 setFirewallChainState(chain, enable);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002172 }
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002173
2174 final String operation = enable ? "enable_chain" : "disable_chain";
Lorenzo Colitti3fef7232016-04-29 18:00:03 +09002175 final String chainName;
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002176 switch(chain) {
2177 case FIREWALL_CHAIN_STANDBY:
2178 chainName = FIREWALL_CHAIN_NAME_STANDBY;
2179 break;
2180 case FIREWALL_CHAIN_DOZABLE:
2181 chainName = FIREWALL_CHAIN_NAME_DOZABLE;
2182 break;
2183 case FIREWALL_CHAIN_POWERSAVE:
2184 chainName = FIREWALL_CHAIN_NAME_POWERSAVE;
2185 break;
2186 default:
2187 throw new IllegalArgumentException("Bad child chain: " + chain);
2188 }
2189
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002190 try {
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002191 mConnector.execute("firewall", operation, chainName);
2192 } catch (NativeDaemonConnectorException e) {
2193 throw e.rethrowAsParcelableException();
2194 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002195
2196 // Close any sockets that were opened by the affected UIDs. This has to be done after
2197 // disabling network connectivity, in case they react to the socket close by reopening
2198 // the connection and race with the iptables commands that enable the firewall. All
2199 // whitelist and blacklist chains allow RSTs through.
2200 if (enable) {
2201 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
Lorenzo Colitti3fef7232016-04-29 18:00:03 +09002202 closeSocketsForFirewallChainLocked(chain, chainName);
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002203 }
Amith Yamasani15e472352015-04-24 19:06:07 -07002204 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002205 }
2206
2207 private int getFirewallType(int chain) {
2208 switch (chain) {
2209 case FIREWALL_CHAIN_STANDBY:
2210 return FIREWALL_TYPE_BLACKLIST;
2211 case FIREWALL_CHAIN_DOZABLE:
2212 return FIREWALL_TYPE_WHITELIST;
Felipe Leme011b98f2016-02-10 17:28:31 -08002213 case FIREWALL_CHAIN_POWERSAVE:
2214 return FIREWALL_TYPE_WHITELIST;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002215 default:
2216 return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
2217 }
2218 }
2219
2220 @Override
2221 public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
2222 enforceSystemUid();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002223 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002224 synchronized (mRulesLock) {
2225 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
2226 SparseIntArray newRules = new SparseIntArray();
2227 // apply new set of rules
2228 for (int index = uids.length - 1; index >= 0; --index) {
2229 int uid = uids[index];
2230 int rule = rules[index];
2231 updateFirewallUidRuleLocked(chain, uid, rule);
2232 newRules.put(uid, rule);
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002233 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002234 // collect the rules to remove.
2235 SparseIntArray rulesToRemove = new SparseIntArray();
2236 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
2237 int uid = uidFirewallRules.keyAt(index);
2238 if (newRules.indexOfKey(uid) < 0) {
2239 rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
2240 }
2241 }
2242 // remove dead rules
2243 for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
2244 int uid = rulesToRemove.keyAt(index);
2245 updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
2246 }
Felipe Lemea701cad2016-05-12 09:58:14 -07002247 }
2248 try {
2249 switch (chain) {
2250 case FIREWALL_CHAIN_DOZABLE:
2251 mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
2252 break;
2253 case FIREWALL_CHAIN_STANDBY:
2254 mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
2255 break;
2256 case FIREWALL_CHAIN_POWERSAVE:
2257 mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
2258 break;
2259 case FIREWALL_CHAIN_NONE:
2260 default:
2261 Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
2262 }
2263 } catch (RemoteException e) {
2264 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002265 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002266 }
2267 }
2268
2269 @Override
2270 public void setFirewallUidRule(int chain, int uid, int rule) {
2271 enforceSystemUid();
Felipe Lemea701cad2016-05-12 09:58:14 -07002272 synchronized (mQuotaLock) {
2273 setFirewallUidRuleLocked(chain, uid, rule);
2274 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002275 }
2276
Felipe Lemea701cad2016-05-12 09:58:14 -07002277 private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
2278 if (updateFirewallUidRuleLocked(chain, uid, rule)) {
Amith Yamasani15e472352015-04-24 19:06:07 -07002279 try {
Felipe Lemea701cad2016-05-12 09:58:14 -07002280 mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
2281 getFirewallRuleName(chain, rule));
Amith Yamasani15e472352015-04-24 19:06:07 -07002282 } catch (NativeDaemonConnectorException e) {
2283 throw e.rethrowAsParcelableException();
2284 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002285 }
2286 }
2287
Felipe Lemea701cad2016-05-12 09:58:14 -07002288 // TODO: now that netd supports batching, NMS should not keep these data structures anymore...
2289 private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002290 synchronized (mRulesLock) {
2291 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
Felipe Lemea701cad2016-05-12 09:58:14 -07002292
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002293 final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
2294 if (DBG) {
2295 Slog.d(TAG, "oldRule = " + oldUidFirewallRule
2296 + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain);
2297 }
2298 if (oldUidFirewallRule == rule) {
2299 if (DBG) Slog.d(TAG, "!!!!! Skipping change");
2300 // TODO: eventually consider throwing
2301 return false;
2302 }
Felipe Lemea701cad2016-05-12 09:58:14 -07002303
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002304 String ruleName = getFirewallRuleName(chain, rule);
2305 String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
Felipe Lemea701cad2016-05-12 09:58:14 -07002306
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002307 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
2308 uidFirewallRules.delete(uid);
2309 } else {
2310 uidFirewallRules.put(uid, rule);
2311 }
2312 return !ruleName.equals(oldRuleName);
Felipe Lemea701cad2016-05-12 09:58:14 -07002313 }
Felipe Lemea701cad2016-05-12 09:58:14 -07002314 }
2315
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002316 private @NonNull String getFirewallRuleName(int chain, int rule) {
2317 String ruleName;
2318 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
2319 if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
2320 ruleName = "allow";
2321 } else {
2322 ruleName = "deny";
2323 }
2324 } else { // Blacklist mode
2325 if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
2326 ruleName = "deny";
2327 } else {
2328 ruleName = "allow";
2329 }
2330 }
2331 return ruleName;
2332 }
2333
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002334 private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) {
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002335 switch (chain) {
2336 case FIREWALL_CHAIN_STANDBY:
2337 return mUidFirewallStandbyRules;
2338 case FIREWALL_CHAIN_DOZABLE:
2339 return mUidFirewallDozableRules;
Felipe Leme011b98f2016-02-10 17:28:31 -08002340 case FIREWALL_CHAIN_POWERSAVE:
2341 return mUidFirewallPowerSaveRules;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002342 case FIREWALL_CHAIN_NONE:
2343 return mUidFirewallRules;
2344 default:
2345 throw new IllegalArgumentException("Unknown chain:" + chain);
2346 }
2347 }
2348
2349 public @NonNull String getFirewallChainName(int chain) {
2350 switch (chain) {
2351 case FIREWALL_CHAIN_STANDBY:
2352 return FIREWALL_CHAIN_NAME_STANDBY;
2353 case FIREWALL_CHAIN_DOZABLE:
2354 return FIREWALL_CHAIN_NAME_DOZABLE;
Felipe Leme011b98f2016-02-10 17:28:31 -08002355 case FIREWALL_CHAIN_POWERSAVE:
2356 return FIREWALL_CHAIN_NAME_POWERSAVE;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002357 case FIREWALL_CHAIN_NONE:
2358 return FIREWALL_CHAIN_NAME_NONE;
2359 default:
2360 throw new IllegalArgumentException("Unknown chain:" + chain);
2361 }
2362 }
2363
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07002364 private static void enforceSystemUid() {
2365 final int uid = Binder.getCallingUid();
2366 if (uid != Process.SYSTEM_UID) {
2367 throw new SecurityException("Only available to AID_SYSTEM");
2368 }
2369 }
2370
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002371 @Override
Lorenzo Colitti79751842013-02-28 16:16:03 +09002372 public void startClatd(String interfaceName) throws IllegalStateException {
2373 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2374
2375 try {
2376 mConnector.execute("clatd", "start", interfaceName);
2377 } catch (NativeDaemonConnectorException e) {
2378 throw e.rethrowAsParcelableException();
2379 }
2380 }
2381
2382 @Override
Lorenzo Colitti95439462014-10-09 13:44:48 +09002383 public void stopClatd(String interfaceName) throws IllegalStateException {
Lorenzo Colitti79751842013-02-28 16:16:03 +09002384 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2385
2386 try {
Lorenzo Colitti95439462014-10-09 13:44:48 +09002387 mConnector.execute("clatd", "stop", interfaceName);
Lorenzo Colitti79751842013-02-28 16:16:03 +09002388 } catch (NativeDaemonConnectorException e) {
2389 throw e.rethrowAsParcelableException();
2390 }
2391 }
2392
2393 @Override
Lorenzo Colitti95439462014-10-09 13:44:48 +09002394 public boolean isClatdStarted(String interfaceName) {
Lorenzo Colitti79751842013-02-28 16:16:03 +09002395 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2396
2397 final NativeDaemonEvent event;
2398 try {
Lorenzo Colitti95439462014-10-09 13:44:48 +09002399 event = mConnector.execute("clatd", "status", interfaceName);
Lorenzo Colitti79751842013-02-28 16:16:03 +09002400 } catch (NativeDaemonConnectorException e) {
2401 throw e.rethrowAsParcelableException();
2402 }
2403
2404 event.checkCode(ClatdStatusResult);
2405 return event.getMessage().endsWith("started");
2406 }
2407
Dianne Hackborn77b987f2014-02-26 16:20:52 -08002408 @Override
2409 public void registerNetworkActivityListener(INetworkActivityListener listener) {
2410 mNetworkActivityListeners.register(listener);
2411 }
2412
2413 @Override
2414 public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
2415 mNetworkActivityListeners.unregister(listener);
2416 }
2417
2418 @Override
2419 public boolean isNetworkActive() {
2420 synchronized (mNetworkActivityListeners) {
2421 return mNetworkActive || mActiveIdleTimers.isEmpty();
2422 }
2423 }
2424
2425 private void reportNetworkActive() {
2426 final int length = mNetworkActivityListeners.beginBroadcast();
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07002427 try {
2428 for (int i = 0; i < length; i++) {
2429 try {
2430 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
Felipe Leme03e689d2016-03-02 16:17:38 -08002431 } catch (RemoteException | RuntimeException e) {
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07002432 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08002433 }
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07002434 } finally {
2435 mNetworkActivityListeners.finishBroadcast();
Dianne Hackborn77b987f2014-02-26 16:20:52 -08002436 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08002437 }
2438
Mattias Falk8b47b362011-08-23 14:15:13 +02002439 /** {@inheritDoc} */
Jeff Sharkey7b4596f2013-02-25 10:55:29 -08002440 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07002441 public void monitor() {
2442 if (mConnector != null) {
2443 mConnector.monitor();
2444 }
2445 }
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002446
2447 @Override
2448 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06002449 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002450
Robert Greenwalt470fd722012-01-18 12:51:15 -08002451 pw.println("NetworkManagementService NativeDaemonConnector Log:");
2452 mConnector.dump(fd, pw, args);
2453 pw.println();
2454
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002455 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07002456 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
2457 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
2458 pw.print("mNetworkActive="); pw.println(mNetworkActive);
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002459
2460 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07002461 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
2462 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
Felipe Leme65be3022016-03-22 14:53:13 -07002463 pw.print("Data saver mode: "); pw.println(mDataSaverMode);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002464 synchronized (mRulesLock) {
2465 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
2466 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
2467 }
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002468 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002469
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002470 synchronized (mRulesLock) {
Felipe Leme011b98f2016-02-10 17:28:31 -08002471 dumpUidFirewallRule(pw, "", mUidFirewallRules);
Amith Yamasani15e472352015-04-24 19:06:07 -07002472
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002473 pw.print("UID firewall standby chain enabled: "); pw.println(
2474 getFirewallChainState(FIREWALL_CHAIN_STANDBY));
Felipe Leme011b98f2016-02-10 17:28:31 -08002475 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002476
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002477 pw.print("UID firewall dozable chain enabled: "); pw.println(
2478 getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
Felipe Leme011b98f2016-02-10 17:28:31 -08002479 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
Felipe Leme011b98f2016-02-10 17:28:31 -08002480
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002481 pw.println("UID firewall powersave chain enabled: " +
2482 getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
Felipe Leme011b98f2016-02-10 17:28:31 -08002483 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002484 }
2485
Dianne Hackborn77b987f2014-02-26 16:20:52 -08002486 synchronized (mIdleTimerLock) {
2487 pw.println("Idle timers:");
2488 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
2489 pw.print(" "); pw.print(ent.getKey()); pw.println(":");
2490 IdleTimerParams params = ent.getValue();
2491 pw.print(" timeout="); pw.print(params.timeout);
2492 pw.print(" type="); pw.print(params.type);
2493 pw.print(" networkCount="); pw.println(params.networkCount);
2494 }
2495 }
2496
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002497 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
Felipe Leme65be3022016-03-22 14:53:13 -07002498 pw.print("Netd service status: " );
2499 if (mNetdService == null) {
2500 pw.println("disconnected");
2501 } else {
2502 try {
2503 final boolean alive = mNetdService.isAlive();
2504 pw.println(alive ? "alive": "dead");
2505 } catch (RemoteException e) {
2506 pw.println("unreachable");
2507 }
2508 }
2509 }
2510
2511 private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
2512 pw.print("UID bandwith control ");
2513 pw.print(name);
2514 pw.print(" rule: [");
2515 final int size = list.size();
2516 for (int i = 0; i < size; i++) {
2517 pw.print(list.keyAt(i));
2518 if (i < size - 1) pw.print(",");
2519 }
2520 pw.println("]");
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002521 }
Robert Greenwalt9ba9c582014-03-19 17:56:12 -07002522
Felipe Leme011b98f2016-02-10 17:28:31 -08002523 private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002524 pw.print("UID firewall ");
Felipe Leme011b98f2016-02-10 17:28:31 -08002525 pw.print(name);
2526 pw.print(" rule: [");
2527 final int size = rules.size();
2528 for (int i = 0; i < size; i++) {
2529 pw.print(rules.keyAt(i));
2530 pw.print(":");
2531 pw.print(rules.valueAt(i));
2532 if (i < size - 1) pw.print(",");
2533 }
2534 pw.println("]");
2535 }
2536
Robert Greenwalt568891d2014-04-04 13:38:00 -07002537 @Override
Paul Jensen487ffe72015-07-24 15:57:11 -04002538 public void createPhysicalNetwork(int netId, String permission) {
Robert Greenwalt9ba9c582014-03-19 17:56:12 -07002539 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2540
2541 try {
Paul Jensen487ffe72015-07-24 15:57:11 -04002542 if (permission != null) {
2543 mConnector.execute("network", "create", netId, permission);
2544 } else {
2545 mConnector.execute("network", "create", netId);
2546 }
Robert Greenwalt9ba9c582014-03-19 17:56:12 -07002547 } catch (NativeDaemonConnectorException e) {
2548 throw e.rethrowAsParcelableException();
2549 }
2550 }
2551
Robert Greenwalt568891d2014-04-04 13:38:00 -07002552 @Override
Sreeram Ramachandran8cd33ed2014-07-23 15:23:15 -07002553 public void createVirtualNetwork(int netId, boolean hasDNS, boolean secure) {
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002554 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2555
2556 try {
Sreeram Ramachandran8cd33ed2014-07-23 15:23:15 -07002557 mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0",
2558 secure ? "1" : "0");
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002559 } catch (NativeDaemonConnectorException e) {
2560 throw e.rethrowAsParcelableException();
2561 }
2562 }
2563
2564 @Override
Robert Greenwalt9ba9c582014-03-19 17:56:12 -07002565 public void removeNetwork(int netId) {
2566 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2567
2568 try {
2569 mConnector.execute("network", "destroy", netId);
2570 } catch (NativeDaemonConnectorException e) {
2571 throw e.rethrowAsParcelableException();
2572 }
2573 }
Robert Greenwalt568891d2014-04-04 13:38:00 -07002574
2575 @Override
Paul Jensen992f2522014-04-28 10:33:11 -04002576 public void addInterfaceToNetwork(String iface, int netId) {
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002577 modifyInterfaceInNetwork("add", "" + netId, iface);
Paul Jensen992f2522014-04-28 10:33:11 -04002578 }
2579
2580 @Override
2581 public void removeInterfaceFromNetwork(String iface, int netId) {
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002582 modifyInterfaceInNetwork("remove", "" + netId, iface);
2583 }
Paul Jensen992f2522014-04-28 10:33:11 -04002584
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002585 private void modifyInterfaceInNetwork(String action, String netId, String iface) {
2586 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Paul Jensen992f2522014-04-28 10:33:11 -04002587 try {
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002588 mConnector.execute("network", "interface", action, netId, iface);
Paul Jensen992f2522014-04-28 10:33:11 -04002589 } catch (NativeDaemonConnectorException e) {
2590 throw e.rethrowAsParcelableException();
2591 }
2592 }
2593
2594 @Override
Robert Greenwalt913c8952014-04-07 17:36:35 -07002595 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
Robert Greenwalt568891d2014-04-04 13:38:00 -07002596 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2597
Sreeram Ramachandran03666c72014-07-19 23:21:46 -07002598 final Command cmd = new Command("network", "route", "legacy", uid, "add", netId);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002599
Sreeram Ramachandran1fbcb272014-05-22 16:30:48 -07002600 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -07002601 final LinkAddress la = routeInfo.getDestinationLinkAddress();
Robert Greenwalt568891d2014-04-04 13:38:00 -07002602 cmd.appendArg(routeInfo.getInterface());
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +09002603 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength());
Sreeram Ramachandran1fbcb272014-05-22 16:30:48 -07002604 if (routeInfo.hasGateway()) {
2605 cmd.appendArg(routeInfo.getGateway().getHostAddress());
2606 }
Robert Greenwalt568891d2014-04-04 13:38:00 -07002607
2608 try {
2609 mConnector.execute(cmd);
2610 } catch (NativeDaemonConnectorException e) {
2611 throw e.rethrowAsParcelableException();
2612 }
2613 }
2614
2615 @Override
Sreeram Ramachandranf047f2a2014-04-15 16:04:26 -07002616 public void setDefaultNetId(int netId) {
Robert Greenwalt568891d2014-04-04 13:38:00 -07002617 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2618
2619 try {
Sreeram Ramachandranf047f2a2014-04-15 16:04:26 -07002620 mConnector.execute("network", "default", "set", netId);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002621 } catch (NativeDaemonConnectorException e) {
2622 throw e.rethrowAsParcelableException();
2623 }
2624 }
2625
2626 @Override
2627 public void clearDefaultNetId() {
2628 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2629
2630 try {
2631 mConnector.execute("network", "default", "clear");
2632 } catch (NativeDaemonConnectorException e) {
2633 throw e.rethrowAsParcelableException();
2634 }
2635 }
2636
2637 @Override
Paul Jensen487ffe72015-07-24 15:57:11 -04002638 public void setNetworkPermission(int netId, String permission) {
2639 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2640
2641 try {
2642 if (permission != null) {
2643 mConnector.execute("network", "permission", "network", "set", permission, netId);
2644 } else {
2645 mConnector.execute("network", "permission", "network", "clear", netId);
2646 }
2647 } catch (NativeDaemonConnectorException e) {
2648 throw e.rethrowAsParcelableException();
2649 }
2650 }
2651
2652
2653 @Override
Sreeram Ramachandrane4a05af2014-09-24 09:16:19 -07002654 public void setPermission(String permission, int[] uids) {
Robert Greenwalt568891d2014-04-04 13:38:00 -07002655 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2656
Sreeram Ramachandrane4a05af2014-09-24 09:16:19 -07002657 Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND];
2658 argv[0] = "permission";
2659 argv[1] = "user";
2660 argv[2] = "set";
2661 argv[3] = permission;
2662 int argc = 4;
2663 // Avoid overly long commands by limiting number of UIDs per command.
2664 for (int i = 0; i < uids.length; ++i) {
2665 argv[argc++] = uids[i];
2666 if (i == uids.length - 1 || argc == argv.length) {
2667 try {
2668 mConnector.execute("network", Arrays.copyOf(argv, argc));
2669 } catch (NativeDaemonConnectorException e) {
2670 throw e.rethrowAsParcelableException();
2671 }
2672 argc = 4;
2673 }
Robert Greenwalt568891d2014-04-04 13:38:00 -07002674 }
2675 }
2676
2677 @Override
2678 public void clearPermission(int[] uids) {
2679 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2680
Sreeram Ramachandrane4a05af2014-09-24 09:16:19 -07002681 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2682 argv[0] = "permission";
2683 argv[1] = "user";
2684 argv[2] = "clear";
2685 int argc = 3;
2686 // Avoid overly long commands by limiting number of UIDs per command.
2687 for (int i = 0; i < uids.length; ++i) {
2688 argv[argc++] = uids[i];
2689 if (i == uids.length - 1 || argc == argv.length) {
2690 try {
2691 mConnector.execute("network", Arrays.copyOf(argv, argc));
2692 } catch (NativeDaemonConnectorException e) {
2693 throw e.rethrowAsParcelableException();
2694 }
2695 argc = 3;
2696 }
Robert Greenwalt568891d2014-04-04 13:38:00 -07002697 }
2698 }
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002699
2700 @Override
2701 public void allowProtect(int uid) {
2702 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2703
2704 try {
2705 mConnector.execute("network", "protect", "allow", uid);
2706 } catch (NativeDaemonConnectorException e) {
2707 throw e.rethrowAsParcelableException();
2708 }
2709 }
2710
2711 @Override
2712 public void denyProtect(int uid) {
2713 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2714
2715 try {
2716 mConnector.execute("network", "protect", "deny", uid);
2717 } catch (NativeDaemonConnectorException e) {
2718 throw e.rethrowAsParcelableException();
2719 }
2720 }
2721
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002722 @Override
2723 public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
2724 modifyInterfaceInNetwork("add", "local", iface);
2725
2726 for (RouteInfo route : routes) {
2727 if (!route.isDefaultRoute()) {
2728 modifyRoute("add", "local", route);
2729 }
2730 }
2731 }
2732
2733 @Override
2734 public void removeInterfaceFromLocalNetwork(String iface) {
2735 modifyInterfaceInNetwork("remove", "local", iface);
2736 }
Erik Kline6599ee82016-07-17 21:28:39 +09002737
2738 @Override
2739 public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
2740 int failures = 0;
2741
2742 for (RouteInfo route : routes) {
2743 try {
2744 modifyRoute("remove", "local", route);
2745 } catch (IllegalStateException e) {
2746 failures++;
2747 }
2748 }
2749
2750 return failures;
2751 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002752
Sudheer Shankab8f23162017-08-04 13:30:10 -07002753 @Override
2754 public boolean isNetworkRestricted(int uid) {
2755 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2756 return isNetworkRestrictedInternal(uid);
2757 }
2758
2759 private boolean isNetworkRestrictedInternal(int uid) {
2760 synchronized (mRulesLock) {
2761 if (getFirewallChainState(FIREWALL_CHAIN_STANDBY)
2762 && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) {
2763 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode");
2764 return true;
2765 }
2766 if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE)
2767 && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) {
2768 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode");
2769 return true;
2770 }
2771 if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)
2772 && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) {
2773 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
2774 return true;
2775 }
2776 if (mUidRejectOnMetered.get(uid)) {
2777 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
2778 + " in the background");
2779 return true;
2780 }
2781 if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) {
2782 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode");
2783 return true;
2784 }
2785 return false;
2786 }
2787 }
2788
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002789 private void setFirewallChainState(int chain, boolean state) {
2790 synchronized (mRulesLock) {
2791 mFirewallChainStates.put(chain, state);
2792 }
2793 }
2794
2795 private boolean getFirewallChainState(int chain) {
2796 synchronized (mRulesLock) {
2797 return mFirewallChainStates.get(chain);
2798 }
2799 }
2800
2801 @VisibleForTesting
2802 class LocalService extends NetworkManagementInternal {
2803 @Override
2804 public boolean isNetworkRestrictedForUid(int uid) {
Sudheer Shankab8f23162017-08-04 13:30:10 -07002805 return isNetworkRestrictedInternal(uid);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002806 }
2807 }
2808
2809 @VisibleForTesting
2810 Injector getInjector() {
2811 return new Injector();
2812 }
2813
2814 @VisibleForTesting
2815 class Injector {
2816 void setDataSaverMode(boolean dataSaverMode) {
2817 mDataSaverMode = dataSaverMode;
2818 }
2819
2820 void setFirewallChainState(int chain, boolean state) {
2821 NetworkManagementService.this.setFirewallChainState(chain, state);
2822 }
2823
2824 void setFirewallRule(int chain, int uid, int rule) {
2825 synchronized (mRulesLock) {
2826 getUidFirewallRulesLR(chain).put(uid, rule);
2827 }
2828 }
2829
2830 void setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable) {
2831 synchronized (mRulesLock) {
2832 if (blacklist) {
2833 mUidRejectOnMetered.put(uid, enable);
2834 } else {
2835 mUidAllowOnMetered.put(uid, enable);
2836 }
2837 }
2838 }
2839
2840 void reset() {
2841 synchronized (mRulesLock) {
2842 setDataSaverMode(false);
2843 final int[] chains = {
2844 FIREWALL_CHAIN_DOZABLE,
2845 FIREWALL_CHAIN_STANDBY,
2846 FIREWALL_CHAIN_POWERSAVE
2847 };
2848 for (int chain : chains) {
2849 setFirewallChainState(chain, false);
2850 getUidFirewallRulesLR(chain).clear();
2851 }
2852 mUidAllowOnMetered.clear();
2853 mUidRejectOnMetered.clear();
2854 }
2855 }
2856 }
San Mehat873f2142010-01-14 10:25:07 -08002857}