blob: 9224b925aca84d2c461341f4547a02e1bb77ef50 [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;
Sehee Parka9139bc2017-12-22 13:54:05 +090021import static android.Manifest.permission.NETWORK_SETTINGS;
Lorenzo Colitti07f13042017-07-10 19:06:57 +090022import static android.Manifest.permission.NETWORK_STACK;
Jeff Sharkeyaf75c332011-11-18 12:41:12 -080023import static android.Manifest.permission.SHUTDOWN;
Erik Kline4d092232017-10-30 15:29:44 +090024import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
25import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
26import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070027import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
28import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
29import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
Felipe Leme011b98f2016-02-10 17:28:31 -080030import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070031import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
32import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
Felipe Leme011b98f2016-02-10 17:28:31 -080033import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070034import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
Sudheer Shanka62f5c172017-03-17 16:25:55 -070035import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070036import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
Sudheer Shanka62f5c172017-03-17 16:25:55 -070037import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070038import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
39import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070040import static android.net.NetworkStats.SET_DEFAULT;
Lorenzo Colittif1912ca2017-08-17 19:23:08 +090041import static android.net.NetworkStats.STATS_PER_UID;
Dianne Hackbornd0c5b9a2014-02-21 16:19:05 -080042import static android.net.NetworkStats.TAG_ALL;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070043import static android.net.NetworkStats.TAG_NONE;
44import static android.net.NetworkStats.UID_ALL;
Jeff Sharkeyae2c1812011-10-04 13:11:40 -070045import static android.net.TrafficStats.UID_TETHERING;
Lorenzo Colitti79751842013-02-28 16:16:03 +090046import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -080047import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
48import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -080049import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult;
50import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult;
51import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult;
52import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult;
Jeff Sharkeye4984be2013-09-10 21:03:27 -070053import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -080054import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
Jeff Sharkeya63ba592011-07-19 23:47:12 -070055import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
Erik Klineb2cfdfb2017-01-18 20:54:14 +090056
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070057import android.annotation.NonNull;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080058import android.app.ActivityManager;
Pierre Imai8e48e672016-04-21 13:30:43 +090059import android.content.ContentResolver;
San Mehat873f2142010-01-14 10:25:07 -080060import android.content.Context;
Dianne Hackborn77b987f2014-02-26 16:20:52 -080061import android.net.ConnectivityManager;
Lorenzo Colitti58967ba2016-02-02 17:21:21 +090062import android.net.INetd;
San Mehat4d02d002010-01-22 16:07:46 -080063import android.net.INetworkManagementEventObserver;
Lorenzo Colitti07f13042017-07-10 19:06:57 +090064import android.net.ITetheringStatsProvider;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070065import android.net.InterfaceConfiguration;
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +090066import android.net.IpPrefix;
Robert Greenwalted126402011-01-28 15:34:55 -080067import android.net.LinkAddress;
Lorenzo Colittib57edc52014-08-22 17:10:50 -070068import android.net.Network;
Amith Yamasani15e472352015-04-24 19:06:07 -070069import android.net.NetworkPolicyManager;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070070import android.net.NetworkStats;
Robert Greenwalted126402011-01-28 15:34:55 -080071import android.net.NetworkUtils;
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070072import android.net.RouteInfo;
Paul Jensen6bc2c2c2014-05-07 15:27:40 -040073import android.net.UidRange;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +090074import android.net.util.NetdService;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080075import android.net.wifi.WifiConfiguration;
76import android.net.wifi.WifiConfiguration.KeyMgmt;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070077import android.os.BatteryStats;
Jeff Sharkeyf56e2432012-09-06 17:54:29 -070078import android.os.Binder;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -070079import android.os.Handler;
Lorenzo Colittia0868002017-07-11 02:29:28 +090080import android.os.IBinder;
Dianne Hackborn77b987f2014-02-26 16:20:52 -080081import android.os.INetworkActivityListener;
San Mehat873f2142010-01-14 10:25:07 -080082import android.os.INetworkManagementService;
Lorenzo Colitti563dc452017-09-01 17:12:34 +090083import android.os.PersistableBundle;
Dianne Hackborn77b987f2014-02-26 16:20:52 -080084import android.os.PowerManager;
Jeff Sharkeyf56e2432012-09-06 17:54:29 -070085import android.os.Process;
Jeff Sharkey3df273e2011-12-15 15:47:12 -080086import android.os.RemoteCallbackList;
87import android.os.RemoteException;
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -070088import android.os.ServiceManager;
Lorenzo Colitti4cb42402016-04-24 12:52:00 +090089import android.os.ServiceSpecificException;
Jeff Sharkey605eb792014-11-04 13:34:06 -080090import android.os.StrictMode;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070091import android.os.SystemClock;
Marco Nelissen62dbb222010-02-18 10:56:30 -080092import android.os.SystemProperties;
Felipe Leme29e72ea2016-09-08 13:26:55 -070093import android.os.Trace;
Pierre Imai8e48e672016-04-21 13:30:43 +090094import android.provider.Settings;
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -070095import android.telephony.DataConnectionRealTimeInfo;
96import android.telephony.PhoneStateListener;
Wink Savillefb40dd42014-06-12 17:02:31 -070097import android.telephony.SubscriptionManager;
Wink Saville67e07892014-06-18 16:43:14 -070098import android.telephony.TelephonyManager;
Erik Kline4d092232017-10-30 15:29:44 +090099import android.text.TextUtils;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800100import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800101import android.util.Slog;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700102import android.util.SparseBooleanArray;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800103import android.util.SparseIntArray;
San Mehat873f2142010-01-14 10:25:07 -0800104
Jeff Sharkey605eb792014-11-04 13:34:06 -0800105import com.android.internal.annotations.GuardedBy;
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700106import com.android.internal.annotations.VisibleForTesting;
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -0700107import com.android.internal.app.IBatteryStats;
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700108import com.android.internal.net.NetworkStatsFactory;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600109import com.android.internal.util.DumpUtils;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800110import com.android.internal.util.HexDump;
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700111import com.android.internal.util.Preconditions;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800112import com.android.server.NativeDaemonConnector.Command;
Jeff Sharkey56cd6462013-06-07 15:09:15 -0700113import com.android.server.NativeDaemonConnector.SensitiveArg;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700114import com.google.android.collect.Maps;
Jeff Sharkey4414cea2011-06-24 17:05:24 -0700115
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700116import java.io.BufferedReader;
117import java.io.DataInputStream;
San Mehat873f2142010-01-14 10:25:07 -0800118import java.io.File;
Jeff Sharkey47eb1022011-08-25 17:48:52 -0700119import java.io.FileDescriptor;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700120import java.io.FileInputStream;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700121import java.io.IOException;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700122import java.io.InputStreamReader;
Jeff Sharkey47eb1022011-08-25 17:48:52 -0700123import java.io.PrintWriter;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -0700124import java.net.InetAddress;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700125import java.net.InterfaceAddress;
126import java.net.NetworkInterface;
127import java.net.SocketException;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -0700128import java.util.ArrayList;
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400129import java.util.Arrays;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700130import java.util.HashMap;
jiaguo1da35f72014-01-09 16:39:59 +0800131import java.util.List;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700132import java.util.Map;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -0700133import java.util.NoSuchElementException;
134import java.util.StringTokenizer;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700135import java.util.concurrent.CountDownLatch;
San Mehat873f2142010-01-14 10:25:07 -0800136
137/**
138 * @hide
139 */
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700140public class NetworkManagementService extends INetworkManagementService.Stub
141 implements Watchdog.Monitor {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900142
143 /**
144 * Helper class that encapsulates NetworkManagementService dependencies and makes them
145 * easier to mock in unit tests.
146 */
147 static class SystemServices {
148 public IBinder getService(String name) {
149 return ServiceManager.getService(name);
150 }
151 public void registerLocalService(NetworkManagementInternal nmi) {
152 LocalServices.addService(NetworkManagementInternal.class, nmi);
153 }
154 public INetd getNetd() {
155 return NetdService.get();
156 }
157 }
158
Amith Yamasani15e472352015-04-24 19:06:07 -0700159 private static final String TAG = "NetworkManagement";
160 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
Kenny Root305bcbf2010-09-03 07:56:38 -0700161 private static final String NETD_TAG = "NetdConnector";
Lorenzo Colittia0868002017-07-11 02:29:28 +0900162 static final String NETD_SERVICE_NAME = "netd";
Kenny Root305bcbf2010-09-03 07:56:38 -0700163
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400164 private static final int MAX_UID_RANGES_PER_COMMAND = 10;
165
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700166 /**
167 * Name representing {@link #setGlobalAlert(long)} limit when delivered to
168 * {@link INetworkManagementEventObserver#limitReached(String, String)}.
169 */
170 public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
171
Paul Jensen487ffe72015-07-24 15:57:11 -0400172 /**
173 * String to pass to netd to indicate that a network is only accessible
174 * to apps that have the CHANGE_NETWORK_STATE permission.
175 */
176 public static final String PERMISSION_NETWORK = "NETWORK";
177
178 /**
179 * String to pass to netd to indicate that a network is only
180 * accessible to system apps and those with the CONNECTIVITY_INTERNAL
181 * permission.
182 */
183 public static final String PERMISSION_SYSTEM = "SYSTEM";
184
Andrew Scull45f533c2017-05-19 15:37:20 +0100185 static class NetdResponseCode {
Sreeram Ramachandran03666c72014-07-19 23:21:46 -0700186 /* Keep in sync with system/netd/server/ResponseCode.h */
San Mehat873f2142010-01-14 10:25:07 -0800187 public static final int InterfaceListResult = 110;
188 public static final int TetherInterfaceListResult = 111;
189 public static final int TetherDnsFwdTgtListResult = 112;
San Mehat72759df2010-01-19 13:50:37 -0800190 public static final int TtyListResult = 113;
Jeff Sharkeye4984be2013-09-10 21:03:27 -0700191 public static final int TetheringStatsListResult = 114;
San Mehat873f2142010-01-14 10:25:07 -0800192
193 public static final int TetherStatusResult = 210;
194 public static final int IpFwdStatusResult = 211;
San Mehated4fc8a2010-01-22 12:28:36 -0800195 public static final int InterfaceGetCfgResult = 213;
Robert Greenwalte3253922010-02-18 09:23:25 -0800196 public static final int SoftapStatusResult = 214;
San Mehat91cac642010-03-31 14:31:36 -0700197 public static final int InterfaceRxCounterResult = 216;
198 public static final int InterfaceTxCounterResult = 217;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700199 public static final int QuotaCounterResult = 220;
200 public static final int TetheringStatsResult = 221;
Selim Gurun84c00c62012-02-27 15:42:38 -0800201 public static final int DnsProxyQueryResult = 222;
Lorenzo Colitti79751842013-02-28 16:16:03 +0900202 public static final int ClatdStatusResult = 223;
Robert Greenwalte3253922010-02-18 09:23:25 -0800203
204 public static final int InterfaceChange = 600;
JP Abgrall12b933d2011-07-14 18:09:22 -0700205 public static final int BandwidthControl = 601;
Haoyu Bai6b7358d2012-07-17 16:36:50 -0700206 public static final int InterfaceClassActivity = 613;
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900207 public static final int InterfaceAddressChange = 614;
Lorenzo Colitti5ae4a532013-10-31 11:59:46 +0900208 public static final int InterfaceDnsServerInfo = 615;
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +0900209 public static final int RouteChange = 616;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800210 public static final int StrictCleartext = 617;
San Mehat873f2142010-01-14 10:25:07 -0800211 }
212
Pierre Imai8e48e672016-04-21 13:30:43 +0900213 /* Defaults for resolver parameters. */
214 public static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
215 public static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
216 public static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
217 public static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
218
Rebecca Silbersteine2ec94f2016-03-24 13:29:00 -0700219 /**
220 * String indicating a softap command.
221 */
222 static final String SOFT_AP_COMMAND = "softap";
223
224 /**
225 * String passed back to netd connector indicating softap command success.
226 */
227 static final String SOFT_AP_COMMAND_SUCCESS = "Ok";
228
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700229 static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
230
San Mehat873f2142010-01-14 10:25:07 -0800231 /**
232 * Binder context for this service
233 */
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700234 private final Context mContext;
San Mehat873f2142010-01-14 10:25:07 -0800235
236 /**
237 * connector object for communicating with netd
238 */
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700239 private final NativeDaemonConnector mConnector;
San Mehat873f2142010-01-14 10:25:07 -0800240
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700241 private final Handler mFgHandler;
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700242 private final Handler mDaemonHandler;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700243
Lorenzo Colittia0868002017-07-11 02:29:28 +0900244 private final SystemServices mServices;
245
Lorenzo Colitti58967ba2016-02-02 17:21:21 +0900246 private INetd mNetdService;
247
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800248 private IBatteryStats mBatteryStats;
249
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700250 private final Thread mThread;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700251 private CountDownLatch mConnectedSignal = new CountDownLatch(1);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700252
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800253 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
Christopher Wiley212b95f2016-08-02 11:38:57 -0700254 new RemoteCallbackList<>();
San Mehat4d02d002010-01-22 16:07:46 -0800255
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700256 private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
257
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900258 @GuardedBy("mTetheringStatsProviders")
259 private final HashMap<ITetheringStatsProvider, String>
260 mTetheringStatsProviders = Maps.newHashMap();
261
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700262 /**
263 * If both locks need to be held, then they should be obtained in the order:
264 * first {@link #mQuotaLock} and then {@link #mRulesLock}.
265 */
Andrew Scull45f533c2017-05-19 15:37:20 +0100266 private final Object mQuotaLock = new Object();
Andrew Scull519291f2017-05-23 13:11:03 +0100267 private final Object mRulesLock = new Object();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800268
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700269 /** Set of interfaces with active quotas. */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800270 @GuardedBy("mQuotaLock")
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700271 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700272 /** Set of interfaces with active alerts. */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800273 @GuardedBy("mQuotaLock")
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700274 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
Felipe Leme65be3022016-03-22 14:53:13 -0700275 /** Set of UIDs blacklisted on metered networks. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700276 @GuardedBy("mRulesLock")
Felipe Leme65be3022016-03-22 14:53:13 -0700277 private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
278 /** Set of UIDs whitelisted on metered networks. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700279 @GuardedBy("mRulesLock")
Felipe Leme65be3022016-03-22 14:53:13 -0700280 private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800281 /** Set of UIDs with cleartext penalties. */
282 @GuardedBy("mQuotaLock")
283 private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
Amith Yamasani15e472352015-04-24 19:06:07 -0700284 /** Set of UIDs that are to be blocked/allowed by firewall controller. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700285 @GuardedBy("mRulesLock")
Amith Yamasani15e472352015-04-24 19:06:07 -0700286 private SparseIntArray mUidFirewallRules = new SparseIntArray();
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700287 /**
288 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
289 * to application idles.
290 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700291 @GuardedBy("mRulesLock")
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700292 private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
293 /**
294 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
295 * to device idles.
296 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700297 @GuardedBy("mRulesLock")
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700298 private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
Felipe Leme011b98f2016-02-10 17:28:31 -0800299 /**
300 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
301 * to device on power-save mode.
302 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700303 @GuardedBy("mRulesLock")
Felipe Leme011b98f2016-02-10 17:28:31 -0800304 private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -0700305 /** Set of states for the child firewall chains. True if the chain is active. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700306 @GuardedBy("mRulesLock")
Xiaohui Chen8dca36d2015-06-19 12:44:59 -0700307 final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700308
Felipe Leme65be3022016-03-22 14:53:13 -0700309 @GuardedBy("mQuotaLock")
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700310 private volatile boolean mDataSaverMode;
Felipe Leme65be3022016-03-22 14:53:13 -0700311
Andrew Scull45f533c2017-05-19 15:37:20 +0100312 private final Object mIdleTimerLock = new Object();
Haoyu Bai04124232012-06-28 15:26:19 -0700313 /** Set of interfaces with active idle timers. */
314 private static class IdleTimerParams {
315 public final int timeout;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800316 public final int type;
Haoyu Bai04124232012-06-28 15:26:19 -0700317 public int networkCount;
318
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800319 IdleTimerParams(int timeout, int type) {
Haoyu Bai04124232012-06-28 15:26:19 -0700320 this.timeout = timeout;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800321 this.type = type;
Haoyu Bai04124232012-06-28 15:26:19 -0700322 this.networkCount = 1;
323 }
324 }
325 private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
326
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700327 private volatile boolean mBandwidthControlEnabled;
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700328 private volatile boolean mFirewallEnabled;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800329 private volatile boolean mStrictEnabled;
Jeff Sharkey350083e2011-06-29 10:45:16 -0700330
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700331 private boolean mMobileActivityFromRadio = false;
332 private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
Adam Lesinskie08af192015-03-25 16:42:59 -0700333 private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700334
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800335 private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
Christopher Wiley212b95f2016-08-02 11:38:57 -0700336 new RemoteCallbackList<>();
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800337 private boolean mNetworkActive;
338
San Mehat873f2142010-01-14 10:25:07 -0800339 /**
340 * Constructs a new NetworkManagementService instance
341 *
342 * @param context Binder context for this service
343 */
Lorenzo Colittia0868002017-07-11 02:29:28 +0900344 private NetworkManagementService(
345 Context context, String socket, SystemServices services) {
San Mehat873f2142010-01-14 10:25:07 -0800346 mContext = context;
Lorenzo Colittia0868002017-07-11 02:29:28 +0900347 mServices = services;
San Mehat4d02d002010-01-22 16:07:46 -0800348
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700349 // make sure this is on the same looper as our NativeDaemonConnector for sync purposes
350 mFgHandler = new Handler(FgThread.get().getLooper());
351
Dianne Hackborn4590e522014-03-24 13:36:46 -0700352 // Don't need this wake lock, since we now have a time stamp for when
353 // the network actually went inactive. (It might be nice to still do this,
354 // but I don't want to do it through the power manager because that pollutes the
355 // battery stats history with pointless noise.)
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700356 //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
Dianne Hackborn4590e522014-03-24 13:36:46 -0700357 PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800358
San Mehat873f2142010-01-14 10:25:07 -0800359 mConnector = new NativeDaemonConnector(
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700360 new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
361 FgThread.get().getLooper());
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700362 mThread = new Thread(mConnector, NETD_TAG);
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700363
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700364 mDaemonHandler = new Handler(FgThread.get().getLooper());
Wink Saville67e07892014-06-18 16:43:14 -0700365
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700366 // Add ourself to the Watchdog monitors.
367 Watchdog.getInstance().addMonitor(this);
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700368
Lorenzo Colittia0868002017-07-11 02:29:28 +0900369 mServices.registerLocalService(new LocalService());
Lorenzo Colitti8228eb32017-07-19 06:17:33 +0900370
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900371 synchronized (mTetheringStatsProviders) {
372 mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
373 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700374 }
375
376 @VisibleForTesting
377 NetworkManagementService() {
378 mConnector = null;
379 mContext = null;
380 mDaemonHandler = null;
381 mFgHandler = null;
382 mThread = null;
Lorenzo Colittia0868002017-07-11 02:29:28 +0900383 mServices = null;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700384 }
385
Lorenzo Colittia0868002017-07-11 02:29:28 +0900386 static NetworkManagementService create(Context context, String socket, SystemServices services)
Felipe Leme03e689d2016-03-02 16:17:38 -0800387 throws InterruptedException {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900388 final NetworkManagementService service =
389 new NetworkManagementService(context, socket, services);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700390 final CountDownLatch connectedSignal = service.mConnectedSignal;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700391 if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
392 service.mThread.start();
393 if (DBG) Slog.d(TAG, "Awaiting socket connection");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700394 connectedSignal.await();
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700395 if (DBG) Slog.d(TAG, "Connected");
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900396 if (DBG) Slog.d(TAG, "Connecting native netd service");
bohu07cc3bb2016-05-03 15:58:01 -0700397 service.connectNativeNetdService();
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900398 if (DBG) Slog.d(TAG, "Connected");
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700399 return service;
San Mehat873f2142010-01-14 10:25:07 -0800400 }
401
Lorenzo Colitti7421a012013-08-20 22:51:24 +0900402 public static NetworkManagementService create(Context context) throws InterruptedException {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900403 return create(context, NETD_SERVICE_NAME, new SystemServices());
Lorenzo Colitti7421a012013-08-20 22:51:24 +0900404 }
405
Jeff Sharkey350083e2011-06-29 10:45:16 -0700406 public void systemReady() {
Felipe Leme03e689d2016-03-02 16:17:38 -0800407 if (DBG) {
408 final long start = System.currentTimeMillis();
409 prepareNativeDaemon();
410 final long delta = System.currentTimeMillis() - start;
411 Slog.d(TAG, "Prepared in " + delta + "ms");
412 return;
413 } else {
414 prepareNativeDaemon();
415 }
Jeff Sharkey350083e2011-06-29 10:45:16 -0700416 }
417
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800418 private IBatteryStats getBatteryStats() {
419 synchronized (this) {
420 if (mBatteryStats != null) {
421 return mBatteryStats;
422 }
Lorenzo Colittia0868002017-07-11 02:29:28 +0900423 mBatteryStats =
424 IBatteryStats.Stub.asInterface(mServices.getService(BatteryStats.SERVICE_NAME));
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800425 return mBatteryStats;
426 }
427 }
428
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800429 @Override
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800430 public void registerObserver(INetworkManagementEventObserver observer) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800431 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800432 mObservers.register(observer);
San Mehat4d02d002010-01-22 16:07:46 -0800433 }
434
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800435 @Override
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800436 public void unregisterObserver(INetworkManagementEventObserver observer) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800437 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800438 mObservers.unregister(observer);
San Mehat4d02d002010-01-22 16:07:46 -0800439 }
440
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900441 @FunctionalInterface
442 private interface NetworkManagementEventCallback {
443 public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
444 }
445
446 private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800447 final int length = mObservers.beginBroadcast();
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700448 try {
449 for (int i = 0; i < length; i++) {
450 try {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900451 eventCallback.sendCallback(mObservers.getBroadcastItem(i));
Felipe Leme03e689d2016-03-02 16:17:38 -0800452 } catch (RemoteException | RuntimeException e) {
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700453 }
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700454 }
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700455 } finally {
456 mObservers.finishBroadcast();
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700457 }
458 }
459
460 /**
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900461 * Notify our observers of an interface status change
462 */
463 private void notifyInterfaceStatusChanged(String iface, boolean up) {
464 invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
465 }
466
467 /**
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700468 * Notify our observers of an interface link state change
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700469 * (typically, an Ethernet cable has been plugged-in or unplugged).
470 */
471 private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900472 invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
San Mehat4d02d002010-01-22 16:07:46 -0800473 }
474
475 /**
476 * Notify our observers of an interface addition.
477 */
478 private void notifyInterfaceAdded(String iface) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900479 invokeForAllObservers(o -> o.interfaceAdded(iface));
San Mehat4d02d002010-01-22 16:07:46 -0800480 }
481
482 /**
483 * Notify our observers of an interface removal.
484 */
485 private void notifyInterfaceRemoved(String iface) {
Jeff Sharkey89b8a212011-10-11 11:58:11 -0700486 // netd already clears out quota and alerts for removed ifaces; update
487 // our sanity-checking state.
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700488 mActiveAlerts.remove(iface);
489 mActiveQuotas.remove(iface);
Jeff Sharkey89b8a212011-10-11 11:58:11 -0700490
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900491 invokeForAllObservers(o -> o.interfaceRemoved(iface));
San Mehat4d02d002010-01-22 16:07:46 -0800492 }
493
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700494 /**
JP Abgrall12b933d2011-07-14 18:09:22 -0700495 * Notify our observers of a limit reached.
496 */
497 private void notifyLimitReached(String limitName, String iface) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900498 invokeForAllObservers(o -> o.limitReached(limitName, iface));
JP Abgrall12b933d2011-07-14 18:09:22 -0700499 }
500
501 /**
Haoyu Baidb3c8672012-06-20 14:29:57 -0700502 * Notify our observers of a change in the data activity state of the interface
503 */
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700504 private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos,
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700505 int uid, boolean fromRadio) {
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700506 final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
507 if (isMobile) {
508 if (!fromRadio) {
509 if (mMobileActivityFromRadio) {
510 // If this call is not coming from a report from the radio itself, but we
511 // have previously received reports from the radio, then we will take the
512 // power state to just be whatever the radio last reported.
513 powerState = mLastPowerStateFromRadio;
514 }
515 } else {
516 mMobileActivityFromRadio = true;
517 }
518 if (mLastPowerStateFromRadio != powerState) {
519 mLastPowerStateFromRadio = powerState;
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700520 try {
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700521 getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700522 } catch (RemoteException e) {
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700523 }
Haoyu Baidb3c8672012-06-20 14:29:57 -0700524 }
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700525 }
526
Adam Lesinskie08af192015-03-25 16:42:59 -0700527 if (ConnectivityManager.isNetworkTypeWifi(type)) {
528 if (mLastPowerStateFromWifi != powerState) {
529 mLastPowerStateFromWifi = powerState;
530 try {
Adam Lesinski5f056f62016-07-14 16:56:08 -0700531 getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
Adam Lesinskie08af192015-03-25 16:42:59 -0700532 } catch (RemoteException e) {
533 }
534 }
535 }
536
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700537 boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
538 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
539
540 if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
541 // Report the change in data activity. We don't do this if this is a change
542 // on the mobile network, that is not coming from the radio itself, and we
543 // have previously seen change reports from the radio. In that case only
544 // the radio is the authority for the current state.
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900545 final boolean active = isActive;
546 invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
547 Integer.toString(type), active, tsNanos));
Haoyu Baidb3c8672012-06-20 14:29:57 -0700548 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800549
550 boolean report = false;
551 synchronized (mIdleTimerLock) {
552 if (mActiveIdleTimers.isEmpty()) {
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700553 // If there are no idle timers, we are not monitoring activity, so we
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800554 // are always considered active.
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700555 isActive = true;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800556 }
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700557 if (mNetworkActive != isActive) {
558 mNetworkActive = isActive;
559 report = isActive;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800560 }
561 }
562 if (report) {
563 reportNetworkActive();
564 }
Haoyu Baidb3c8672012-06-20 14:29:57 -0700565 }
566
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900567 @Override
568 public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
569 mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
570 Preconditions.checkNotNull(provider);
571 synchronized(mTetheringStatsProviders) {
572 mTetheringStatsProviders.put(provider, name);
573 }
574 }
575
576 @Override
577 public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
578 mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
579 synchronized(mTetheringStatsProviders) {
580 mTetheringStatsProviders.remove(provider);
581 }
582 }
583
Lorenzo Colitti9f0baa92017-08-15 19:25:51 +0900584 @Override
585 public void tetherLimitReached(ITetheringStatsProvider provider) {
586 mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
587 synchronized(mTetheringStatsProviders) {
588 if (!mTetheringStatsProviders.containsKey(provider)) {
589 return;
590 }
591 // No current code examines the interface parameter in a global alert. Just pass null.
592 notifyLimitReached(LIMIT_GLOBAL_ALERT, null);
593 }
594 }
595
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900596 // Sync the state of the given chain with the native daemon.
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700597 private void syncFirewallChainLocked(int chain, String name) {
598 SparseIntArray rules;
599 synchronized (mRulesLock) {
600 final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900601 // Make a copy of the current rules, and then clear them. This is because
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700602 // setFirewallUidRuleInternal only pushes down rules to the native daemon if they
603 // are different from the current rules stored in the mUidFirewall*Rules array for
604 // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal
605 // will do nothing.
606 rules = uidFirewallRules.clone();
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900607 uidFirewallRules.clear();
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700608 }
609 if (rules.size() > 0) {
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900610 // Now push the rules. setFirewallUidRuleInternal will push each of these down to the
611 // native daemon, and also add them to the mUidFirewall*Rules array for the specified
612 // chain.
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700613 if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall "
614 + name + "UID rules");
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900615 for (int i = 0; i < rules.size(); i++) {
Felipe Lemea701cad2016-05-12 09:58:14 -0700616 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i));
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900617 }
618 }
619 }
620
bohu07cc3bb2016-05-03 15:58:01 -0700621 private void connectNativeNetdService() {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900622 mNetdService = mServices.getNetd();
bohu07cc3bb2016-05-03 15:58:01 -0700623 }
624
625 /**
626 * Prepare native daemon once connected, enabling modules and pushing any
627 * existing in-memory rules.
628 */
629 private void prepareNativeDaemon() {
Lorenzo Colitti58967ba2016-02-02 17:21:21 +0900630
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700631 mBandwidthControlEnabled = false;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700632
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700633 // only enable bandwidth control when support exists
634 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800635
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700636 // push any existing quota or UID rules
637 synchronized (mQuotaLock) {
Felipe Leme65be3022016-03-22 14:53:13 -0700638
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900639 if (hasKernelSupport) {
640 Slog.d(TAG, "enabling bandwidth control");
641 try {
642 mConnector.execute("bandwidth", "enable");
643 mBandwidthControlEnabled = true;
644 } catch (NativeDaemonConnectorException e) {
645 Log.wtf(TAG, "problem enabling bandwidth controls", e);
646 }
647 } else {
648 Slog.i(TAG, "not enabling bandwidth control");
649 }
650
651 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
652
653 try {
654 mConnector.execute("strict", "enable");
655 mStrictEnabled = true;
656 } catch (NativeDaemonConnectorException e) {
657 Log.wtf(TAG, "Failed strict enable", e);
658 }
659
Felipe Leme65be3022016-03-22 14:53:13 -0700660 setDataSaverModeEnabled(mDataSaverMode);
661
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700662 int size = mActiveQuotas.size();
663 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800664 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700665 final HashMap<String, Long> activeQuotas = mActiveQuotas;
666 mActiveQuotas = Maps.newHashMap();
667 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
668 setInterfaceQuota(entry.getKey(), entry.getValue());
669 }
670 }
671
672 size = mActiveAlerts.size();
673 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800674 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700675 final HashMap<String, Long> activeAlerts = mActiveAlerts;
676 mActiveAlerts = Maps.newHashMap();
677 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
678 setInterfaceAlert(entry.getKey(), entry.getValue());
679 }
680 }
681
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700682 SparseBooleanArray uidRejectOnQuota = null;
683 SparseBooleanArray uidAcceptOnQuota = null;
684 synchronized (mRulesLock) {
685 size = mUidRejectOnMetered.size();
686 if (size > 0) {
687 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
688 uidRejectOnQuota = mUidRejectOnMetered;
689 mUidRejectOnMetered = new SparseBooleanArray();
690 }
691
692 size = mUidAllowOnMetered.size();
693 if (size > 0) {
694 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
695 uidAcceptOnQuota = mUidAllowOnMetered;
696 mUidAllowOnMetered = new SparseBooleanArray();
697 }
698 }
699 if (uidRejectOnQuota != null) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700700 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
Felipe Leme65be3022016-03-22 14:53:13 -0700701 setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
702 uidRejectOnQuota.valueAt(i));
703 }
704 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700705 if (uidAcceptOnQuota != null) {
Felipe Leme65be3022016-03-22 14:53:13 -0700706 for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
707 setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
708 uidAcceptOnQuota.valueAt(i));
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700709 }
710 }
Jeff Sharkey605eb792014-11-04 13:34:06 -0800711
712 size = mUidCleartextPolicy.size();
713 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800714 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
Jeff Sharkey605eb792014-11-04 13:34:06 -0800715 final SparseIntArray local = mUidCleartextPolicy;
716 mUidCleartextPolicy = new SparseIntArray();
717 for (int i = 0; i < local.size(); i++) {
718 setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
719 }
720 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700721
Robin Leec3736bc2017-03-10 16:19:54 +0000722 setFirewallEnabled(mFirewallEnabled);
Amith Yamasani15e472352015-04-24 19:06:07 -0700723
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700724 syncFirewallChainLocked(FIREWALL_CHAIN_NONE, "");
725 syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
726 syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
727 syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700728
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700729 final int[] chains =
730 {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
731 for (int chain : chains) {
732 if (getFirewallChainState(chain)) {
733 setFirewallChainEnabled(chain, true);
734 }
Felipe Leme011b98f2016-02-10 17:28:31 -0800735 }
Amith Yamasani15e472352015-04-24 19:06:07 -0700736 }
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900737
738 if (mBandwidthControlEnabled) {
739 try {
740 getBatteryStats().noteNetworkStatsEnabled();
741 } catch (RemoteException e) {
742 }
743 }
744
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700745 }
San Mehat4d02d002010-01-22 16:07:46 -0800746
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900747 /**
748 * Notify our observers of a new or updated interface address.
749 */
Lorenzo Colitti64483942013-11-15 18:43:52 +0900750 private void notifyAddressUpdated(String iface, LinkAddress address) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900751 invokeForAllObservers(o -> o.addressUpdated(iface, address));
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900752 }
753
754 /**
755 * Notify our observers of a deleted interface address.
756 */
Lorenzo Colitti64483942013-11-15 18:43:52 +0900757 private void notifyAddressRemoved(String iface, LinkAddress address) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900758 invokeForAllObservers(o -> o.addressRemoved(iface, address));
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900759 }
760
Lorenzo Colitti5ae4a532013-10-31 11:59:46 +0900761 /**
762 * Notify our observers of DNS server information received.
763 */
764 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900765 invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
Lorenzo Colitti5ae4a532013-10-31 11:59:46 +0900766 }
767
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +0900768 /**
769 * Notify our observers of a route change.
770 */
771 private void notifyRouteChange(String action, RouteInfo route) {
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900772 if (action.equals("updated")) {
773 invokeForAllObservers(o -> o.routeUpdated(route));
774 } else {
775 invokeForAllObservers(o -> o.routeRemoved(route));
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +0900776 }
777 }
778
San Mehat873f2142010-01-14 10:25:07 -0800779 //
780 // Netd Callback handling
781 //
782
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700783 private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
784 @Override
San Mehat873f2142010-01-14 10:25:07 -0800785 public void onDaemonConnected() {
Felipe Leme65be3022016-03-22 14:53:13 -0700786 Slog.i(TAG, "onDaemonConnected()");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700787 // event is dispatched from internal NDC thread, so we prepare the
788 // daemon back on main thread.
789 if (mConnectedSignal != null) {
bohu07cc3bb2016-05-03 15:58:01 -0700790 // The system is booting and we're connecting to netd for the first time.
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700791 mConnectedSignal.countDown();
792 mConnectedSignal = null;
793 } else {
bohu07cc3bb2016-05-03 15:58:01 -0700794 // We're reconnecting to netd after the socket connection
795 // was interrupted (e.g., if it crashed).
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700796 mFgHandler.post(new Runnable() {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700797 @Override
798 public void run() {
bohu07cc3bb2016-05-03 15:58:01 -0700799 connectNativeNetdService();
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700800 prepareNativeDaemon();
801 }
802 });
803 }
San Mehat873f2142010-01-14 10:25:07 -0800804 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700805
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700806 @Override
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800807 public boolean onCheckHoldWakeLock(int code) {
808 return code == NetdResponseCode.InterfaceClassActivity;
809 }
810
811 @Override
San Mehat873f2142010-01-14 10:25:07 -0800812 public boolean onEvent(int code, String raw, String[] cooked) {
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900813 String errorMessage = String.format("Invalid event from daemon (%s)", raw);
JP Abgrall12b933d2011-07-14 18:09:22 -0700814 switch (code) {
815 case NetdResponseCode.InterfaceChange:
816 /*
817 * a network interface change occured
818 * Format: "NNN Iface added <name>"
819 * "NNN Iface removed <name>"
820 * "NNN Iface changed <name> <up/down>"
821 * "NNN Iface linkstatus <name> <up/down>"
822 */
823 if (cooked.length < 4 || !cooked[1].equals("Iface")) {
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900824 throw new IllegalStateException(errorMessage);
JP Abgrall12b933d2011-07-14 18:09:22 -0700825 }
826 if (cooked[2].equals("added")) {
827 notifyInterfaceAdded(cooked[3]);
828 return true;
829 } else if (cooked[2].equals("removed")) {
830 notifyInterfaceRemoved(cooked[3]);
831 return true;
832 } else if (cooked[2].equals("changed") && cooked.length == 5) {
833 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
834 return true;
835 } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
836 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
837 return true;
838 }
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900839 throw new IllegalStateException(errorMessage);
JP Abgrall12b933d2011-07-14 18:09:22 -0700840 // break;
841 case NetdResponseCode.BandwidthControl:
842 /*
843 * Bandwidth control needs some attention
844 * Format: "NNN limit alert <alertName> <ifaceName>"
845 */
846 if (cooked.length < 5 || !cooked[1].equals("limit")) {
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900847 throw new IllegalStateException(errorMessage);
JP Abgrall12b933d2011-07-14 18:09:22 -0700848 }
849 if (cooked[2].equals("alert")) {
850 notifyLimitReached(cooked[3], cooked[4]);
851 return true;
852 }
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900853 throw new IllegalStateException(errorMessage);
JP Abgrall12b933d2011-07-14 18:09:22 -0700854 // break;
Haoyu Baidb3c8672012-06-20 14:29:57 -0700855 case NetdResponseCode.InterfaceClassActivity:
856 /*
857 * An network interface class state changed (active/idle)
858 * Format: "NNN IfaceClass <active/idle> <label>"
859 */
860 if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900861 throw new IllegalStateException(errorMessage);
Haoyu Baidb3c8672012-06-20 14:29:57 -0700862 }
Ashish Sharma0535a9f2014-03-12 18:42:23 -0700863 long timestampNanos = 0;
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700864 int processUid = -1;
865 if (cooked.length >= 5) {
Ashish Sharma0535a9f2014-03-12 18:42:23 -0700866 try {
867 timestampNanos = Long.parseLong(cooked[4]);
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700868 if (cooked.length == 6) {
869 processUid = Integer.parseInt(cooked[5]);
870 }
Ashish Sharma0535a9f2014-03-12 18:42:23 -0700871 } catch(NumberFormatException ne) {}
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700872 } else {
873 timestampNanos = SystemClock.elapsedRealtimeNanos();
Ashish Sharma0535a9f2014-03-12 18:42:23 -0700874 }
Haoyu Baidb3c8672012-06-20 14:29:57 -0700875 boolean isActive = cooked[2].equals("active");
Ashish Sharma0535a9f2014-03-12 18:42:23 -0700876 notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700877 isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -0700878 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
879 timestampNanos, processUid, false);
Haoyu Baidb3c8672012-06-20 14:29:57 -0700880 return true;
881 // break;
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900882 case NetdResponseCode.InterfaceAddressChange:
883 /*
884 * A network address change occurred
885 * Format: "NNN Address updated <addr> <iface> <flags> <scope>"
886 * "NNN Address removed <addr> <iface> <flags> <scope>"
887 */
Lorenzo Colittia9626c12013-11-04 17:44:09 +0900888 if (cooked.length < 7 || !cooked[1].equals("Address")) {
889 throw new IllegalStateException(errorMessage);
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900890 }
891
Lorenzo Colitti64483942013-11-15 18:43:52 +0900892 String iface = cooked[4];
Lorenzo Colitti5ad421a2013-11-17 15:05:02 +0900893 LinkAddress address;
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900894 try {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900895 int flags = Integer.parseInt(cooked[5]);
896 int scope = Integer.parseInt(cooked[6]);
897 address = new LinkAddress(cooked[3], flags, scope);
Lorenzo Colitti5ad421a2013-11-17 15:05:02 +0900898 } catch(NumberFormatException e) { // Non-numeric lifetime or scope.
899 throw new IllegalStateException(errorMessage, e);
Lorenzo Colitti64483942013-11-15 18:43:52 +0900900 } catch(IllegalArgumentException e) { // Malformed/invalid IP address.
Lorenzo Colitti5ad421a2013-11-17 15:05:02 +0900901 throw new IllegalStateException(errorMessage, e);
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900902 }
903
904 if (cooked[2].equals("updated")) {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900905 notifyAddressUpdated(iface, address);
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900906 } else {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900907 notifyAddressRemoved(iface, address);
Lorenzo Colitti5c7daac2013-08-05 10:39:37 +0900908 }
909 return true;
910 // break;
Lorenzo Colitti5ae4a532013-10-31 11:59:46 +0900911 case NetdResponseCode.InterfaceDnsServerInfo:
912 /*
913 * Information about available DNS servers has been received.
914 * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>"
915 */
916 long lifetime; // Actually a 32-bit unsigned integer.
917
918 if (cooked.length == 6 &&
919 cooked[1].equals("DnsInfo") &&
920 cooked[2].equals("servers")) {
921 try {
922 lifetime = Long.parseLong(cooked[4]);
923 } catch (NumberFormatException e) {
924 throw new IllegalStateException(errorMessage);
925 }
926 String[] servers = cooked[5].split(",");
927 notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
928 }
929 return true;
930 // break;
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +0900931 case NetdResponseCode.RouteChange:
932 /*
933 * A route has been updated or removed.
934 * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]"
935 */
936 if (!cooked[1].equals("Route") || cooked.length < 6) {
937 throw new IllegalStateException(errorMessage);
938 }
939
940 String via = null;
941 String dev = null;
942 boolean valid = true;
943 for (int i = 4; (i + 1) < cooked.length && valid; i += 2) {
944 if (cooked[i].equals("dev")) {
945 if (dev == null) {
946 dev = cooked[i+1];
947 } else {
948 valid = false; // Duplicate interface.
949 }
950 } else if (cooked[i].equals("via")) {
951 if (via == null) {
952 via = cooked[i+1];
953 } else {
954 valid = false; // Duplicate gateway.
955 }
956 } else {
957 valid = false; // Unknown syntax.
958 }
959 }
960 if (valid) {
961 try {
962 // InetAddress.parseNumericAddress(null) inexplicably returns ::1.
963 InetAddress gateway = null;
964 if (via != null) gateway = InetAddress.parseNumericAddress(via);
965 RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
966 notifyRouteChange(cooked[2], route);
967 return true;
968 } catch (IllegalArgumentException e) {}
969 }
970 throw new IllegalStateException(errorMessage);
971 // break;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800972 case NetdResponseCode.StrictCleartext:
973 final int uid = Integer.parseInt(cooked[1]);
974 final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]);
975 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800976 ActivityManager.getService().notifyCleartextNetwork(uid, firstPacket);
Jeff Sharkey605eb792014-11-04 13:34:06 -0800977 } catch (RemoteException ignored) {
978 }
979 break;
JP Abgrall12b933d2011-07-14 18:09:22 -0700980 default: break;
Robert Greenwalte3253922010-02-18 09:23:25 -0800981 }
982 return false;
San Mehat873f2142010-01-14 10:25:07 -0800983 }
984 }
985
San Mehated4fc8a2010-01-22 12:28:36 -0800986
San Mehat873f2142010-01-14 10:25:07 -0800987 //
988 // INetworkManagementService members
989 //
Erik Kline4e37b702016-07-05 11:34:21 +0900990 @Override
991 public INetd getNetdService() throws RemoteException {
992 final CountDownLatch connectedSignal = mConnectedSignal;
993 if (connectedSignal != null) {
994 try {
995 connectedSignal.await();
996 } catch (InterruptedException ignored) {}
997 }
998
999 return mNetdService;
1000 }
San Mehat873f2142010-01-14 10:25:07 -08001001
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001002 @Override
1003 public String[] listInterfaces() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001004 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001005 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001006 return NativeDaemonEvent.filterMessageList(
1007 mConnector.executeForList("interface", "list"), InterfaceListResult);
Kenny Roota80ce062010-06-01 13:23:53 -07001008 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001009 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001010 }
San Mehated4fc8a2010-01-22 12:28:36 -08001011 }
1012
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001013 @Override
1014 public InterfaceConfiguration getInterfaceConfig(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001015 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001016
1017 final NativeDaemonEvent event;
Kenny Roota80ce062010-06-01 13:23:53 -07001018 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001019 event = mConnector.execute("interface", "getcfg", iface);
Kenny Roota80ce062010-06-01 13:23:53 -07001020 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001021 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001022 }
San Mehated4fc8a2010-01-22 12:28:36 -08001023
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001024 event.checkCode(InterfaceGetCfgResult);
1025
1026 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3
1027 final StringTokenizer st = new StringTokenizer(event.getMessage());
San Mehated4fc8a2010-01-22 12:28:36 -08001028
Kenny Roota80ce062010-06-01 13:23:53 -07001029 InterfaceConfiguration cfg;
San Mehated4fc8a2010-01-22 12:28:36 -08001030 try {
Kenny Roota80ce062010-06-01 13:23:53 -07001031 cfg = new InterfaceConfiguration();
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001032 cfg.setHardwareAddress(st.nextToken(" "));
Robert Greenwalted126402011-01-28 15:34:55 -08001033 InetAddress addr = null;
Robert Greenwalt2d2afd12011-02-01 15:30:46 -08001034 int prefixLength = 0;
Kenny Roota80ce062010-06-01 13:23:53 -07001035 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001036 addr = NetworkUtils.numericToInetAddress(st.nextToken());
Robert Greenwalte5903732011-02-22 16:00:42 -08001037 } catch (IllegalArgumentException iae) {
1038 Slog.e(TAG, "Failed to parse ipaddr", iae);
Kenny Roota80ce062010-06-01 13:23:53 -07001039 }
1040
1041 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001042 prefixLength = Integer.parseInt(st.nextToken());
Robert Greenwalt2d2afd12011-02-01 15:30:46 -08001043 } catch (NumberFormatException nfe) {
1044 Slog.e(TAG, "Failed to parse prefixLength", nfe);
Kenny Roota80ce062010-06-01 13:23:53 -07001045 }
Robert Greenwalt04808c22010-12-13 17:01:41 -08001046
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001047 cfg.setLinkAddress(new LinkAddress(addr, prefixLength));
1048 while (st.hasMoreTokens()) {
1049 cfg.setFlag(st.nextToken());
1050 }
Kenny Roota80ce062010-06-01 13:23:53 -07001051 } catch (NoSuchElementException nsee) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001052 throw new IllegalStateException("Invalid response from daemon: " + event);
San Mehated4fc8a2010-01-22 12:28:36 -08001053 }
San Mehated4fc8a2010-01-22 12:28:36 -08001054 return cfg;
1055 }
1056
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001057 @Override
1058 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001059 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001060 LinkAddress linkAddr = cfg.getLinkAddress();
Robert Greenwalt2d2afd12011-02-01 15:30:46 -08001061 if (linkAddr == null || linkAddr.getAddress() == null) {
1062 throw new IllegalStateException("Null LinkAddress given");
Robert Greenwalted126402011-01-28 15:34:55 -08001063 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001064
1065 final Command cmd = new Command("interface", "setcfg", iface,
Robert Greenwalt2d2afd12011-02-01 15:30:46 -08001066 linkAddr.getAddress().getHostAddress(),
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +09001067 linkAddr.getPrefixLength());
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001068 for (String flag : cfg.getFlags()) {
1069 cmd.appendArg(flag);
1070 }
1071
Kenny Roota80ce062010-06-01 13:23:53 -07001072 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001073 mConnector.execute(cmd);
Kenny Roota80ce062010-06-01 13:23:53 -07001074 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001075 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001076 }
San Mehat873f2142010-01-14 10:25:07 -08001077 }
1078
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001079 @Override
1080 public void setInterfaceDown(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001081 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001082 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001083 ifcg.setInterfaceDown();
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001084 setInterfaceConfig(iface, ifcg);
Irfan Sheriff7244c972011-08-05 20:40:45 -07001085 }
1086
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001087 @Override
1088 public void setInterfaceUp(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001089 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001090 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001091 ifcg.setInterfaceUp();
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001092 setInterfaceConfig(iface, ifcg);
Irfan Sheriff7244c972011-08-05 20:40:45 -07001093 }
1094
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001095 @Override
1096 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001097 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Irfan Sheriff73293612011-09-14 12:31:56 -07001098 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001099 mConnector.execute(
1100 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable");
Irfan Sheriff73293612011-09-14 12:31:56 -07001101 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001102 throw e.rethrowAsParcelableException();
Irfan Sheriff73293612011-09-14 12:31:56 -07001103 }
1104 }
1105
Irfan Sherifff5600612011-06-16 10:26:28 -07001106 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
1107 IPv6 addresses on interface down, but we need to do full clean up here */
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001108 @Override
1109 public void clearInterfaceAddresses(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001110 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Irfan Sherifff5600612011-06-16 10:26:28 -07001111 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001112 mConnector.execute("interface", "clearaddrs", iface);
Irfan Sherifff5600612011-06-16 10:26:28 -07001113 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001114 throw e.rethrowAsParcelableException();
Irfan Sherifff5600612011-06-16 10:26:28 -07001115 }
1116 }
1117
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001118 @Override
1119 public void enableIpv6(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001120 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
repo sync7960d9f2011-09-29 12:40:02 -07001121 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001122 mConnector.execute("interface", "ipv6", iface, "enable");
repo sync7960d9f2011-09-29 12:40:02 -07001123 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001124 throw e.rethrowAsParcelableException();
repo sync7960d9f2011-09-29 12:40:02 -07001125 }
1126 }
1127
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001128 @Override
Joel Scherpelz2db10742017-06-07 15:38:38 +09001129 public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
1130 try {
1131 mNetdService.setIPv6AddrGenMode(iface, mode);
1132 } catch (RemoteException e) {
1133 throw e.rethrowAsRuntimeException();
1134 }
1135 }
1136
1137 @Override
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001138 public void disableIpv6(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001139 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
repo sync7960d9f2011-09-29 12:40:02 -07001140 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001141 mConnector.execute("interface", "ipv6", iface, "disable");
repo sync7960d9f2011-09-29 12:40:02 -07001142 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001143 throw e.rethrowAsParcelableException();
repo sync7960d9f2011-09-29 12:40:02 -07001144 }
1145 }
1146
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001147 @Override
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -07001148 public void addRoute(int netId, RouteInfo route) {
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07001149 modifyRoute("add", "" + netId, route);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -07001150 }
1151
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001152 @Override
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -07001153 public void removeRoute(int netId, RouteInfo route) {
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07001154 modifyRoute("remove", "" + netId, route);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -07001155 }
1156
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07001157 private void modifyRoute(String action, String netId, RouteInfo route) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001158 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001159
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -07001160 final Command cmd = new Command("network", "route", action, netId);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001161
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -07001162 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -07001163 cmd.appendArg(route.getInterface());
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +09001164 cmd.appendArg(route.getDestination().toString());
1165
1166 switch (route.getType()) {
1167 case RouteInfo.RTN_UNICAST:
1168 if (route.hasGateway()) {
1169 cmd.appendArg(route.getGateway().getHostAddress());
1170 }
1171 break;
1172 case RouteInfo.RTN_UNREACHABLE:
1173 cmd.appendArg("unreachable");
1174 break;
1175 case RouteInfo.RTN_THROW:
1176 cmd.appendArg("throw");
1177 break;
Sreeram Ramachandran1fbcb272014-05-22 16:30:48 -07001178 }
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -07001179
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001180 try {
1181 mConnector.execute(cmd);
1182 } catch (NativeDaemonConnectorException e) {
1183 throw e.rethrowAsParcelableException();
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -07001184 }
1185 }
1186
1187 private ArrayList<String> readRouteList(String filename) {
1188 FileInputStream fstream = null;
Christopher Wiley212b95f2016-08-02 11:38:57 -07001189 ArrayList<String> list = new ArrayList<>();
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -07001190
1191 try {
1192 fstream = new FileInputStream(filename);
1193 DataInputStream in = new DataInputStream(fstream);
1194 BufferedReader br = new BufferedReader(new InputStreamReader(in));
1195 String s;
1196
1197 // throw away the title line
1198
1199 while (((s = br.readLine()) != null) && (s.length() != 0)) {
1200 list.add(s);
1201 }
1202 } catch (IOException ex) {
1203 // return current list, possibly empty
1204 } finally {
1205 if (fstream != null) {
1206 try {
1207 fstream.close();
1208 } catch (IOException ex) {}
1209 }
1210 }
1211
1212 return list;
1213 }
1214
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001215 @Override
sy.yun9d9b74a2013-09-02 05:24:09 +09001216 public void setMtu(String iface, int mtu) {
1217 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1218
1219 final NativeDaemonEvent event;
1220 try {
1221 event = mConnector.execute("interface", "setmtu", iface, mtu);
1222 } catch (NativeDaemonConnectorException e) {
1223 throw e.rethrowAsParcelableException();
1224 }
1225 }
1226
1227 @Override
San Mehat873f2142010-01-14 10:25:07 -08001228 public void shutdown() {
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001229 // TODO: remove from aidl if nobody calls externally
1230 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
San Mehat873f2142010-01-14 10:25:07 -08001231
Felipe Leme03e689d2016-03-02 16:17:38 -08001232 Slog.i(TAG, "Shutting down");
San Mehat873f2142010-01-14 10:25:07 -08001233 }
1234
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001235 @Override
San Mehat873f2142010-01-14 10:25:07 -08001236 public boolean getIpForwardingEnabled() throws IllegalStateException{
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001237 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat873f2142010-01-14 10:25:07 -08001238
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001239 final NativeDaemonEvent event;
Kenny Roota80ce062010-06-01 13:23:53 -07001240 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001241 event = mConnector.execute("ipfwd", "status");
Kenny Roota80ce062010-06-01 13:23:53 -07001242 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001243 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001244 }
San Mehat873f2142010-01-14 10:25:07 -08001245
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001246 // 211 Forwarding enabled
1247 event.checkCode(IpFwdStatusResult);
1248 return event.getMessage().endsWith("enabled");
San Mehat873f2142010-01-14 10:25:07 -08001249 }
1250
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001251 @Override
1252 public void setIpForwardingEnabled(boolean enable) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001253 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001254 try {
Nilesh Poddarf3d4a582015-02-24 12:11:11 -08001255 mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering");
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001256 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001257 throw e.rethrowAsParcelableException();
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001258 }
San Mehat873f2142010-01-14 10:25:07 -08001259 }
1260
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001261 @Override
1262 public void startTethering(String[] dhcpRange) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001263 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -07001264 // cmd is "tether start first_start first_stop second_start second_stop ..."
1265 // an odd number of addrs will fail
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001266
1267 final Command cmd = new Command("tether", "start");
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -07001268 for (String d : dhcpRange) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001269 cmd.appendArg(d);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -07001270 }
Kenny Roota80ce062010-06-01 13:23:53 -07001271
1272 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001273 mConnector.execute(cmd);
Kenny Roota80ce062010-06-01 13:23:53 -07001274 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001275 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001276 }
San Mehat873f2142010-01-14 10:25:07 -08001277 }
1278
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001279 @Override
1280 public void stopTethering() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001281 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001282 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001283 mConnector.execute("tether", "stop");
Kenny Roota80ce062010-06-01 13:23:53 -07001284 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001285 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001286 }
San Mehat873f2142010-01-14 10:25:07 -08001287 }
1288
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001289 @Override
1290 public boolean isTetheringStarted() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001291 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat873f2142010-01-14 10:25:07 -08001292
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001293 final NativeDaemonEvent event;
Kenny Roota80ce062010-06-01 13:23:53 -07001294 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001295 event = mConnector.execute("tether", "status");
Kenny Roota80ce062010-06-01 13:23:53 -07001296 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001297 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001298 }
San Mehat873f2142010-01-14 10:25:07 -08001299
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001300 // 210 Tethering services started
1301 event.checkCode(TetherStatusResult);
1302 return event.getMessage().endsWith("started");
San Mehat873f2142010-01-14 10:25:07 -08001303 }
Matthew Xiefe19f122012-07-12 16:03:32 -07001304
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001305 @Override
1306 public void tetherInterface(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001307 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001308 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001309 mConnector.execute("tether", "interface", "add", iface);
Kenny Roota80ce062010-06-01 13:23:53 -07001310 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001311 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001312 }
Christopher Wiley212b95f2016-08-02 11:38:57 -07001313 List<RouteInfo> routes = new ArrayList<>();
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07001314 // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
1315 // suitable to use as a route destination.
1316 routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
1317 addInterfaceToLocalNetwork(iface, routes);
San Mehat873f2142010-01-14 10:25:07 -08001318 }
1319
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001320 @Override
San Mehat873f2142010-01-14 10:25:07 -08001321 public void untetherInterface(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001322 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001323 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001324 mConnector.execute("tether", "interface", "remove", iface);
Kenny Roota80ce062010-06-01 13:23:53 -07001325 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001326 throw e.rethrowAsParcelableException();
Erik Kline1f4278a2016-08-16 16:46:33 +09001327 } finally {
1328 removeInterfaceFromLocalNetwork(iface);
Kenny Roota80ce062010-06-01 13:23:53 -07001329 }
San Mehat873f2142010-01-14 10:25:07 -08001330 }
1331
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001332 @Override
1333 public String[] listTetheredInterfaces() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001334 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001335 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001336 return NativeDaemonEvent.filterMessageList(
1337 mConnector.executeForList("tether", "interface", "list"),
1338 TetherInterfaceListResult);
Kenny Roota80ce062010-06-01 13:23:53 -07001339 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001340 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001341 }
San Mehat873f2142010-01-14 10:25:07 -08001342 }
1343
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001344 @Override
Lorenzo Colittib57edc52014-08-22 17:10:50 -07001345 public void setDnsForwarders(Network network, String[] dns) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001346 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001347
Lorenzo Colittib57edc52014-08-22 17:10:50 -07001348 int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
1349 final Command cmd = new Command("tether", "dns", "set", netId);
1350
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001351 for (String s : dns) {
1352 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
1353 }
1354
San Mehat873f2142010-01-14 10:25:07 -08001355 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001356 mConnector.execute(cmd);
1357 } catch (NativeDaemonConnectorException e) {
1358 throw e.rethrowAsParcelableException();
San Mehat873f2142010-01-14 10:25:07 -08001359 }
1360 }
1361
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001362 @Override
1363 public String[] getDnsForwarders() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001364 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001365 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001366 return NativeDaemonEvent.filterMessageList(
1367 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult);
Kenny Roota80ce062010-06-01 13:23:53 -07001368 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001369 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001370 }
San Mehat873f2142010-01-14 10:25:07 -08001371 }
1372
jiaguo1da35f72014-01-09 16:39:59 +08001373 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
Christopher Wiley212b95f2016-08-02 11:38:57 -07001374 ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
jiaguo1da35f72014-01-09 16:39:59 +08001375 for (InterfaceAddress ia : addresses) {
1376 if (!ia.getAddress().isLinkLocalAddress())
1377 filtered.add(ia);
1378 }
1379 return filtered;
1380 }
1381
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001382 private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
1383 final Command cmd = new Command("ipfwd", add ? "add" : "remove", fromIface, toIface);
1384 try {
1385 mConnector.execute(cmd);
1386 } catch (NativeDaemonConnectorException e) {
1387 throw e.rethrowAsParcelableException();
1388 }
1389 }
1390
1391 @Override
1392 public void startInterfaceForwarding(String fromIface, String toIface) {
1393 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1394 modifyInterfaceForward(true, fromIface, toIface);
1395 }
1396
1397 @Override
1398 public void stopInterfaceForwarding(String fromIface, String toIface) {
1399 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1400 modifyInterfaceForward(false, fromIface, toIface);
1401 }
1402
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001403 private void modifyNat(String action, String internalInterface, String externalInterface)
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001404 throws SocketException {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001405 final Command cmd = new Command("nat", action, internalInterface, externalInterface);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001406
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001407 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName(
1408 internalInterface);
Robert Greenwalte83d1812011-11-21 14:44:39 -08001409 if (internalNetworkInterface == null) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001410 cmd.appendArg("0");
Robert Greenwalte83d1812011-11-21 14:44:39 -08001411 } else {
jiaguo1da35f72014-01-09 16:39:59 +08001412 // Don't touch link-local routes, as link-local addresses aren't routable,
1413 // kernel creates link-local routes on all interfaces automatically
1414 List<InterfaceAddress> interfaceAddresses = excludeLinkLocal(
1415 internalNetworkInterface.getInterfaceAddresses());
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001416 cmd.appendArg(interfaceAddresses.size());
Robert Greenwalte83d1812011-11-21 14:44:39 -08001417 for (InterfaceAddress ia : interfaceAddresses) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001418 InetAddress addr = NetworkUtils.getNetworkPart(
1419 ia.getAddress(), ia.getNetworkPrefixLength());
1420 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength());
Robert Greenwalte83d1812011-11-21 14:44:39 -08001421 }
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001422 }
1423
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001424 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001425 mConnector.execute(cmd);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001426 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001427 throw e.rethrowAsParcelableException();
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001428 }
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001429 }
1430
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001431 @Override
1432 public void enableNat(String internalInterface, String externalInterface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001433 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001434 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001435 modifyNat("enable", internalInterface, externalInterface);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001436 } catch (SocketException e) {
1437 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001438 }
San Mehat873f2142010-01-14 10:25:07 -08001439 }
1440
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001441 @Override
1442 public void disableNat(String internalInterface, String externalInterface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001443 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001444 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001445 modifyNat("disable", internalInterface, externalInterface);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001446 } catch (SocketException e) {
1447 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001448 }
San Mehat873f2142010-01-14 10:25:07 -08001449 }
San Mehat72759df2010-01-19 13:50:37 -08001450
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001451 @Override
1452 public String[] listTtys() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001453 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001454 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001455 return NativeDaemonEvent.filterMessageList(
1456 mConnector.executeForList("list_ttys"), TtyListResult);
Kenny Roota80ce062010-06-01 13:23:53 -07001457 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001458 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001459 }
San Mehat72759df2010-01-19 13:50:37 -08001460 }
1461
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001462 @Override
1463 public void attachPppd(
1464 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001465 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat72759df2010-01-19 13:50:37 -08001466 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001467 mConnector.execute("pppd", "attach", tty,
Robert Greenwalte5903732011-02-22 16:00:42 -08001468 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
1469 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
1470 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001471 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress());
Kenny Roota80ce062010-06-01 13:23:53 -07001472 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001473 throw e.rethrowAsParcelableException();
San Mehat72759df2010-01-19 13:50:37 -08001474 }
1475 }
1476
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001477 @Override
1478 public void detachPppd(String tty) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001479 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001480 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001481 mConnector.execute("pppd", "detach", tty);
Kenny Roota80ce062010-06-01 13:23:53 -07001482 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001483 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001484 }
San Mehat72759df2010-01-19 13:50:37 -08001485 }
Robert Greenwaltce1200d2010-02-18 11:25:54 -08001486
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001487 @Override
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001488 public void addIdleTimer(String iface, int timeout, final int type) {
Haoyu Bai04124232012-06-28 15:26:19 -07001489 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1490
1491 if (DBG) Slog.d(TAG, "Adding idletimer");
1492
1493 synchronized (mIdleTimerLock) {
1494 IdleTimerParams params = mActiveIdleTimers.get(iface);
1495 if (params != null) {
1496 // the interface already has idletimer, update network count
1497 params.networkCount++;
1498 return;
1499 }
1500
1501 try {
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001502 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout),
1503 Integer.toString(type));
Haoyu Bai04124232012-06-28 15:26:19 -07001504 } catch (NativeDaemonConnectorException e) {
1505 throw e.rethrowAsParcelableException();
1506 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001507 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
1508
Dianne Hackborne13c4c02014-02-11 17:18:35 -08001509 // Networks start up.
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001510 if (ConnectivityManager.isNetworkTypeMobile(type)) {
1511 mNetworkActive = false;
1512 }
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07001513 mDaemonHandler.post(new Runnable() {
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001514 @Override public void run() {
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07001515 notifyInterfaceClassActivity(type,
1516 DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -07001517 SystemClock.elapsedRealtimeNanos(), -1, false);
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001518 }
1519 });
Haoyu Bai04124232012-06-28 15:26:19 -07001520 }
1521 }
1522
1523 @Override
1524 public void removeIdleTimer(String iface) {
1525 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1526
1527 if (DBG) Slog.d(TAG, "Removing idletimer");
1528
1529 synchronized (mIdleTimerLock) {
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001530 final IdleTimerParams params = mActiveIdleTimers.get(iface);
Haoyu Bai04124232012-06-28 15:26:19 -07001531 if (params == null || --(params.networkCount) > 0) {
1532 return;
1533 }
1534
1535 try {
1536 mConnector.execute("idletimer", "remove", iface,
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001537 Integer.toString(params.timeout), Integer.toString(params.type));
Haoyu Bai04124232012-06-28 15:26:19 -07001538 } catch (NativeDaemonConnectorException e) {
1539 throw e.rethrowAsParcelableException();
1540 }
1541 mActiveIdleTimers.remove(iface);
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07001542 mDaemonHandler.post(new Runnable() {
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001543 @Override public void run() {
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07001544 notifyInterfaceClassActivity(params.type,
1545 DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
Ruchi Kandoifa97fcf2016-05-13 15:10:39 -07001546 SystemClock.elapsedRealtimeNanos(), -1, false);
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001547 }
1548 });
Haoyu Bai04124232012-06-28 15:26:19 -07001549 }
1550 }
1551
1552 @Override
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001553 public NetworkStats getNetworkStatsSummaryDev() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001554 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001555 try {
1556 return mStatsFactory.readNetworkStatsSummaryDev();
1557 } catch (IOException e) {
1558 throw new IllegalStateException(e);
1559 }
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001560 }
1561
1562 @Override
1563 public NetworkStats getNetworkStatsSummaryXt() {
1564 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001565 try {
1566 return mStatsFactory.readNetworkStatsSummaryXt();
1567 } catch (IOException e) {
1568 throw new IllegalStateException(e);
1569 }
Jeff Sharkeyae2c1812011-10-04 13:11:40 -07001570 }
1571
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001572 @Override
Jeff Sharkey9a13f362011-04-26 16:25:36 -07001573 public NetworkStats getNetworkStatsDetail() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001574 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001575 try {
Dianne Hackbornd0c5b9a2014-02-21 16:19:05 -08001576 return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001577 } catch (IOException e) {
1578 throw new IllegalStateException(e);
1579 }
San Mehat91cac642010-03-31 14:31:36 -07001580 }
1581
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001582 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001583 public void setInterfaceQuota(String iface, long quotaBytes) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001584 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001585
Jeff Sharkey350083e2011-06-29 10:45:16 -07001586 // silently discard when control disabled
1587 // TODO: eventually migrate to be always enabled
1588 if (!mBandwidthControlEnabled) return;
1589
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001590 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001591 if (mActiveQuotas.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001592 throw new IllegalStateException("iface " + iface + " already has quota");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001593 }
1594
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001595 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001596 // TODO: support quota shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001597 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001598 mActiveQuotas.put(iface, quotaBytes);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001599 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001600 throw e.rethrowAsParcelableException();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001601 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001602
1603 synchronized (mTetheringStatsProviders) {
1604 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1605 try {
1606 provider.setInterfaceQuota(iface, quotaBytes);
1607 } catch (RemoteException e) {
1608 Log.e(TAG, "Problem setting tethering data limit on provider " +
1609 mTetheringStatsProviders.get(provider) + ": " + e);
1610 }
1611 }
1612 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001613 }
1614 }
1615
1616 @Override
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001617 public void removeInterfaceQuota(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001618 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001619
Jeff Sharkey350083e2011-06-29 10:45:16 -07001620 // silently discard when control disabled
1621 // TODO: eventually migrate to be always enabled
1622 if (!mBandwidthControlEnabled) return;
1623
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001624 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001625 if (!mActiveQuotas.containsKey(iface)) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001626 // TODO: eventually consider throwing
1627 return;
1628 }
1629
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001630 mActiveQuotas.remove(iface);
1631 mActiveAlerts.remove(iface);
Jeff Sharkey38ddeaa2011-11-08 13:04:22 -08001632
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001633 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001634 // TODO: support quota shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001635 mConnector.execute("bandwidth", "removeiquota", iface);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001636 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001637 throw e.rethrowAsParcelableException();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001638 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001639
1640 synchronized (mTetheringStatsProviders) {
1641 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1642 try {
1643 provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
1644 } catch (RemoteException e) {
1645 Log.e(TAG, "Problem removing tethering data limit on provider " +
1646 mTetheringStatsProviders.get(provider) + ": " + e);
1647 }
1648 }
1649 }
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001650 }
1651 }
1652
1653 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001654 public void setInterfaceAlert(String iface, long alertBytes) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001655 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001656
1657 // silently discard when control disabled
1658 // TODO: eventually migrate to be always enabled
1659 if (!mBandwidthControlEnabled) return;
1660
1661 // quick sanity check
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001662 if (!mActiveQuotas.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001663 throw new IllegalStateException("setting alert requires existing quota on iface");
1664 }
1665
1666 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001667 if (mActiveAlerts.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001668 throw new IllegalStateException("iface " + iface + " already has alert");
1669 }
1670
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001671 try {
1672 // TODO: support alert shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001673 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001674 mActiveAlerts.put(iface, alertBytes);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001675 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001676 throw e.rethrowAsParcelableException();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001677 }
1678 }
1679 }
1680
1681 @Override
1682 public void removeInterfaceAlert(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001683 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001684
1685 // silently discard when control disabled
1686 // TODO: eventually migrate to be always enabled
1687 if (!mBandwidthControlEnabled) return;
1688
1689 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001690 if (!mActiveAlerts.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001691 // TODO: eventually consider throwing
1692 return;
1693 }
1694
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001695 try {
1696 // TODO: support alert shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001697 mConnector.execute("bandwidth", "removeinterfacealert", iface);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001698 mActiveAlerts.remove(iface);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001699 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001700 throw e.rethrowAsParcelableException();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001701 }
1702 }
1703 }
1704
1705 @Override
1706 public void setGlobalAlert(long alertBytes) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001707 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001708
1709 // silently discard when control disabled
1710 // TODO: eventually migrate to be always enabled
1711 if (!mBandwidthControlEnabled) return;
1712
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001713 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001714 mConnector.execute("bandwidth", "setglobalalert", alertBytes);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001715 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001716 throw e.rethrowAsParcelableException();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001717 }
1718 }
1719
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001720 private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001721 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001722
Jeff Sharkey350083e2011-06-29 10:45:16 -07001723 // silently discard when control disabled
1724 // TODO: eventually migrate to be always enabled
1725 if (!mBandwidthControlEnabled) return;
1726
Felipe Leme65be3022016-03-22 14:53:13 -07001727 final String chain = blacklist ? "naughtyapps" : "niceapps";
1728 final String suffix = enable ? "add" : "remove";
1729
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001730 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001731 boolean oldEnable;
1732 SparseBooleanArray quotaList;
1733 synchronized (mRulesLock) {
1734 quotaList = blacklist ? mUidRejectOnMetered : mUidAllowOnMetered;
1735 oldEnable = quotaList.get(uid, false);
1736 }
Felipe Leme65be3022016-03-22 14:53:13 -07001737 if (oldEnable == enable) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001738 // TODO: eventually consider throwing
1739 return;
1740 }
1741
Felipe Leme29e72ea2016-09-08 13:26:55 -07001742 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001743 try {
Felipe Leme65be3022016-03-22 14:53:13 -07001744 mConnector.execute("bandwidth", suffix + chain, uid);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001745 synchronized (mRulesLock) {
1746 if (enable) {
1747 quotaList.put(uid, true);
1748 } else {
1749 quotaList.delete(uid);
1750 }
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001751 }
1752 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001753 throw e.rethrowAsParcelableException();
Felipe Leme29e72ea2016-09-08 13:26:55 -07001754 } finally {
1755 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001756 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001757 }
1758 }
1759
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001760 @Override
Felipe Leme65be3022016-03-22 14:53:13 -07001761 public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001762 setUidOnMeteredNetworkList(uid, true, enable);
Felipe Leme65be3022016-03-22 14:53:13 -07001763 }
1764
1765 @Override
1766 public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001767 setUidOnMeteredNetworkList(uid, false, enable);
Felipe Leme65be3022016-03-22 14:53:13 -07001768 }
1769
1770 @Override
1771 public boolean setDataSaverModeEnabled(boolean enable) {
Sehee Parka9139bc2017-12-22 13:54:05 +09001772 mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
1773
Felipe Leme65be3022016-03-22 14:53:13 -07001774 if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
1775 synchronized (mQuotaLock) {
1776 if (mDataSaverMode == enable) {
1777 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
1778 return true;
1779 }
Felipe Leme29e72ea2016-09-08 13:26:55 -07001780 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
Felipe Leme65be3022016-03-22 14:53:13 -07001781 try {
1782 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
1783 if (changed) {
1784 mDataSaverMode = enable;
1785 } else {
1786 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
1787 }
1788 return changed;
1789 } catch (RemoteException e) {
1790 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
1791 return false;
Felipe Leme29e72ea2016-09-08 13:26:55 -07001792 } finally {
1793 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
Felipe Leme65be3022016-03-22 14:53:13 -07001794 }
1795 }
1796 }
1797
1798 @Override
Robin Lee17e61832016-05-09 13:46:28 +01001799 public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
1800 throws ServiceSpecificException {
1801 try {
1802 mNetdService.networkRejectNonSecureVpn(add, uidRanges);
1803 } catch (ServiceSpecificException e) {
1804 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1805 + ": netd command failed", e);
1806 throw e;
1807 } catch (RemoteException e) {
1808 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1809 + ": netd command failed", e);
1810 throw e.rethrowAsRuntimeException();
1811 }
1812 }
1813
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001814 private void applyUidCleartextNetworkPolicy(int uid, int policy) {
1815 final String policyString;
1816 switch (policy) {
1817 case StrictMode.NETWORK_POLICY_ACCEPT:
1818 policyString = "accept";
1819 break;
1820 case StrictMode.NETWORK_POLICY_LOG:
1821 policyString = "log";
1822 break;
1823 case StrictMode.NETWORK_POLICY_REJECT:
1824 policyString = "reject";
1825 break;
1826 default:
1827 throw new IllegalArgumentException("Unknown policy " + policy);
1828 }
1829
1830 try {
1831 mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString);
1832 mUidCleartextPolicy.put(uid, policy);
1833 } catch (NativeDaemonConnectorException e) {
1834 throw e.rethrowAsParcelableException();
1835 }
1836 }
1837
Robin Lee17e61832016-05-09 13:46:28 +01001838 @Override
Jeff Sharkey605eb792014-11-04 13:34:06 -08001839 public void setUidCleartextNetworkPolicy(int uid, int policy) {
1840 if (Binder.getCallingUid() != uid) {
1841 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1842 }
1843
1844 synchronized (mQuotaLock) {
1845 final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1846 if (oldPolicy == policy) {
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001847 // This also ensures we won't needlessly apply an ACCEPT policy if we've just
1848 // enabled strict and the underlying iptables rules are empty.
Jeff Sharkey605eb792014-11-04 13:34:06 -08001849 return;
1850 }
1851
1852 if (!mStrictEnabled) {
1853 // Module isn't enabled yet; stash the requested policy away to
1854 // apply later once the daemon is connected.
1855 mUidCleartextPolicy.put(uid, policy);
1856 return;
1857 }
1858
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001859 // netd does not keep state on strict mode policies, and cannot replace a non-accept
1860 // policy without deleting it first. Rather than add state to netd, just always send
1861 // it an accept policy when switching between two non-accept policies.
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001862 // TODO: consider keeping state in netd so we can simplify this code.
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001863 if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT &&
1864 policy != StrictMode.NETWORK_POLICY_ACCEPT) {
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001865 applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001866 }
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001867
1868 applyUidCleartextNetworkPolicy(uid, policy);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001869 }
1870 }
1871
1872 @Override
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001873 public boolean isBandwidthControlEnabled() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001874 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001875 return mBandwidthControlEnabled;
1876 }
1877
1878 @Override
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001879 public NetworkStats getNetworkStatsUidDetail(int uid) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001880 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001881 try {
Dianne Hackbornd0c5b9a2014-02-21 16:19:05 -08001882 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null);
Jeff Sharkey9a2c2a62013-01-14 16:48:51 -08001883 } catch (IOException e) {
1884 throw new IllegalStateException(e);
1885 }
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001886 }
1887
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001888 private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
1889 @Override
Lorenzo Colittif1912ca2017-08-17 19:23:08 +09001890 public NetworkStats getTetherStats(int how) {
1891 // We only need to return per-UID stats. Per-device stats are already counted by
1892 // interface counters.
1893 if (how != STATS_PER_UID) {
1894 return new NetworkStats(SystemClock.elapsedRealtime(), 0);
1895 }
1896
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001897 final PersistableBundle bundle;
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001898 try {
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001899 bundle = mNetdService.tetherGetStats();
1900 } catch (RemoteException | ServiceSpecificException e) {
1901 throw new IllegalStateException("problem parsing tethering stats: ", e);
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001902 }
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001903
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001904 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
1905 bundle.size());
1906 final NetworkStats.Entry entry = new NetworkStats.Entry();
1907
1908 for (String iface : bundle.keySet()) {
1909 long[] statsArray = bundle.getLongArray(iface);
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001910 try {
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001911 entry.iface = iface;
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001912 entry.uid = UID_TETHERING;
1913 entry.set = SET_DEFAULT;
1914 entry.tag = TAG_NONE;
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001915 entry.rxBytes = statsArray[INetd.TETHER_STATS_RX_BYTES];
1916 entry.rxPackets = statsArray[INetd.TETHER_STATS_RX_PACKETS];
1917 entry.txBytes = statsArray[INetd.TETHER_STATS_TX_BYTES];
1918 entry.txPackets = statsArray[INetd.TETHER_STATS_TX_PACKETS];
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001919 stats.combineValues(entry);
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001920 } catch (ArrayIndexOutOfBoundsException e) {
1921 throw new IllegalStateException("invalid tethering stats for " + iface, e);
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001922 }
1923 }
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001924
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001925 return stats;
1926 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001927
1928 @Override
1929 public void setInterfaceQuota(String iface, long quotaBytes) {
1930 // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
1931 }
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001932 }
1933
1934 @Override
Lorenzo Colittif1912ca2017-08-17 19:23:08 +09001935 public NetworkStats getNetworkStatsTethering(int how) {
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001936 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1937
1938 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1939 synchronized (mTetheringStatsProviders) {
1940 for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
1941 try {
Lorenzo Colittif1912ca2017-08-17 19:23:08 +09001942 stats.combineAllValues(provider.getTetherStats(how));
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001943 } catch (RemoteException e) {
1944 Log.e(TAG, "Problem reading tethering stats from " +
1945 mTetheringStatsProviders.get(provider) + ": " + e);
1946 }
1947 }
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001948 }
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001949 return stats;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001950 }
1951
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001952 @Override
Pierre Imai8e48e672016-04-21 13:30:43 +09001953 public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) {
1954 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1955
Erik Kline4d092232017-10-30 15:29:44 +09001956 final ContentResolver cr = mContext.getContentResolver();
Pierre Imai8e48e672016-04-21 13:30:43 +09001957
Erik Kline4d092232017-10-30 15:29:44 +09001958 int sampleValidity = Settings.Global.getInt(cr,
Pierre Imai8e48e672016-04-21 13:30:43 +09001959 Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
1960 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
1961 if (sampleValidity < 0 || sampleValidity > 65535) {
1962 Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" +
1963 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
1964 sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
1965 }
1966
Erik Kline4d092232017-10-30 15:29:44 +09001967 int successThreshold = Settings.Global.getInt(cr,
Pierre Imai8e48e672016-04-21 13:30:43 +09001968 Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
1969 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
1970 if (successThreshold < 0 || successThreshold > 100) {
1971 Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" +
1972 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
1973 successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
1974 }
1975
Erik Kline4d092232017-10-30 15:29:44 +09001976 int minSamples = Settings.Global.getInt(cr,
Pierre Imai8e48e672016-04-21 13:30:43 +09001977 Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
Erik Kline4d092232017-10-30 15:29:44 +09001978 int maxSamples = Settings.Global.getInt(cr,
Pierre Imai8e48e672016-04-21 13:30:43 +09001979 Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
1980 if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) {
1981 Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples +
1982 "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
1983 DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
1984 minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
1985 maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
1986 }
1987
1988 final String[] domainStrs = domains == null ? new String[0] : domains.split(" ");
1989 final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples };
Erik Kline4d092232017-10-30 15:29:44 +09001990 final boolean useTls = shouldUseTls(cr);
1991 // TODO: Populate tlsHostname once it's decided how the hostname's IP
1992 // addresses will be resolved:
1993 //
1994 // [1] network-provided DNS servers are included here with the
1995 // hostname and netd will use the network-provided servers to
1996 // resolve the hostname and fix up its internal structures, or
1997 //
1998 // [2] network-provided DNS servers are included here without the
1999 // hostname, the ConnectivityService layer resolves the given
2000 // hostname, and then reconfigures netd with this information.
2001 //
2002 // In practice, there will always be a need for ConnectivityService or
2003 // the captive portal app to use the network-provided services to make
2004 // some queries. This argues in favor of [1], in concert with another
2005 // mechanism, perhaps setting a high bit in the netid, to indicate
2006 // via existing DNS APIs which set of servers (network-provided or
2007 // non-network-provided private DNS) should be queried.
Ben Schwartz6ec28df2017-10-02 13:08:06 -04002008 final String tlsHostname = "";
2009 final String[] tlsFingerprints = new String[0];
Pierre Imai8e48e672016-04-21 13:30:43 +09002010 try {
Ben Schwartz6ec28df2017-10-02 13:08:06 -04002011 mNetdService.setResolverConfiguration(netId, servers, domainStrs, params,
2012 useTls, tlsHostname, tlsFingerprints);
Pierre Imai8e48e672016-04-21 13:30:43 +09002013 } catch (RemoteException e) {
2014 throw new RuntimeException(e);
2015 }
2016 }
2017
Erik Kline4d092232017-10-30 15:29:44 +09002018 private static boolean shouldUseTls(ContentResolver cr) {
2019 String privateDns = Settings.Global.getString(cr, Settings.Global.PRIVATE_DNS_MODE);
2020 if (TextUtils.isEmpty(privateDns)) {
2021 privateDns = PRIVATE_DNS_DEFAULT_MODE;
2022 }
2023 return privateDns.equals(PRIVATE_DNS_MODE_OPPORTUNISTIC) ||
2024 privateDns.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
2025 }
2026
Pierre Imai8e48e672016-04-21 13:30:43 +09002027 @Override
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002028 public void addVpnUidRanges(int netId, UidRange[] ranges) {
Chad Brubaker3277620a2013-06-12 13:37:30 -07002029 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002030 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2031 argv[0] = "users";
2032 argv[1] = "add";
2033 argv[2] = netId;
2034 int argc = 3;
2035 // Avoid overly long commands by limiting number of UID ranges per command.
2036 for (int i = 0; i < ranges.length; i++) {
2037 argv[argc++] = ranges[i].toString();
2038 if (i == (ranges.length - 1) || argc == argv.length) {
2039 try {
2040 mConnector.execute("network", Arrays.copyOf(argv, argc));
2041 } catch (NativeDaemonConnectorException e) {
2042 throw e.rethrowAsParcelableException();
2043 }
2044 argc = 3;
2045 }
Chad Brubaker3277620a2013-06-12 13:37:30 -07002046 }
2047 }
2048
2049 @Override
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002050 public void removeVpnUidRanges(int netId, UidRange[] ranges) {
Chad Brubaker3277620a2013-06-12 13:37:30 -07002051 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002052 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2053 argv[0] = "users";
2054 argv[1] = "remove";
2055 argv[2] = netId;
2056 int argc = 3;
2057 // Avoid overly long commands by limiting number of UID ranges per command.
2058 for (int i = 0; i < ranges.length; i++) {
2059 argv[argc++] = ranges[i].toString();
2060 if (i == (ranges.length - 1) || argc == argv.length) {
2061 try {
2062 mConnector.execute("network", Arrays.copyOf(argv, argc));
2063 } catch (NativeDaemonConnectorException e) {
2064 throw e.rethrowAsParcelableException();
2065 }
2066 argc = 3;
2067 }
Chad Brubakercca54c42013-06-27 17:41:38 -07002068 }
2069 }
2070
2071 @Override
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002072 public void setFirewallEnabled(boolean enabled) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07002073 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002074 try {
Amith Yamasani15e472352015-04-24 19:06:07 -07002075 mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist");
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002076 mFirewallEnabled = enabled;
2077 } catch (NativeDaemonConnectorException e) {
2078 throw e.rethrowAsParcelableException();
2079 }
2080 }
2081
2082 @Override
2083 public boolean isFirewallEnabled() {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07002084 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002085 return mFirewallEnabled;
2086 }
2087
2088 @Override
Jeff Sharkey2c092982012-08-24 11:44:40 -07002089 public void setFirewallInterfaceRule(String iface, boolean allow) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07002090 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002091 Preconditions.checkState(mFirewallEnabled);
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002092 final String rule = allow ? "allow" : "deny";
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002093 try {
2094 mConnector.execute("firewall", "set_interface_rule", iface, rule);
2095 } catch (NativeDaemonConnectorException e) {
2096 throw e.rethrowAsParcelableException();
2097 }
2098 }
2099
Lorenzo Colitti3fef7232016-04-29 18:00:03 +09002100 private void closeSocketsForFirewallChainLocked(int chain, String chainName) {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002101 // UID ranges to close sockets on.
2102 UidRange[] ranges;
2103 // UID ranges whose sockets we won't touch.
2104 int[] exemptUids;
2105
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002106 int numUids = 0;
2107
2108 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
2109 // Close all sockets on all non-system UIDs...
2110 ranges = new UidRange[] {
2111 // TODO: is there a better way of finding all existing users? If so, we could
2112 // specify their ranges here.
2113 new UidRange(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
2114 };
2115 // ... except for the UIDs that have allow rules.
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002116 synchronized (mRulesLock) {
2117 final SparseIntArray rules = getUidFirewallRulesLR(chain);
2118 exemptUids = new int[rules.size()];
2119 for (int i = 0; i < exemptUids.length; i++) {
2120 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
2121 exemptUids[numUids] = rules.keyAt(i);
2122 numUids++;
2123 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002124 }
2125 }
2126 // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
2127 // But the code does not guarantee this in any way, and at least in one case - if we add
2128 // a UID rule to the firewall, and then disable the firewall - the chains can contain
2129 // the wrong type of rule. In this case, don't close connections that we shouldn't.
2130 //
2131 // TODO: tighten up this code by ensuring we never set the wrong type of rule, and
2132 // fix setFirewallEnabled to grab mQuotaLock and clear rules.
2133 if (numUids != exemptUids.length) {
2134 exemptUids = Arrays.copyOf(exemptUids, numUids);
2135 }
2136 } else {
2137 // Close sockets for every UID that has a deny rule...
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002138 synchronized (mRulesLock) {
2139 final SparseIntArray rules = getUidFirewallRulesLR(chain);
2140 ranges = new UidRange[rules.size()];
2141 for (int i = 0; i < ranges.length; i++) {
2142 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_DENY) {
2143 int uid = rules.keyAt(i);
2144 ranges[numUids] = new UidRange(uid, uid);
2145 numUids++;
2146 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002147 }
2148 }
2149 // As above; usually numUids == ranges.length, but not always.
2150 if (numUids != ranges.length) {
2151 ranges = Arrays.copyOf(ranges, numUids);
2152 }
2153 // ... with no exceptions.
2154 exemptUids = new int[0];
2155 }
2156
2157 try {
2158 mNetdService.socketDestroy(ranges, exemptUids);
2159 } catch(RemoteException | ServiceSpecificException e) {
2160 Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e);
2161 }
2162 }
2163
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002164 @Override
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002165 public void setFirewallChainEnabled(int chain, boolean enable) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07002166 enforceSystemUid();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002167 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002168 synchronized (mRulesLock) {
2169 if (getFirewallChainState(chain) == enable) {
2170 // All is the same, nothing to do. This relies on the fact that netd has child
2171 // chains default detached.
2172 return;
2173 }
2174 setFirewallChainState(chain, enable);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002175 }
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002176
2177 final String operation = enable ? "enable_chain" : "disable_chain";
Lorenzo Colitti3fef7232016-04-29 18:00:03 +09002178 final String chainName;
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002179 switch(chain) {
2180 case FIREWALL_CHAIN_STANDBY:
2181 chainName = FIREWALL_CHAIN_NAME_STANDBY;
2182 break;
2183 case FIREWALL_CHAIN_DOZABLE:
2184 chainName = FIREWALL_CHAIN_NAME_DOZABLE;
2185 break;
2186 case FIREWALL_CHAIN_POWERSAVE:
2187 chainName = FIREWALL_CHAIN_NAME_POWERSAVE;
2188 break;
2189 default:
2190 throw new IllegalArgumentException("Bad child chain: " + chain);
2191 }
2192
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002193 try {
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002194 mConnector.execute("firewall", operation, chainName);
2195 } catch (NativeDaemonConnectorException e) {
2196 throw e.rethrowAsParcelableException();
2197 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002198
2199 // Close any sockets that were opened by the affected UIDs. This has to be done after
2200 // disabling network connectivity, in case they react to the socket close by reopening
2201 // the connection and race with the iptables commands that enable the firewall. All
2202 // whitelist and blacklist chains allow RSTs through.
2203 if (enable) {
2204 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
Lorenzo Colitti3fef7232016-04-29 18:00:03 +09002205 closeSocketsForFirewallChainLocked(chain, chainName);
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002206 }
Amith Yamasani15e472352015-04-24 19:06:07 -07002207 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002208 }
2209
2210 private int getFirewallType(int chain) {
2211 switch (chain) {
2212 case FIREWALL_CHAIN_STANDBY:
2213 return FIREWALL_TYPE_BLACKLIST;
2214 case FIREWALL_CHAIN_DOZABLE:
2215 return FIREWALL_TYPE_WHITELIST;
Felipe Leme011b98f2016-02-10 17:28:31 -08002216 case FIREWALL_CHAIN_POWERSAVE:
2217 return FIREWALL_TYPE_WHITELIST;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002218 default:
2219 return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
2220 }
2221 }
2222
2223 @Override
2224 public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
2225 enforceSystemUid();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002226 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002227 synchronized (mRulesLock) {
2228 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
2229 SparseIntArray newRules = new SparseIntArray();
2230 // apply new set of rules
2231 for (int index = uids.length - 1; index >= 0; --index) {
2232 int uid = uids[index];
2233 int rule = rules[index];
2234 updateFirewallUidRuleLocked(chain, uid, rule);
2235 newRules.put(uid, rule);
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002236 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002237 // collect the rules to remove.
2238 SparseIntArray rulesToRemove = new SparseIntArray();
2239 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
2240 int uid = uidFirewallRules.keyAt(index);
2241 if (newRules.indexOfKey(uid) < 0) {
2242 rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
2243 }
2244 }
2245 // remove dead rules
2246 for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
2247 int uid = rulesToRemove.keyAt(index);
2248 updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
2249 }
Felipe Lemea701cad2016-05-12 09:58:14 -07002250 }
2251 try {
2252 switch (chain) {
2253 case FIREWALL_CHAIN_DOZABLE:
2254 mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
2255 break;
2256 case FIREWALL_CHAIN_STANDBY:
2257 mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
2258 break;
2259 case FIREWALL_CHAIN_POWERSAVE:
2260 mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
2261 break;
2262 case FIREWALL_CHAIN_NONE:
2263 default:
2264 Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
2265 }
2266 } catch (RemoteException e) {
2267 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002268 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002269 }
2270 }
2271
2272 @Override
2273 public void setFirewallUidRule(int chain, int uid, int rule) {
2274 enforceSystemUid();
Felipe Lemea701cad2016-05-12 09:58:14 -07002275 synchronized (mQuotaLock) {
2276 setFirewallUidRuleLocked(chain, uid, rule);
2277 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002278 }
2279
Felipe Lemea701cad2016-05-12 09:58:14 -07002280 private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
2281 if (updateFirewallUidRuleLocked(chain, uid, rule)) {
Amith Yamasani15e472352015-04-24 19:06:07 -07002282 try {
Felipe Lemea701cad2016-05-12 09:58:14 -07002283 mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
2284 getFirewallRuleName(chain, rule));
Amith Yamasani15e472352015-04-24 19:06:07 -07002285 } catch (NativeDaemonConnectorException e) {
2286 throw e.rethrowAsParcelableException();
2287 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002288 }
2289 }
2290
Felipe Lemea701cad2016-05-12 09:58:14 -07002291 // TODO: now that netd supports batching, NMS should not keep these data structures anymore...
2292 private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002293 synchronized (mRulesLock) {
2294 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
Felipe Lemea701cad2016-05-12 09:58:14 -07002295
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002296 final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
2297 if (DBG) {
2298 Slog.d(TAG, "oldRule = " + oldUidFirewallRule
2299 + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain);
2300 }
2301 if (oldUidFirewallRule == rule) {
2302 if (DBG) Slog.d(TAG, "!!!!! Skipping change");
2303 // TODO: eventually consider throwing
2304 return false;
2305 }
Felipe Lemea701cad2016-05-12 09:58:14 -07002306
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002307 String ruleName = getFirewallRuleName(chain, rule);
2308 String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
Felipe Lemea701cad2016-05-12 09:58:14 -07002309
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002310 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
2311 uidFirewallRules.delete(uid);
2312 } else {
2313 uidFirewallRules.put(uid, rule);
2314 }
2315 return !ruleName.equals(oldRuleName);
Felipe Lemea701cad2016-05-12 09:58:14 -07002316 }
Felipe Lemea701cad2016-05-12 09:58:14 -07002317 }
2318
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07002319 private @NonNull String getFirewallRuleName(int chain, int rule) {
2320 String ruleName;
2321 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
2322 if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
2323 ruleName = "allow";
2324 } else {
2325 ruleName = "deny";
2326 }
2327 } else { // Blacklist mode
2328 if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
2329 ruleName = "deny";
2330 } else {
2331 ruleName = "allow";
2332 }
2333 }
2334 return ruleName;
2335 }
2336
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002337 private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) {
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002338 switch (chain) {
2339 case FIREWALL_CHAIN_STANDBY:
2340 return mUidFirewallStandbyRules;
2341 case FIREWALL_CHAIN_DOZABLE:
2342 return mUidFirewallDozableRules;
Felipe Leme011b98f2016-02-10 17:28:31 -08002343 case FIREWALL_CHAIN_POWERSAVE:
2344 return mUidFirewallPowerSaveRules;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002345 case FIREWALL_CHAIN_NONE:
2346 return mUidFirewallRules;
2347 default:
2348 throw new IllegalArgumentException("Unknown chain:" + chain);
2349 }
2350 }
2351
2352 public @NonNull String getFirewallChainName(int chain) {
2353 switch (chain) {
2354 case FIREWALL_CHAIN_STANDBY:
2355 return FIREWALL_CHAIN_NAME_STANDBY;
2356 case FIREWALL_CHAIN_DOZABLE:
2357 return FIREWALL_CHAIN_NAME_DOZABLE;
Felipe Leme011b98f2016-02-10 17:28:31 -08002358 case FIREWALL_CHAIN_POWERSAVE:
2359 return FIREWALL_CHAIN_NAME_POWERSAVE;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002360 case FIREWALL_CHAIN_NONE:
2361 return FIREWALL_CHAIN_NAME_NONE;
2362 default:
2363 throw new IllegalArgumentException("Unknown chain:" + chain);
2364 }
2365 }
2366
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07002367 private static void enforceSystemUid() {
2368 final int uid = Binder.getCallingUid();
2369 if (uid != Process.SYSTEM_UID) {
2370 throw new SecurityException("Only available to AID_SYSTEM");
2371 }
2372 }
2373
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002374 @Override
Lorenzo Colitti79751842013-02-28 16:16:03 +09002375 public void startClatd(String interfaceName) throws IllegalStateException {
2376 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2377
2378 try {
2379 mConnector.execute("clatd", "start", interfaceName);
2380 } catch (NativeDaemonConnectorException e) {
2381 throw e.rethrowAsParcelableException();
2382 }
2383 }
2384
2385 @Override
Lorenzo Colitti95439462014-10-09 13:44:48 +09002386 public void stopClatd(String interfaceName) throws IllegalStateException {
Lorenzo Colitti79751842013-02-28 16:16:03 +09002387 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2388
2389 try {
Lorenzo Colitti95439462014-10-09 13:44:48 +09002390 mConnector.execute("clatd", "stop", interfaceName);
Lorenzo Colitti79751842013-02-28 16:16:03 +09002391 } catch (NativeDaemonConnectorException e) {
2392 throw e.rethrowAsParcelableException();
2393 }
2394 }
2395
2396 @Override
Lorenzo Colitti95439462014-10-09 13:44:48 +09002397 public boolean isClatdStarted(String interfaceName) {
Lorenzo Colitti79751842013-02-28 16:16:03 +09002398 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2399
2400 final NativeDaemonEvent event;
2401 try {
Lorenzo Colitti95439462014-10-09 13:44:48 +09002402 event = mConnector.execute("clatd", "status", interfaceName);
Lorenzo Colitti79751842013-02-28 16:16:03 +09002403 } catch (NativeDaemonConnectorException e) {
2404 throw e.rethrowAsParcelableException();
2405 }
2406
2407 event.checkCode(ClatdStatusResult);
2408 return event.getMessage().endsWith("started");
2409 }
2410
Dianne Hackborn77b987f2014-02-26 16:20:52 -08002411 @Override
2412 public void registerNetworkActivityListener(INetworkActivityListener listener) {
2413 mNetworkActivityListeners.register(listener);
2414 }
2415
2416 @Override
2417 public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
2418 mNetworkActivityListeners.unregister(listener);
2419 }
2420
2421 @Override
2422 public boolean isNetworkActive() {
2423 synchronized (mNetworkActivityListeners) {
2424 return mNetworkActive || mActiveIdleTimers.isEmpty();
2425 }
2426 }
2427
2428 private void reportNetworkActive() {
2429 final int length = mNetworkActivityListeners.beginBroadcast();
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07002430 try {
2431 for (int i = 0; i < length; i++) {
2432 try {
2433 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
Felipe Leme03e689d2016-03-02 16:17:38 -08002434 } catch (RemoteException | RuntimeException e) {
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07002435 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08002436 }
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07002437 } finally {
2438 mNetworkActivityListeners.finishBroadcast();
Dianne Hackborn77b987f2014-02-26 16:20:52 -08002439 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08002440 }
2441
Mattias Falk8b47b362011-08-23 14:15:13 +02002442 /** {@inheritDoc} */
Jeff Sharkey7b4596f2013-02-25 10:55:29 -08002443 @Override
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07002444 public void monitor() {
2445 if (mConnector != null) {
2446 mConnector.monitor();
2447 }
2448 }
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002449
2450 @Override
2451 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06002452 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002453
Robert Greenwalt470fd722012-01-18 12:51:15 -08002454 pw.println("NetworkManagementService NativeDaemonConnector Log:");
2455 mConnector.dump(fd, pw, args);
2456 pw.println();
2457
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002458 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07002459 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
2460 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
2461 pw.print("mNetworkActive="); pw.println(mNetworkActive);
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002462
2463 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07002464 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
2465 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
Felipe Leme65be3022016-03-22 14:53:13 -07002466 pw.print("Data saver mode: "); pw.println(mDataSaverMode);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002467 synchronized (mRulesLock) {
2468 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
2469 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
2470 }
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002471 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002472
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002473 synchronized (mRulesLock) {
Felipe Leme011b98f2016-02-10 17:28:31 -08002474 dumpUidFirewallRule(pw, "", mUidFirewallRules);
Amith Yamasani15e472352015-04-24 19:06:07 -07002475
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002476 pw.print("UID firewall standby chain enabled: "); pw.println(
2477 getFirewallChainState(FIREWALL_CHAIN_STANDBY));
Felipe Leme011b98f2016-02-10 17:28:31 -08002478 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002479
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002480 pw.print("UID firewall dozable chain enabled: "); pw.println(
2481 getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
Felipe Leme011b98f2016-02-10 17:28:31 -08002482 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
Felipe Leme011b98f2016-02-10 17:28:31 -08002483
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002484 pw.println("UID firewall powersave chain enabled: " +
2485 getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
Felipe Leme011b98f2016-02-10 17:28:31 -08002486 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07002487 }
2488
Dianne Hackborn77b987f2014-02-26 16:20:52 -08002489 synchronized (mIdleTimerLock) {
2490 pw.println("Idle timers:");
2491 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
2492 pw.print(" "); pw.print(ent.getKey()); pw.println(":");
2493 IdleTimerParams params = ent.getValue();
2494 pw.print(" timeout="); pw.print(params.timeout);
2495 pw.print(" type="); pw.print(params.type);
2496 pw.print(" networkCount="); pw.println(params.networkCount);
2497 }
2498 }
2499
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07002500 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
Felipe Leme65be3022016-03-22 14:53:13 -07002501 pw.print("Netd service status: " );
2502 if (mNetdService == null) {
2503 pw.println("disconnected");
2504 } else {
2505 try {
2506 final boolean alive = mNetdService.isAlive();
2507 pw.println(alive ? "alive": "dead");
2508 } catch (RemoteException e) {
2509 pw.println("unreachable");
2510 }
2511 }
2512 }
2513
2514 private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
2515 pw.print("UID bandwith control ");
2516 pw.print(name);
2517 pw.print(" rule: [");
2518 final int size = list.size();
2519 for (int i = 0; i < size; i++) {
2520 pw.print(list.keyAt(i));
2521 if (i < size - 1) pw.print(",");
2522 }
2523 pw.println("]");
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002524 }
Robert Greenwalt9ba9c582014-03-19 17:56:12 -07002525
Felipe Leme011b98f2016-02-10 17:28:31 -08002526 private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002527 pw.print("UID firewall ");
Felipe Leme011b98f2016-02-10 17:28:31 -08002528 pw.print(name);
2529 pw.print(" rule: [");
2530 final int size = rules.size();
2531 for (int i = 0; i < size; i++) {
2532 pw.print(rules.keyAt(i));
2533 pw.print(":");
2534 pw.print(rules.valueAt(i));
2535 if (i < size - 1) pw.print(",");
2536 }
2537 pw.println("]");
2538 }
2539
Robert Greenwalt568891d2014-04-04 13:38:00 -07002540 @Override
Paul Jensen487ffe72015-07-24 15:57:11 -04002541 public void createPhysicalNetwork(int netId, String permission) {
Robert Greenwalt9ba9c582014-03-19 17:56:12 -07002542 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2543
2544 try {
Paul Jensen487ffe72015-07-24 15:57:11 -04002545 if (permission != null) {
2546 mConnector.execute("network", "create", netId, permission);
2547 } else {
2548 mConnector.execute("network", "create", netId);
2549 }
Robert Greenwalt9ba9c582014-03-19 17:56:12 -07002550 } catch (NativeDaemonConnectorException e) {
2551 throw e.rethrowAsParcelableException();
2552 }
2553 }
2554
Robert Greenwalt568891d2014-04-04 13:38:00 -07002555 @Override
Sreeram Ramachandran8cd33ed2014-07-23 15:23:15 -07002556 public void createVirtualNetwork(int netId, boolean hasDNS, boolean secure) {
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002557 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2558
2559 try {
Sreeram Ramachandran8cd33ed2014-07-23 15:23:15 -07002560 mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0",
2561 secure ? "1" : "0");
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002562 } catch (NativeDaemonConnectorException e) {
2563 throw e.rethrowAsParcelableException();
2564 }
2565 }
2566
2567 @Override
Robert Greenwalt9ba9c582014-03-19 17:56:12 -07002568 public void removeNetwork(int netId) {
2569 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2570
2571 try {
2572 mConnector.execute("network", "destroy", netId);
2573 } catch (NativeDaemonConnectorException e) {
2574 throw e.rethrowAsParcelableException();
2575 }
2576 }
Robert Greenwalt568891d2014-04-04 13:38:00 -07002577
2578 @Override
Paul Jensen992f2522014-04-28 10:33:11 -04002579 public void addInterfaceToNetwork(String iface, int netId) {
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002580 modifyInterfaceInNetwork("add", "" + netId, iface);
Paul Jensen992f2522014-04-28 10:33:11 -04002581 }
2582
2583 @Override
2584 public void removeInterfaceFromNetwork(String iface, int netId) {
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002585 modifyInterfaceInNetwork("remove", "" + netId, iface);
2586 }
Paul Jensen992f2522014-04-28 10:33:11 -04002587
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002588 private void modifyInterfaceInNetwork(String action, String netId, String iface) {
2589 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Paul Jensen992f2522014-04-28 10:33:11 -04002590 try {
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002591 mConnector.execute("network", "interface", action, netId, iface);
Paul Jensen992f2522014-04-28 10:33:11 -04002592 } catch (NativeDaemonConnectorException e) {
2593 throw e.rethrowAsParcelableException();
2594 }
2595 }
2596
2597 @Override
Robert Greenwalt913c8952014-04-07 17:36:35 -07002598 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
Robert Greenwalt568891d2014-04-04 13:38:00 -07002599 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2600
Sreeram Ramachandran03666c72014-07-19 23:21:46 -07002601 final Command cmd = new Command("network", "route", "legacy", uid, "add", netId);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002602
Sreeram Ramachandran1fbcb272014-05-22 16:30:48 -07002603 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -07002604 final LinkAddress la = routeInfo.getDestinationLinkAddress();
Robert Greenwalt568891d2014-04-04 13:38:00 -07002605 cmd.appendArg(routeInfo.getInterface());
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +09002606 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength());
Sreeram Ramachandran1fbcb272014-05-22 16:30:48 -07002607 if (routeInfo.hasGateway()) {
2608 cmd.appendArg(routeInfo.getGateway().getHostAddress());
2609 }
Robert Greenwalt568891d2014-04-04 13:38:00 -07002610
2611 try {
2612 mConnector.execute(cmd);
2613 } catch (NativeDaemonConnectorException e) {
2614 throw e.rethrowAsParcelableException();
2615 }
2616 }
2617
2618 @Override
Sreeram Ramachandranf047f2a2014-04-15 16:04:26 -07002619 public void setDefaultNetId(int netId) {
Robert Greenwalt568891d2014-04-04 13:38:00 -07002620 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2621
2622 try {
Sreeram Ramachandranf047f2a2014-04-15 16:04:26 -07002623 mConnector.execute("network", "default", "set", netId);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002624 } catch (NativeDaemonConnectorException e) {
2625 throw e.rethrowAsParcelableException();
2626 }
2627 }
2628
2629 @Override
2630 public void clearDefaultNetId() {
2631 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2632
2633 try {
2634 mConnector.execute("network", "default", "clear");
2635 } catch (NativeDaemonConnectorException e) {
2636 throw e.rethrowAsParcelableException();
2637 }
2638 }
2639
2640 @Override
Paul Jensen487ffe72015-07-24 15:57:11 -04002641 public void setNetworkPermission(int netId, String permission) {
2642 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2643
2644 try {
2645 if (permission != null) {
2646 mConnector.execute("network", "permission", "network", "set", permission, netId);
2647 } else {
2648 mConnector.execute("network", "permission", "network", "clear", netId);
2649 }
2650 } catch (NativeDaemonConnectorException e) {
2651 throw e.rethrowAsParcelableException();
2652 }
2653 }
2654
2655
2656 @Override
Sreeram Ramachandrane4a05af2014-09-24 09:16:19 -07002657 public void setPermission(String permission, int[] uids) {
Robert Greenwalt568891d2014-04-04 13:38:00 -07002658 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2659
Sreeram Ramachandrane4a05af2014-09-24 09:16:19 -07002660 Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND];
2661 argv[0] = "permission";
2662 argv[1] = "user";
2663 argv[2] = "set";
2664 argv[3] = permission;
2665 int argc = 4;
2666 // Avoid overly long commands by limiting number of UIDs per command.
2667 for (int i = 0; i < uids.length; ++i) {
2668 argv[argc++] = uids[i];
2669 if (i == uids.length - 1 || argc == argv.length) {
2670 try {
2671 mConnector.execute("network", Arrays.copyOf(argv, argc));
2672 } catch (NativeDaemonConnectorException e) {
2673 throw e.rethrowAsParcelableException();
2674 }
2675 argc = 4;
2676 }
Robert Greenwalt568891d2014-04-04 13:38:00 -07002677 }
2678 }
2679
2680 @Override
2681 public void clearPermission(int[] uids) {
2682 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2683
Sreeram Ramachandrane4a05af2014-09-24 09:16:19 -07002684 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2685 argv[0] = "permission";
2686 argv[1] = "user";
2687 argv[2] = "clear";
2688 int argc = 3;
2689 // Avoid overly long commands by limiting number of UIDs per command.
2690 for (int i = 0; i < uids.length; ++i) {
2691 argv[argc++] = uids[i];
2692 if (i == uids.length - 1 || argc == argv.length) {
2693 try {
2694 mConnector.execute("network", Arrays.copyOf(argv, argc));
2695 } catch (NativeDaemonConnectorException e) {
2696 throw e.rethrowAsParcelableException();
2697 }
2698 argc = 3;
2699 }
Robert Greenwalt568891d2014-04-04 13:38:00 -07002700 }
2701 }
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002702
2703 @Override
2704 public void allowProtect(int uid) {
2705 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2706
2707 try {
2708 mConnector.execute("network", "protect", "allow", uid);
2709 } catch (NativeDaemonConnectorException e) {
2710 throw e.rethrowAsParcelableException();
2711 }
2712 }
2713
2714 @Override
2715 public void denyProtect(int uid) {
2716 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2717
2718 try {
2719 mConnector.execute("network", "protect", "deny", uid);
2720 } catch (NativeDaemonConnectorException e) {
2721 throw e.rethrowAsParcelableException();
2722 }
2723 }
2724
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002725 @Override
2726 public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
2727 modifyInterfaceInNetwork("add", "local", iface);
2728
2729 for (RouteInfo route : routes) {
2730 if (!route.isDefaultRoute()) {
2731 modifyRoute("add", "local", route);
2732 }
2733 }
2734 }
2735
2736 @Override
2737 public void removeInterfaceFromLocalNetwork(String iface) {
2738 modifyInterfaceInNetwork("remove", "local", iface);
2739 }
Erik Kline6599ee82016-07-17 21:28:39 +09002740
2741 @Override
2742 public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
2743 int failures = 0;
2744
2745 for (RouteInfo route : routes) {
2746 try {
2747 modifyRoute("remove", "local", route);
2748 } catch (IllegalStateException e) {
2749 failures++;
2750 }
2751 }
2752
2753 return failures;
2754 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002755
Sudheer Shankab8f23162017-08-04 13:30:10 -07002756 @Override
2757 public boolean isNetworkRestricted(int uid) {
2758 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2759 return isNetworkRestrictedInternal(uid);
2760 }
2761
2762 private boolean isNetworkRestrictedInternal(int uid) {
2763 synchronized (mRulesLock) {
2764 if (getFirewallChainState(FIREWALL_CHAIN_STANDBY)
2765 && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) {
2766 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode");
2767 return true;
2768 }
2769 if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE)
2770 && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) {
2771 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode");
2772 return true;
2773 }
2774 if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)
2775 && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) {
2776 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
2777 return true;
2778 }
2779 if (mUidRejectOnMetered.get(uid)) {
2780 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
2781 + " in the background");
2782 return true;
2783 }
2784 if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) {
2785 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode");
2786 return true;
2787 }
2788 return false;
2789 }
2790 }
2791
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002792 private void setFirewallChainState(int chain, boolean state) {
2793 synchronized (mRulesLock) {
2794 mFirewallChainStates.put(chain, state);
2795 }
2796 }
2797
2798 private boolean getFirewallChainState(int chain) {
2799 synchronized (mRulesLock) {
2800 return mFirewallChainStates.get(chain);
2801 }
2802 }
2803
2804 @VisibleForTesting
2805 class LocalService extends NetworkManagementInternal {
2806 @Override
2807 public boolean isNetworkRestrictedForUid(int uid) {
Sudheer Shankab8f23162017-08-04 13:30:10 -07002808 return isNetworkRestrictedInternal(uid);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002809 }
2810 }
2811
2812 @VisibleForTesting
2813 Injector getInjector() {
2814 return new Injector();
2815 }
2816
2817 @VisibleForTesting
2818 class Injector {
2819 void setDataSaverMode(boolean dataSaverMode) {
2820 mDataSaverMode = dataSaverMode;
2821 }
2822
2823 void setFirewallChainState(int chain, boolean state) {
2824 NetworkManagementService.this.setFirewallChainState(chain, state);
2825 }
2826
2827 void setFirewallRule(int chain, int uid, int rule) {
2828 synchronized (mRulesLock) {
2829 getUidFirewallRulesLR(chain).put(uid, rule);
2830 }
2831 }
2832
2833 void setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable) {
2834 synchronized (mRulesLock) {
2835 if (blacklist) {
2836 mUidRejectOnMetered.put(uid, enable);
2837 } else {
2838 mUidAllowOnMetered.put(uid, enable);
2839 }
2840 }
2841 }
2842
2843 void reset() {
2844 synchronized (mRulesLock) {
2845 setDataSaverMode(false);
2846 final int[] chains = {
2847 FIREWALL_CHAIN_DOZABLE,
2848 FIREWALL_CHAIN_STANDBY,
2849 FIREWALL_CHAIN_POWERSAVE
2850 };
2851 for (int chain : chains) {
2852 setFirewallChainState(chain, false);
2853 getUidFirewallRulesLR(chain).clear();
2854 }
2855 mUidAllowOnMetered.clear();
2856 mUidRejectOnMetered.clear();
2857 }
2858 }
2859 }
San Mehat873f2142010-01-14 10:25:07 -08002860}