blob: 1f736502ae420d6cdbde9313c567231aeb96b526 [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
paulhu79ebe4f2019-12-06 16:45:38 +080019import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
Sehee Parka9139bc2017-12-22 13:54:05 +090020import static android.Manifest.permission.NETWORK_SETTINGS;
paulhu59148b72019-08-12 16:25:11 +080021import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
Jeff Sharkeyaf75c332011-11-18 12:41:12 -080022import static android.Manifest.permission.SHUTDOWN;
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +090023import static android.net.INetd.FIREWALL_BLACKLIST;
24import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
25import static android.net.INetd.FIREWALL_CHAIN_NONE;
26import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
27import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
28import static android.net.INetd.FIREWALL_RULE_ALLOW;
29import static android.net.INetd.FIREWALL_RULE_DENY;
30import static android.net.INetd.FIREWALL_WHITELIST;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070031import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
Felipe Leme011b98f2016-02-10 17:28:31 -080032import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070033import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070034import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070035import static android.net.NetworkStats.SET_DEFAULT;
Lorenzo Colittif1912ca2017-08-17 19:23:08 +090036import static android.net.NetworkStats.STATS_PER_UID;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070037import static android.net.NetworkStats.TAG_NONE;
Jeff Sharkeyae2c1812011-10-04 13:11:40 -070038import static android.net.TrafficStats.UID_TETHERING;
Lorenzo Colitti9307ca22019-01-12 01:54:23 +090039
Jeff Sharkeya63ba592011-07-19 23:47:12 -070040import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
Erik Klineb2cfdfb2017-01-18 20:54:14 +090041
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070042import android.annotation.NonNull;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080043import android.app.ActivityManager;
San Mehat873f2142010-01-14 10:25:07 -080044import android.content.Context;
Dianne Hackborn77b987f2014-02-26 16:20:52 -080045import android.net.ConnectivityManager;
Lorenzo Colitti58967ba2016-02-02 17:21:21 +090046import android.net.INetd;
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +090047import android.net.INetdUnsolicitedEventListener;
San Mehat4d02d002010-01-22 16:07:46 -080048import android.net.INetworkManagementEventObserver;
Lorenzo Colitti07f13042017-07-10 19:06:57 +090049import android.net.ITetheringStatsProvider;
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +090050import android.net.InetAddresses;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070051import android.net.InterfaceConfiguration;
Luke Huang14f75442018-08-15 19:22:54 +080052import android.net.InterfaceConfigurationParcel;
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +090053import android.net.IpPrefix;
Robert Greenwalted126402011-01-28 15:34:55 -080054import android.net.LinkAddress;
Lorenzo Colittib57edc52014-08-22 17:10:50 -070055import android.net.Network;
Amith Yamasani15e472352015-04-24 19:06:07 -070056import android.net.NetworkPolicyManager;
paulhu59148b72019-08-12 16:25:11 +080057import android.net.NetworkStack;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070058import android.net.NetworkStats;
Robert Greenwalted126402011-01-28 15:34:55 -080059import android.net.NetworkUtils;
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070060import android.net.RouteInfo;
Chiachang Wangafd43e42019-12-10 10:07:12 +080061import android.net.TetherConfigParcel;
Lorenzo Colitti9307ca22019-01-12 01:54:23 +090062import android.net.TetherStatsParcel;
Paul Jensen6bc2c2c2014-05-07 15:27:40 -040063import android.net.UidRange;
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +090064import android.net.UidRangeParcel;
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090065import android.net.util.NetdService;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070066import android.os.BatteryStats;
Jeff Sharkeyf56e2432012-09-06 17:54:29 -070067import android.os.Binder;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -070068import android.os.Handler;
Lorenzo Colittia0868002017-07-11 02:29:28 +090069import android.os.IBinder;
Dianne Hackborn77b987f2014-02-26 16:20:52 -080070import android.os.INetworkActivityListener;
San Mehat873f2142010-01-14 10:25:07 -080071import android.os.INetworkManagementService;
Jeff Sharkeyf56e2432012-09-06 17:54:29 -070072import android.os.Process;
Jeff Sharkey3df273e2011-12-15 15:47:12 -080073import android.os.RemoteCallbackList;
74import android.os.RemoteException;
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -070075import android.os.ServiceManager;
Lorenzo Colitti4cb42402016-04-24 12:52:00 +090076import android.os.ServiceSpecificException;
Jeff Sharkey605eb792014-11-04 13:34:06 -080077import android.os.StrictMode;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070078import android.os.SystemClock;
Marco Nelissen62dbb222010-02-18 10:56:30 -080079import android.os.SystemProperties;
Felipe Leme29e72ea2016-09-08 13:26:55 -070080import android.os.Trace;
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -070081import android.telephony.DataConnectionRealTimeInfo;
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +090082import android.text.TextUtils;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080083import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080084import android.util.Slog;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -070085import android.util.SparseBooleanArray;
Jeff Sharkey605eb792014-11-04 13:34:06 -080086import android.util.SparseIntArray;
Bookatz0b028b12018-05-31 16:51:17 -070087import android.util.StatsLog;
San Mehat873f2142010-01-14 10:25:07 -080088
Jeff Sharkey605eb792014-11-04 13:34:06 -080089import com.android.internal.annotations.GuardedBy;
Sudheer Shanka62f5c172017-03-17 16:25:55 -070090import com.android.internal.annotations.VisibleForTesting;
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -070091import com.android.internal.app.IBatteryStats;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060092import com.android.internal.util.DumpUtils;
Jeff Sharkey605eb792014-11-04 13:34:06 -080093import com.android.internal.util.HexDump;
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -070094import com.android.internal.util.Preconditions;
Lorenzo Colitti9307ca22019-01-12 01:54:23 +090095
Jeff Sharkeyb24a7852012-05-01 15:19:37 -070096import com.google.android.collect.Maps;
Jeff Sharkey4414cea2011-06-24 17:05:24 -070097
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070098import java.io.BufferedReader;
99import java.io.DataInputStream;
Jeff Sharkey47eb1022011-08-25 17:48:52 -0700100import java.io.FileDescriptor;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700101import java.io.FileInputStream;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700102import java.io.IOException;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700103import java.io.InputStreamReader;
Jeff Sharkey47eb1022011-08-25 17:48:52 -0700104import java.io.PrintWriter;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -0700105import java.net.InetAddress;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700106import java.net.InterfaceAddress;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -0700107import java.util.ArrayList;
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400108import java.util.Arrays;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700109import java.util.HashMap;
jiaguo1da35f72014-01-09 16:39:59 +0800110import java.util.List;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700111import java.util.Map;
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +0000112import java.util.Objects;
San Mehat873f2142010-01-14 10:25:07 -0800113
114/**
115 * @hide
116 */
Luke Huang909b31a2019-03-16 21:21:16 +0800117public class NetworkManagementService extends INetworkManagementService.Stub {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900118
119 /**
120 * Helper class that encapsulates NetworkManagementService dependencies and makes them
121 * easier to mock in unit tests.
122 */
123 static class SystemServices {
124 public IBinder getService(String name) {
125 return ServiceManager.getService(name);
126 }
127 public void registerLocalService(NetworkManagementInternal nmi) {
128 LocalServices.addService(NetworkManagementInternal.class, nmi);
129 }
130 public INetd getNetd() {
131 return NetdService.get();
132 }
133 }
134
Amith Yamasani15e472352015-04-24 19:06:07 -0700135 private static final String TAG = "NetworkManagement";
136 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
Kenny Root305bcbf2010-09-03 07:56:38 -0700137
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400138 private static final int MAX_UID_RANGES_PER_COMMAND = 10;
139
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700140 /**
141 * Name representing {@link #setGlobalAlert(long)} limit when delivered to
142 * {@link INetworkManagementEventObserver#limitReached(String, String)}.
143 */
144 public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
145
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700146 static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
147
Luke Huang8a462ec2018-08-24 20:33:16 +0800148 static final boolean MODIFY_OPERATION_ADD = true;
149 static final boolean MODIFY_OPERATION_REMOVE = false;
150
San Mehat873f2142010-01-14 10:25:07 -0800151 /**
152 * Binder context for this service
153 */
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700154 private final Context mContext;
San Mehat873f2142010-01-14 10:25:07 -0800155
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700156 private final Handler mDaemonHandler;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700157
Lorenzo Colittia0868002017-07-11 02:29:28 +0900158 private final SystemServices mServices;
159
Lorenzo Colitti58967ba2016-02-02 17:21:21 +0900160 private INetd mNetdService;
161
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900162 private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener;
Luke Huangd290dd52018-09-04 17:08:18 +0800163
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800164 private IBatteryStats mBatteryStats;
165
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900166 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
167 new RemoteCallbackList<>();
168
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900169 @GuardedBy("mTetheringStatsProviders")
170 private final HashMap<ITetheringStatsProvider, String>
171 mTetheringStatsProviders = Maps.newHashMap();
172
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700173 /**
174 * If both locks need to be held, then they should be obtained in the order:
175 * first {@link #mQuotaLock} and then {@link #mRulesLock}.
176 */
Andrew Scull45f533c2017-05-19 15:37:20 +0100177 private final Object mQuotaLock = new Object();
Andrew Scull519291f2017-05-23 13:11:03 +0100178 private final Object mRulesLock = new Object();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800179
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700180 /** Set of interfaces with active quotas. */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800181 @GuardedBy("mQuotaLock")
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700182 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700183 /** Set of interfaces with active alerts. */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800184 @GuardedBy("mQuotaLock")
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700185 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
Felipe Leme65be3022016-03-22 14:53:13 -0700186 /** Set of UIDs blacklisted on metered networks. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700187 @GuardedBy("mRulesLock")
Felipe Leme65be3022016-03-22 14:53:13 -0700188 private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
189 /** Set of UIDs whitelisted on metered networks. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700190 @GuardedBy("mRulesLock")
Felipe Leme65be3022016-03-22 14:53:13 -0700191 private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800192 /** Set of UIDs with cleartext penalties. */
193 @GuardedBy("mQuotaLock")
194 private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
Amith Yamasani15e472352015-04-24 19:06:07 -0700195 /** Set of UIDs that are to be blocked/allowed by firewall controller. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700196 @GuardedBy("mRulesLock")
Amith Yamasani15e472352015-04-24 19:06:07 -0700197 private SparseIntArray mUidFirewallRules = new SparseIntArray();
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700198 /**
199 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
200 * to application idles.
201 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700202 @GuardedBy("mRulesLock")
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700203 private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
204 /**
205 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
206 * to device idles.
207 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700208 @GuardedBy("mRulesLock")
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700209 private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
Felipe Leme011b98f2016-02-10 17:28:31 -0800210 /**
211 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
212 * to device on power-save mode.
213 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700214 @GuardedBy("mRulesLock")
Felipe Leme011b98f2016-02-10 17:28:31 -0800215 private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -0700216 /** Set of states for the child firewall chains. True if the chain is active. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700217 @GuardedBy("mRulesLock")
Xiaohui Chen8dca36d2015-06-19 12:44:59 -0700218 final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700219
Felipe Leme65be3022016-03-22 14:53:13 -0700220 @GuardedBy("mQuotaLock")
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700221 private volatile boolean mDataSaverMode;
Felipe Leme65be3022016-03-22 14:53:13 -0700222
Andrew Scull45f533c2017-05-19 15:37:20 +0100223 private final Object mIdleTimerLock = new Object();
Haoyu Bai04124232012-06-28 15:26:19 -0700224 /** Set of interfaces with active idle timers. */
225 private static class IdleTimerParams {
226 public final int timeout;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800227 public final int type;
Haoyu Bai04124232012-06-28 15:26:19 -0700228 public int networkCount;
229
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800230 IdleTimerParams(int timeout, int type) {
Haoyu Bai04124232012-06-28 15:26:19 -0700231 this.timeout = timeout;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800232 this.type = type;
Haoyu Bai04124232012-06-28 15:26:19 -0700233 this.networkCount = 1;
234 }
235 }
236 private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
237
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700238 private volatile boolean mFirewallEnabled;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800239 private volatile boolean mStrictEnabled;
Jeff Sharkey350083e2011-06-29 10:45:16 -0700240
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700241 private boolean mMobileActivityFromRadio = false;
242 private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
Adam Lesinskie08af192015-03-25 16:42:59 -0700243 private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700244
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800245 private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
Christopher Wiley212b95f2016-08-02 11:38:57 -0700246 new RemoteCallbackList<>();
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800247 private boolean mNetworkActive;
248
San Mehat873f2142010-01-14 10:25:07 -0800249 /**
250 * Constructs a new NetworkManagementService instance
251 *
252 * @param context Binder context for this service
253 */
Lorenzo Colittia0868002017-07-11 02:29:28 +0900254 private NetworkManagementService(
Luke Huang909b31a2019-03-16 21:21:16 +0800255 Context context, SystemServices services) {
San Mehat873f2142010-01-14 10:25:07 -0800256 mContext = context;
Lorenzo Colittia0868002017-07-11 02:29:28 +0900257 mServices = services;
San Mehat4d02d002010-01-22 16:07:46 -0800258
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700259 mDaemonHandler = new Handler(FgThread.get().getLooper());
Wink Saville67e07892014-06-18 16:43:14 -0700260
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900261 mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
262
Lorenzo Colittia0868002017-07-11 02:29:28 +0900263 mServices.registerLocalService(new LocalService());
Lorenzo Colitti8228eb32017-07-19 06:17:33 +0900264
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900265 synchronized (mTetheringStatsProviders) {
266 mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
267 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700268 }
269
270 @VisibleForTesting
271 NetworkManagementService() {
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700272 mContext = null;
273 mDaemonHandler = null;
Lorenzo Colittia0868002017-07-11 02:29:28 +0900274 mServices = null;
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900275 mNetdUnsolicitedEventListener = null;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700276 }
277
Luke Huang909b31a2019-03-16 21:21:16 +0800278 static NetworkManagementService create(Context context, SystemServices services)
Felipe Leme03e689d2016-03-02 16:17:38 -0800279 throws InterruptedException {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900280 final NetworkManagementService service =
Luke Huang909b31a2019-03-16 21:21:16 +0800281 new NetworkManagementService(context, services);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700282 if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900283 if (DBG) Slog.d(TAG, "Connecting native netd service");
bohu07cc3bb2016-05-03 15:58:01 -0700284 service.connectNativeNetdService();
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900285 if (DBG) Slog.d(TAG, "Connected");
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700286 return service;
San Mehat873f2142010-01-14 10:25:07 -0800287 }
288
Lorenzo Colitti7421a012013-08-20 22:51:24 +0900289 public static NetworkManagementService create(Context context) throws InterruptedException {
Luke Huang909b31a2019-03-16 21:21:16 +0800290 return create(context, new SystemServices());
Lorenzo Colitti7421a012013-08-20 22:51:24 +0900291 }
292
Jeff Sharkey350083e2011-06-29 10:45:16 -0700293 public void systemReady() {
Felipe Leme03e689d2016-03-02 16:17:38 -0800294 if (DBG) {
295 final long start = System.currentTimeMillis();
296 prepareNativeDaemon();
297 final long delta = System.currentTimeMillis() - start;
298 Slog.d(TAG, "Prepared in " + delta + "ms");
299 return;
300 } else {
301 prepareNativeDaemon();
302 }
Jeff Sharkey350083e2011-06-29 10:45:16 -0700303 }
304
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800305 private IBatteryStats getBatteryStats() {
306 synchronized (this) {
307 if (mBatteryStats != null) {
308 return mBatteryStats;
309 }
Lorenzo Colittia0868002017-07-11 02:29:28 +0900310 mBatteryStats =
311 IBatteryStats.Stub.asInterface(mServices.getService(BatteryStats.SERVICE_NAME));
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800312 return mBatteryStats;
313 }
314 }
315
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800316 @Override
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800317 public void registerObserver(INetworkManagementEventObserver observer) {
paulhu59148b72019-08-12 16:25:11 +0800318 NetworkStack.checkNetworkStackPermission(mContext);
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900319 mObservers.register(observer);
San Mehat4d02d002010-01-22 16:07:46 -0800320 }
321
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800322 @Override
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800323 public void unregisterObserver(INetworkManagementEventObserver observer) {
paulhu59148b72019-08-12 16:25:11 +0800324 NetworkStack.checkNetworkStackPermission(mContext);
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900325 mObservers.unregister(observer);
San Mehat4d02d002010-01-22 16:07:46 -0800326 }
327
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900328 @FunctionalInterface
329 private interface NetworkManagementEventCallback {
330 public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
331 }
332
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900333 private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
334 final int length = mObservers.beginBroadcast();
335 try {
336 for (int i = 0; i < length; i++) {
337 try {
338 eventCallback.sendCallback(mObservers.getBroadcastItem(i));
339 } catch (RemoteException | RuntimeException e) {
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700340 }
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900341 }
342 } finally {
343 mObservers.finishBroadcast();
344 }
345 }
346
347 /**
348 * Notify our observers of an interface status change
349 */
350 private void notifyInterfaceStatusChanged(String iface, boolean up) {
351 invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
352 }
353
354 /**
355 * Notify our observers of an interface link state change
356 * (typically, an Ethernet cable has been plugged-in or unplugged).
357 */
358 private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
359 invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
360 }
361
362 /**
363 * Notify our observers of an interface addition.
364 */
365 private void notifyInterfaceAdded(String iface) {
366 invokeForAllObservers(o -> o.interfaceAdded(iface));
367 }
368
369 /**
370 * Notify our observers of an interface removal.
371 */
372 private void notifyInterfaceRemoved(String iface) {
373 // netd already clears out quota and alerts for removed ifaces; update
374 // our sanity-checking state.
375 mActiveAlerts.remove(iface);
376 mActiveQuotas.remove(iface);
377 invokeForAllObservers(o -> o.interfaceRemoved(iface));
378 }
379
380 /**
381 * Notify our observers of a limit reached.
382 */
383 private void notifyLimitReached(String limitName, String iface) {
384 invokeForAllObservers(o -> o.limitReached(limitName, iface));
385 }
386
387 /**
388 * Notify our observers of a change in the data activity state of the interface
389 */
390 private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
391 int uid, boolean fromRadio) {
392 final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
393 int powerState = isActive
394 ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
395 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
396 if (isMobile) {
397 if (!fromRadio) {
398 if (mMobileActivityFromRadio) {
399 // If this call is not coming from a report from the radio itself, but we
400 // have previously received reports from the radio, then we will take the
401 // power state to just be whatever the radio last reported.
402 powerState = mLastPowerStateFromRadio;
403 }
404 } else {
405 mMobileActivityFromRadio = true;
406 }
407 if (mLastPowerStateFromRadio != powerState) {
408 mLastPowerStateFromRadio = powerState;
409 try {
410 getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
411 } catch (RemoteException e) {
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700412 }
Bookatz0b028b12018-05-31 16:51:17 -0700413 StatsLog.write_non_chained(StatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null,
414 powerState);
Haoyu Baidb3c8672012-06-20 14:29:57 -0700415 }
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900416 }
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700417
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900418 if (ConnectivityManager.isNetworkTypeWifi(type)) {
419 if (mLastPowerStateFromWifi != powerState) {
420 mLastPowerStateFromWifi = powerState;
421 try {
422 getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
423 } catch (RemoteException e) {
Adam Lesinskie08af192015-03-25 16:42:59 -0700424 }
Bookatz0b028b12018-05-31 16:51:17 -0700425 StatsLog.write_non_chained(StatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null,
426 powerState);
Adam Lesinskie08af192015-03-25 16:42:59 -0700427 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800428 }
Lorenzo Colittid8bc8292019-01-24 13:28:50 +0900429
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900430 if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
431 // Report the change in data activity. We don't do this if this is a change
432 // on the mobile network, that is not coming from the radio itself, and we
433 // have previously seen change reports from the radio. In that case only
434 // the radio is the authority for the current state.
435 final boolean active = isActive;
436 invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
437 Integer.toString(type), active, tsNanos));
Lorenzo Colittid8bc8292019-01-24 13:28:50 +0900438 }
439
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900440 boolean report = false;
441 synchronized (mIdleTimerLock) {
442 if (mActiveIdleTimers.isEmpty()) {
443 // If there are no idle timers, we are not monitoring activity, so we
444 // are always considered active.
445 isActive = true;
446 }
447 if (mNetworkActive != isActive) {
448 mNetworkActive = isActive;
449 report = isActive;
450 }
451 }
452 if (report) {
453 reportNetworkActive();
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800454 }
Haoyu Baidb3c8672012-06-20 14:29:57 -0700455 }
456
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900457 @Override
458 public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
paulhu59148b72019-08-12 16:25:11 +0800459 NetworkStack.checkNetworkStackPermission(mContext);
Daulet Zhanguzinea1a7ca2020-01-03 09:46:50 +0000460 Objects.requireNonNull(provider);
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900461 synchronized(mTetheringStatsProviders) {
462 mTetheringStatsProviders.put(provider, name);
463 }
464 }
465
466 @Override
467 public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
paulhu59148b72019-08-12 16:25:11 +0800468 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900469 synchronized(mTetheringStatsProviders) {
470 mTetheringStatsProviders.remove(provider);
471 }
472 }
473
Lorenzo Colitti9f0baa92017-08-15 19:25:51 +0900474 @Override
475 public void tetherLimitReached(ITetheringStatsProvider provider) {
paulhu59148b72019-08-12 16:25:11 +0800476 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti9f0baa92017-08-15 19:25:51 +0900477 synchronized(mTetheringStatsProviders) {
478 if (!mTetheringStatsProviders.containsKey(provider)) {
479 return;
480 }
481 // No current code examines the interface parameter in a global alert. Just pass null.
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900482 mDaemonHandler.post(() -> notifyLimitReached(LIMIT_GLOBAL_ALERT, null));
Lorenzo Colitti9f0baa92017-08-15 19:25:51 +0900483 }
484 }
485
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900486 // Sync the state of the given chain with the native daemon.
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700487 private void syncFirewallChainLocked(int chain, String name) {
488 SparseIntArray rules;
489 synchronized (mRulesLock) {
490 final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900491 // Make a copy of the current rules, and then clear them. This is because
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700492 // setFirewallUidRuleInternal only pushes down rules to the native daemon if they
493 // are different from the current rules stored in the mUidFirewall*Rules array for
494 // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal
495 // will do nothing.
496 rules = uidFirewallRules.clone();
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900497 uidFirewallRules.clear();
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700498 }
499 if (rules.size() > 0) {
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900500 // Now push the rules. setFirewallUidRuleInternal will push each of these down to the
501 // native daemon, and also add them to the mUidFirewall*Rules array for the specified
502 // chain.
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700503 if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall "
504 + name + "UID rules");
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900505 for (int i = 0; i < rules.size(); i++) {
Felipe Lemea701cad2016-05-12 09:58:14 -0700506 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i));
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900507 }
508 }
509 }
510
bohu07cc3bb2016-05-03 15:58:01 -0700511 private void connectNativeNetdService() {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900512 mNetdService = mServices.getNetd();
Luke Huangd290dd52018-09-04 17:08:18 +0800513 try {
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900514 mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener);
515 if (DBG) Slog.d(TAG, "Register unsolicited event listener");
Luke Huangd290dd52018-09-04 17:08:18 +0800516 } catch (RemoteException | ServiceSpecificException e) {
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900517 Slog.e(TAG, "Failed to set Netd unsolicited event listener " + e);
Luke Huangd290dd52018-09-04 17:08:18 +0800518 }
bohu07cc3bb2016-05-03 15:58:01 -0700519 }
520
521 /**
522 * Prepare native daemon once connected, enabling modules and pushing any
523 * existing in-memory rules.
524 */
525 private void prepareNativeDaemon() {
Lorenzo Colitti58967ba2016-02-02 17:21:21 +0900526
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700527 // push any existing quota or UID rules
528 synchronized (mQuotaLock) {
Felipe Leme65be3022016-03-22 14:53:13 -0700529
Luke Huang56a03a02018-09-07 12:02:16 +0800530 // Netd unconditionally enable bandwidth control
531 SystemProperties.set(PROP_QTAGUID_ENABLED, "1");
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900532
Luke Huang473eb872018-07-26 17:33:14 +0800533 mStrictEnabled = true;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900534
Felipe Leme65be3022016-03-22 14:53:13 -0700535 setDataSaverModeEnabled(mDataSaverMode);
536
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700537 int size = mActiveQuotas.size();
538 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800539 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700540 final HashMap<String, Long> activeQuotas = mActiveQuotas;
541 mActiveQuotas = Maps.newHashMap();
542 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
543 setInterfaceQuota(entry.getKey(), entry.getValue());
544 }
545 }
546
547 size = mActiveAlerts.size();
548 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800549 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700550 final HashMap<String, Long> activeAlerts = mActiveAlerts;
551 mActiveAlerts = Maps.newHashMap();
552 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
553 setInterfaceAlert(entry.getKey(), entry.getValue());
554 }
555 }
556
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700557 SparseBooleanArray uidRejectOnQuota = null;
558 SparseBooleanArray uidAcceptOnQuota = null;
559 synchronized (mRulesLock) {
560 size = mUidRejectOnMetered.size();
561 if (size > 0) {
562 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
563 uidRejectOnQuota = mUidRejectOnMetered;
564 mUidRejectOnMetered = new SparseBooleanArray();
565 }
566
567 size = mUidAllowOnMetered.size();
568 if (size > 0) {
569 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
570 uidAcceptOnQuota = mUidAllowOnMetered;
571 mUidAllowOnMetered = new SparseBooleanArray();
572 }
573 }
574 if (uidRejectOnQuota != null) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700575 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
Felipe Leme65be3022016-03-22 14:53:13 -0700576 setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
577 uidRejectOnQuota.valueAt(i));
578 }
579 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700580 if (uidAcceptOnQuota != null) {
Felipe Leme65be3022016-03-22 14:53:13 -0700581 for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
582 setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
583 uidAcceptOnQuota.valueAt(i));
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700584 }
585 }
Jeff Sharkey605eb792014-11-04 13:34:06 -0800586
587 size = mUidCleartextPolicy.size();
588 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800589 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
Jeff Sharkey605eb792014-11-04 13:34:06 -0800590 final SparseIntArray local = mUidCleartextPolicy;
591 mUidCleartextPolicy = new SparseIntArray();
592 for (int i = 0; i < local.size(); i++) {
593 setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
594 }
595 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700596
Robin Leec3736bc2017-03-10 16:19:54 +0000597 setFirewallEnabled(mFirewallEnabled);
Amith Yamasani15e472352015-04-24 19:06:07 -0700598
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700599 syncFirewallChainLocked(FIREWALL_CHAIN_NONE, "");
600 syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
601 syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
602 syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700603
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700604 final int[] chains =
605 {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
606 for (int chain : chains) {
607 if (getFirewallChainState(chain)) {
608 setFirewallChainEnabled(chain, true);
609 }
Felipe Leme011b98f2016-02-10 17:28:31 -0800610 }
Amith Yamasani15e472352015-04-24 19:06:07 -0700611 }
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900612
Luke Huang56a03a02018-09-07 12:02:16 +0800613
614 try {
615 getBatteryStats().noteNetworkStatsEnabled();
616 } catch (RemoteException e) {
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900617 }
618
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700619 }
San Mehat4d02d002010-01-22 16:07:46 -0800620
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900621 /**
622 * Notify our observers of a new or updated interface address.
623 */
624 private void notifyAddressUpdated(String iface, LinkAddress address) {
625 invokeForAllObservers(o -> o.addressUpdated(iface, address));
626 }
627
628 /**
629 * Notify our observers of a deleted interface address.
630 */
631 private void notifyAddressRemoved(String iface, LinkAddress address) {
632 invokeForAllObservers(o -> o.addressRemoved(iface, address));
633 }
634
635 /**
636 * Notify our observers of DNS server information received.
637 */
638 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
639 invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
640 }
641
642 /**
643 * Notify our observers of a route change.
644 */
645 private void notifyRouteChange(boolean updated, RouteInfo route) {
646 if (updated) {
647 invokeForAllObservers(o -> o.routeUpdated(route));
648 } else {
649 invokeForAllObservers(o -> o.routeRemoved(route));
650 }
651 }
652
653 private class NetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub {
654 @Override
655 public void onInterfaceClassActivityChanged(boolean isActive,
656 int label, long timestamp, int uid) throws RemoteException {
657 final long timestampNanos;
658 if (timestamp <= 0) {
659 timestampNanos = SystemClock.elapsedRealtimeNanos();
660 } else {
661 timestampNanos = timestamp;
662 }
663 mDaemonHandler.post(() ->
664 notifyInterfaceClassActivity(label, isActive, timestampNanos, uid, false));
665 }
666
667 @Override
668 public void onQuotaLimitReached(String alertName, String ifName)
669 throws RemoteException {
670 mDaemonHandler.post(() -> notifyLimitReached(alertName, ifName));
671 }
672
673 @Override
674 public void onInterfaceDnsServerInfo(String ifName,
675 long lifetime, String[] servers) throws RemoteException {
676 mDaemonHandler.post(() -> notifyInterfaceDnsServerInfo(ifName, lifetime, servers));
677 }
678
679 @Override
680 public void onInterfaceAddressUpdated(String addr,
681 String ifName, int flags, int scope) throws RemoteException {
682 final LinkAddress address = new LinkAddress(addr, flags, scope);
683 mDaemonHandler.post(() -> notifyAddressUpdated(ifName, address));
684 }
685
686 @Override
687 public void onInterfaceAddressRemoved(String addr,
688 String ifName, int flags, int scope) throws RemoteException {
689 final LinkAddress address = new LinkAddress(addr, flags, scope);
690 mDaemonHandler.post(() -> notifyAddressRemoved(ifName, address));
691 }
692
693 @Override
694 public void onInterfaceAdded(String ifName) throws RemoteException {
695 mDaemonHandler.post(() -> notifyInterfaceAdded(ifName));
696 }
697
698 @Override
699 public void onInterfaceRemoved(String ifName) throws RemoteException {
700 mDaemonHandler.post(() -> notifyInterfaceRemoved(ifName));
701 }
702
703 @Override
704 public void onInterfaceChanged(String ifName, boolean up)
705 throws RemoteException {
706 mDaemonHandler.post(() -> notifyInterfaceStatusChanged(ifName, up));
707 }
708
709 @Override
710 public void onInterfaceLinkStateChanged(String ifName, boolean up)
711 throws RemoteException {
712 mDaemonHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up));
713 }
714
715 @Override
716 public void onRouteChanged(boolean updated,
717 String route, String gateway, String ifName) throws RemoteException {
718 final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
719 ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
720 ifName);
721 mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute));
722 }
723
724 @Override
725 public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
726 // Don't need to post to mDaemonHandler because the only thing
727 // that notifyCleartextNetwork does is post to a handler
728 ActivityManager.getService().notifyCleartextNetwork(uid,
729 HexDump.hexStringToByteArray(hex));
730 }
Remi NGUYEN VANeec0ed42019-04-09 14:01:51 +0900731
732 @Override
733 public int getInterfaceVersion() {
734 return INetdUnsolicitedEventListener.VERSION;
735 }
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900736 }
737
San Mehat873f2142010-01-14 10:25:07 -0800738 //
San Mehat873f2142010-01-14 10:25:07 -0800739 // INetworkManagementService members
740 //
Erik Kline4e37b702016-07-05 11:34:21 +0900741 @Override
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800742 public String[] listInterfaces() {
paulhu79ebe4f2019-12-06 16:45:38 +0800743 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
744 // APIs.
745 NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
Kenny Roota80ce062010-06-01 13:23:53 -0700746 try {
Luke Huang1b4f92f2018-12-12 15:59:31 +0800747 return mNetdService.interfaceGetList();
Luke Huang14f75442018-08-15 19:22:54 +0800748 } catch (RemoteException | ServiceSpecificException e) {
749 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -0700750 }
San Mehated4fc8a2010-01-22 12:28:36 -0800751 }
752
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +0900753 /**
754 * Convert InterfaceConfiguration to InterfaceConfigurationParcel with given ifname.
755 */
756 private static InterfaceConfigurationParcel toStableParcel(InterfaceConfiguration cfg,
757 String iface) {
758 InterfaceConfigurationParcel cfgParcel = new InterfaceConfigurationParcel();
759 cfgParcel.ifName = iface;
760 String hwAddr = cfg.getHardwareAddress();
761 if (!TextUtils.isEmpty(hwAddr)) {
762 cfgParcel.hwAddr = hwAddr;
763 } else {
764 cfgParcel.hwAddr = "";
765 }
766 cfgParcel.ipv4Addr = cfg.getLinkAddress().getAddress().getHostAddress();
767 cfgParcel.prefixLength = cfg.getLinkAddress().getPrefixLength();
768 ArrayList<String> flags = new ArrayList<>();
769 for (String flag : cfg.getFlags()) {
770 flags.add(flag);
771 }
772 cfgParcel.flags = flags.toArray(new String[0]);
773
774 return cfgParcel;
775 }
776
777 /**
778 * Construct InterfaceConfiguration from InterfaceConfigurationParcel.
779 */
780 public static InterfaceConfiguration fromStableParcel(InterfaceConfigurationParcel p) {
781 InterfaceConfiguration cfg = new InterfaceConfiguration();
782 cfg.setHardwareAddress(p.hwAddr);
783
784 final InetAddress addr = NetworkUtils.numericToInetAddress(p.ipv4Addr);
785 cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength));
786 for (String flag : p.flags) {
787 cfg.setFlag(flag);
788 }
789
790 return cfg;
791 }
792
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800793 @Override
794 public InterfaceConfiguration getInterfaceConfig(String iface) {
paulhu79ebe4f2019-12-06 16:45:38 +0800795 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
796 // APIs.
797 NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
Luke Huang14f75442018-08-15 19:22:54 +0800798 final InterfaceConfigurationParcel result;
Kenny Roota80ce062010-06-01 13:23:53 -0700799 try {
Luke Huang14f75442018-08-15 19:22:54 +0800800 result = mNetdService.interfaceGetCfg(iface);
801 } catch (RemoteException | ServiceSpecificException e) {
802 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -0700803 }
San Mehated4fc8a2010-01-22 12:28:36 -0800804
San Mehated4fc8a2010-01-22 12:28:36 -0800805 try {
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +0900806 final InterfaceConfiguration cfg = fromStableParcel(result);
Luke Huang14f75442018-08-15 19:22:54 +0800807 return cfg;
808 } catch (IllegalArgumentException iae) {
809 throw new IllegalStateException("Invalid InterfaceConfigurationParcel", iae);
San Mehated4fc8a2010-01-22 12:28:36 -0800810 }
San Mehated4fc8a2010-01-22 12:28:36 -0800811 }
812
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800813 @Override
814 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
paulhu79ebe4f2019-12-06 16:45:38 +0800815 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
816 // APIs.
817 NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800818 LinkAddress linkAddr = cfg.getLinkAddress();
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800819 if (linkAddr == null || linkAddr.getAddress() == null) {
820 throw new IllegalStateException("Null LinkAddress given");
Robert Greenwalted126402011-01-28 15:34:55 -0800821 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800822
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +0900823 final InterfaceConfigurationParcel cfgParcel = toStableParcel(cfg, iface);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800824
Kenny Roota80ce062010-06-01 13:23:53 -0700825 try {
Luke Huang14f75442018-08-15 19:22:54 +0800826 mNetdService.interfaceSetCfg(cfgParcel);
827 } catch (RemoteException | ServiceSpecificException e) {
828 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -0700829 }
San Mehat873f2142010-01-14 10:25:07 -0800830 }
831
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800832 @Override
833 public void setInterfaceDown(String iface) {
paulhu59148b72019-08-12 16:25:11 +0800834 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800835 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800836 ifcg.setInterfaceDown();
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800837 setInterfaceConfig(iface, ifcg);
Irfan Sheriff7244c972011-08-05 20:40:45 -0700838 }
839
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800840 @Override
841 public void setInterfaceUp(String iface) {
paulhu59148b72019-08-12 16:25:11 +0800842 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800843 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800844 ifcg.setInterfaceUp();
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800845 setInterfaceConfig(iface, ifcg);
Irfan Sheriff7244c972011-08-05 20:40:45 -0700846 }
847
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800848 @Override
849 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
paulhu59148b72019-08-12 16:25:11 +0800850 NetworkStack.checkNetworkStackPermission(mContext);
Irfan Sheriff73293612011-09-14 12:31:56 -0700851 try {
Luke Huang14f75442018-08-15 19:22:54 +0800852 mNetdService.interfaceSetIPv6PrivacyExtensions(iface, enable);
853 } catch (RemoteException | ServiceSpecificException e) {
854 throw new IllegalStateException(e);
Irfan Sheriff73293612011-09-14 12:31:56 -0700855 }
856 }
857
Irfan Sherifff5600612011-06-16 10:26:28 -0700858 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
859 IPv6 addresses on interface down, but we need to do full clean up here */
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800860 @Override
861 public void clearInterfaceAddresses(String iface) {
paulhu59148b72019-08-12 16:25:11 +0800862 NetworkStack.checkNetworkStackPermission(mContext);
Irfan Sherifff5600612011-06-16 10:26:28 -0700863 try {
Luke Huang14f75442018-08-15 19:22:54 +0800864 mNetdService.interfaceClearAddrs(iface);
865 } catch (RemoteException | ServiceSpecificException e) {
866 throw new IllegalStateException(e);
Irfan Sherifff5600612011-06-16 10:26:28 -0700867 }
868 }
869
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800870 @Override
871 public void enableIpv6(String iface) {
paulhu59148b72019-08-12 16:25:11 +0800872 NetworkStack.checkNetworkStackPermission(mContext);
repo sync7960d9f2011-09-29 12:40:02 -0700873 try {
Luke Huang14f75442018-08-15 19:22:54 +0800874 mNetdService.interfaceSetEnableIPv6(iface, true);
875 } catch (RemoteException | ServiceSpecificException e) {
876 throw new IllegalStateException(e);
repo sync7960d9f2011-09-29 12:40:02 -0700877 }
878 }
879
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800880 @Override
Joel Scherpelz2db10742017-06-07 15:38:38 +0900881 public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
882 try {
883 mNetdService.setIPv6AddrGenMode(iface, mode);
884 } catch (RemoteException e) {
885 throw e.rethrowAsRuntimeException();
886 }
887 }
888
889 @Override
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800890 public void disableIpv6(String iface) {
paulhu59148b72019-08-12 16:25:11 +0800891 NetworkStack.checkNetworkStackPermission(mContext);
repo sync7960d9f2011-09-29 12:40:02 -0700892 try {
Luke Huang14f75442018-08-15 19:22:54 +0800893 mNetdService.interfaceSetEnableIPv6(iface, false);
894 } catch (RemoteException | ServiceSpecificException e) {
895 throw new IllegalStateException(e);
repo sync7960d9f2011-09-29 12:40:02 -0700896 }
897 }
898
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800899 @Override
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -0700900 public void addRoute(int netId, RouteInfo route) {
Luke Huang8a462ec2018-08-24 20:33:16 +0800901 modifyRoute(MODIFY_OPERATION_ADD, netId, route);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700902 }
903
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800904 @Override
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -0700905 public void removeRoute(int netId, RouteInfo route) {
Luke Huang8a462ec2018-08-24 20:33:16 +0800906 modifyRoute(MODIFY_OPERATION_REMOVE, netId, route);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700907 }
908
Luke Huang8a462ec2018-08-24 20:33:16 +0800909 private void modifyRoute(boolean add, int netId, RouteInfo route) {
paulhu59148b72019-08-12 16:25:11 +0800910 NetworkStack.checkNetworkStackPermission(mContext);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700911
Luke Huang8a462ec2018-08-24 20:33:16 +0800912 final String ifName = route.getInterface();
913 final String dst = route.getDestination().toString();
914 final String nextHop;
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900915
916 switch (route.getType()) {
917 case RouteInfo.RTN_UNICAST:
918 if (route.hasGateway()) {
Luke Huang8a462ec2018-08-24 20:33:16 +0800919 nextHop = route.getGateway().getHostAddress();
920 } else {
921 nextHop = INetd.NEXTHOP_NONE;
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900922 }
923 break;
924 case RouteInfo.RTN_UNREACHABLE:
Luke Huang8a462ec2018-08-24 20:33:16 +0800925 nextHop = INetd.NEXTHOP_UNREACHABLE;
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900926 break;
927 case RouteInfo.RTN_THROW:
Luke Huang8a462ec2018-08-24 20:33:16 +0800928 nextHop = INetd.NEXTHOP_THROW;
929 break;
930 default:
931 nextHop = INetd.NEXTHOP_NONE;
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900932 break;
Sreeram Ramachandran1fbcb272014-05-22 16:30:48 -0700933 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800934 try {
Luke Huang8a462ec2018-08-24 20:33:16 +0800935 if (add) {
936 mNetdService.networkAddRoute(netId, ifName, dst, nextHop);
937 } else {
938 mNetdService.networkRemoveRoute(netId, ifName, dst, nextHop);
939 }
940 } catch (RemoteException | ServiceSpecificException e) {
941 throw new IllegalStateException(e);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700942 }
943 }
944
945 private ArrayList<String> readRouteList(String filename) {
946 FileInputStream fstream = null;
Christopher Wiley212b95f2016-08-02 11:38:57 -0700947 ArrayList<String> list = new ArrayList<>();
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700948
949 try {
950 fstream = new FileInputStream(filename);
951 DataInputStream in = new DataInputStream(fstream);
952 BufferedReader br = new BufferedReader(new InputStreamReader(in));
953 String s;
954
955 // throw away the title line
956
957 while (((s = br.readLine()) != null) && (s.length() != 0)) {
958 list.add(s);
959 }
960 } catch (IOException ex) {
961 // return current list, possibly empty
962 } finally {
963 if (fstream != null) {
964 try {
965 fstream.close();
966 } catch (IOException ex) {}
967 }
968 }
969
970 return list;
971 }
972
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800973 @Override
sy.yun9d9b74a2013-09-02 05:24:09 +0900974 public void setMtu(String iface, int mtu) {
paulhu59148b72019-08-12 16:25:11 +0800975 NetworkStack.checkNetworkStackPermission(mContext);
sy.yun9d9b74a2013-09-02 05:24:09 +0900976
sy.yun9d9b74a2013-09-02 05:24:09 +0900977 try {
Luke Huang14f75442018-08-15 19:22:54 +0800978 mNetdService.interfaceSetMtu(iface, mtu);
979 } catch (RemoteException | ServiceSpecificException e) {
980 throw new IllegalStateException(e);
sy.yun9d9b74a2013-09-02 05:24:09 +0900981 }
982 }
983
984 @Override
San Mehat873f2142010-01-14 10:25:07 -0800985 public void shutdown() {
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800986 // TODO: remove from aidl if nobody calls externally
987 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
San Mehat873f2142010-01-14 10:25:07 -0800988
Felipe Leme03e689d2016-03-02 16:17:38 -0800989 Slog.i(TAG, "Shutting down");
San Mehat873f2142010-01-14 10:25:07 -0800990 }
991
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800992 @Override
San Mehat873f2142010-01-14 10:25:07 -0800993 public boolean getIpForwardingEnabled() throws IllegalStateException{
paulhu59148b72019-08-12 16:25:11 +0800994 NetworkStack.checkNetworkStackPermission(mContext);
San Mehat873f2142010-01-14 10:25:07 -0800995
Kenny Roota80ce062010-06-01 13:23:53 -0700996 try {
Luke Huang4db488b2018-08-16 15:37:31 +0800997 final boolean isEnabled = mNetdService.ipfwdEnabled();
998 return isEnabled;
999 } catch (RemoteException | ServiceSpecificException e) {
1000 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001001 }
San Mehat873f2142010-01-14 10:25:07 -08001002 }
1003
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001004 @Override
1005 public void setIpForwardingEnabled(boolean enable) {
paulhu59148b72019-08-12 16:25:11 +08001006 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001007 try {
Luke Huang4db488b2018-08-16 15:37:31 +08001008 if (enable) {
1009 mNetdService.ipfwdEnableForwarding("tethering");
1010 } else {
1011 mNetdService.ipfwdDisableForwarding("tethering");
1012 }
1013 } catch (RemoteException | ServiceSpecificException e) {
1014 throw new IllegalStateException(e);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001015 }
San Mehat873f2142010-01-14 10:25:07 -08001016 }
1017
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001018 @Override
1019 public void startTethering(String[] dhcpRange) {
Luke Huangb0d52462019-03-21 14:43:08 +08001020 startTetheringWithConfiguration(true, dhcpRange);
1021 }
1022
1023 @Override
1024 public void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange) {
paulhu59148b72019-08-12 16:25:11 +08001025 NetworkStack.checkNetworkStackPermission(mContext);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -07001026 // an odd number of addrs will fail
Kenny Roota80ce062010-06-01 13:23:53 -07001027 try {
Chiachang Wangafd43e42019-12-10 10:07:12 +08001028 final TetherConfigParcel config = new TetherConfigParcel();
1029 config.usingLegacyDnsProxy = usingLegacyDnsProxy;
1030 config.dhcpRanges = dhcpRange;
1031 mNetdService.tetherStartWithConfiguration(config);
Luke Huang4a32bf42018-08-21 19:09:45 +08001032 } catch (RemoteException | ServiceSpecificException e) {
1033 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001034 }
San Mehat873f2142010-01-14 10:25:07 -08001035 }
1036
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001037 @Override
1038 public void stopTethering() {
paulhu59148b72019-08-12 16:25:11 +08001039 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001040 try {
Luke Huang4a32bf42018-08-21 19:09:45 +08001041 mNetdService.tetherStop();
1042 } catch (RemoteException | ServiceSpecificException e) {
1043 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001044 }
San Mehat873f2142010-01-14 10:25:07 -08001045 }
1046
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001047 @Override
1048 public boolean isTetheringStarted() {
paulhu59148b72019-08-12 16:25:11 +08001049 NetworkStack.checkNetworkStackPermission(mContext);
San Mehat873f2142010-01-14 10:25:07 -08001050
Kenny Roota80ce062010-06-01 13:23:53 -07001051 try {
Luke Huang4a32bf42018-08-21 19:09:45 +08001052 final boolean isEnabled = mNetdService.tetherIsEnabled();
1053 return isEnabled;
1054 } catch (RemoteException | ServiceSpecificException e) {
1055 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001056 }
San Mehat873f2142010-01-14 10:25:07 -08001057 }
Matthew Xiefe19f122012-07-12 16:03:32 -07001058
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001059 @Override
1060 public void tetherInterface(String iface) {
paulhu59148b72019-08-12 16:25:11 +08001061 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001062 try {
Luke Huang4a32bf42018-08-21 19:09:45 +08001063 mNetdService.tetherInterfaceAdd(iface);
1064 } catch (RemoteException | ServiceSpecificException e) {
1065 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001066 }
Christopher Wiley212b95f2016-08-02 11:38:57 -07001067 List<RouteInfo> routes = new ArrayList<>();
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07001068 // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
1069 // suitable to use as a route destination.
1070 routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
1071 addInterfaceToLocalNetwork(iface, routes);
San Mehat873f2142010-01-14 10:25:07 -08001072 }
1073
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001074 @Override
San Mehat873f2142010-01-14 10:25:07 -08001075 public void untetherInterface(String iface) {
paulhu59148b72019-08-12 16:25:11 +08001076 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001077 try {
Luke Huang4a32bf42018-08-21 19:09:45 +08001078 mNetdService.tetherInterfaceRemove(iface);
1079 } catch (RemoteException | ServiceSpecificException e) {
1080 throw new IllegalStateException(e);
Erik Kline1f4278a2016-08-16 16:46:33 +09001081 } finally {
1082 removeInterfaceFromLocalNetwork(iface);
Kenny Roota80ce062010-06-01 13:23:53 -07001083 }
San Mehat873f2142010-01-14 10:25:07 -08001084 }
1085
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001086 @Override
1087 public String[] listTetheredInterfaces() {
paulhu59148b72019-08-12 16:25:11 +08001088 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001089 try {
Luke Huang1b4f92f2018-12-12 15:59:31 +08001090 return mNetdService.tetherInterfaceList();
Luke Huang4a32bf42018-08-21 19:09:45 +08001091 } catch (RemoteException | ServiceSpecificException e) {
1092 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001093 }
San Mehat873f2142010-01-14 10:25:07 -08001094 }
1095
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001096 @Override
Lorenzo Colittib57edc52014-08-22 17:10:50 -07001097 public void setDnsForwarders(Network network, String[] dns) {
paulhu59148b72019-08-12 16:25:11 +08001098 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001099
Lorenzo Colittib57edc52014-08-22 17:10:50 -07001100 int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001101
San Mehat873f2142010-01-14 10:25:07 -08001102 try {
Luke Huang4a32bf42018-08-21 19:09:45 +08001103 mNetdService.tetherDnsSet(netId, dns);
1104 } catch (RemoteException | ServiceSpecificException e) {
1105 throw new IllegalStateException(e);
San Mehat873f2142010-01-14 10:25:07 -08001106 }
1107 }
1108
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001109 @Override
1110 public String[] getDnsForwarders() {
paulhu59148b72019-08-12 16:25:11 +08001111 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001112 try {
Luke Huang1b4f92f2018-12-12 15:59:31 +08001113 return mNetdService.tetherDnsList();
Luke Huang4a32bf42018-08-21 19:09:45 +08001114 } catch (RemoteException | ServiceSpecificException e) {
1115 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001116 }
San Mehat873f2142010-01-14 10:25:07 -08001117 }
1118
jiaguo1da35f72014-01-09 16:39:59 +08001119 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
Christopher Wiley212b95f2016-08-02 11:38:57 -07001120 ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
jiaguo1da35f72014-01-09 16:39:59 +08001121 for (InterfaceAddress ia : addresses) {
1122 if (!ia.getAddress().isLinkLocalAddress())
1123 filtered.add(ia);
1124 }
1125 return filtered;
1126 }
1127
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001128 private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001129 try {
Luke Huang4db488b2018-08-16 15:37:31 +08001130 if (add) {
1131 mNetdService.ipfwdAddInterfaceForward(fromIface, toIface);
1132 } else {
1133 mNetdService.ipfwdRemoveInterfaceForward(fromIface, toIface);
1134 }
1135 } catch (RemoteException | ServiceSpecificException e) {
1136 throw new IllegalStateException(e);
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001137 }
1138 }
1139
1140 @Override
1141 public void startInterfaceForwarding(String fromIface, String toIface) {
paulhu59148b72019-08-12 16:25:11 +08001142 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001143 modifyInterfaceForward(true, fromIface, toIface);
1144 }
1145
1146 @Override
1147 public void stopInterfaceForwarding(String fromIface, String toIface) {
paulhu59148b72019-08-12 16:25:11 +08001148 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001149 modifyInterfaceForward(false, fromIface, toIface);
1150 }
1151
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001152 @Override
1153 public void enableNat(String internalInterface, String externalInterface) {
paulhu59148b72019-08-12 16:25:11 +08001154 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001155 try {
Luke Huanga31e0732018-10-22 13:23:10 +09001156 mNetdService.tetherAddForward(internalInterface, externalInterface);
1157 } catch (RemoteException | ServiceSpecificException e) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001158 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001159 }
San Mehat873f2142010-01-14 10:25:07 -08001160 }
1161
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001162 @Override
1163 public void disableNat(String internalInterface, String externalInterface) {
paulhu59148b72019-08-12 16:25:11 +08001164 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001165 try {
Luke Huanga31e0732018-10-22 13:23:10 +09001166 mNetdService.tetherRemoveForward(internalInterface, externalInterface);
1167 } catch (RemoteException | ServiceSpecificException e) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001168 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001169 }
San Mehat873f2142010-01-14 10:25:07 -08001170 }
San Mehat72759df2010-01-19 13:50:37 -08001171
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001172 @Override
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001173 public void addIdleTimer(String iface, int timeout, final int type) {
paulhu59148b72019-08-12 16:25:11 +08001174 NetworkStack.checkNetworkStackPermission(mContext);
Haoyu Bai04124232012-06-28 15:26:19 -07001175
1176 if (DBG) Slog.d(TAG, "Adding idletimer");
1177
1178 synchronized (mIdleTimerLock) {
1179 IdleTimerParams params = mActiveIdleTimers.get(iface);
1180 if (params != null) {
1181 // the interface already has idletimer, update network count
1182 params.networkCount++;
1183 return;
1184 }
1185
1186 try {
Luke Huanga62d0492018-07-27 20:08:21 +08001187 mNetdService.idletimerAddInterface(iface, timeout, Integer.toString(type));
1188 } catch (RemoteException | ServiceSpecificException e) {
1189 throw new IllegalStateException(e);
Haoyu Bai04124232012-06-28 15:26:19 -07001190 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001191 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
1192
Dianne Hackborne13c4c02014-02-11 17:18:35 -08001193 // Networks start up.
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001194 if (ConnectivityManager.isNetworkTypeMobile(type)) {
1195 mNetworkActive = false;
1196 }
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +09001197 mDaemonHandler.post(() -> notifyInterfaceClassActivity(type, true,
1198 SystemClock.elapsedRealtimeNanos(), -1, false));
Haoyu Bai04124232012-06-28 15:26:19 -07001199 }
1200 }
1201
1202 @Override
1203 public void removeIdleTimer(String iface) {
paulhu59148b72019-08-12 16:25:11 +08001204 NetworkStack.checkNetworkStackPermission(mContext);
Haoyu Bai04124232012-06-28 15:26:19 -07001205
1206 if (DBG) Slog.d(TAG, "Removing idletimer");
1207
1208 synchronized (mIdleTimerLock) {
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001209 final IdleTimerParams params = mActiveIdleTimers.get(iface);
Haoyu Bai04124232012-06-28 15:26:19 -07001210 if (params == null || --(params.networkCount) > 0) {
1211 return;
1212 }
1213
1214 try {
Luke Huanga62d0492018-07-27 20:08:21 +08001215 mNetdService.idletimerRemoveInterface(iface,
1216 params.timeout, Integer.toString(params.type));
1217 } catch (RemoteException | ServiceSpecificException e) {
1218 throw new IllegalStateException(e);
Haoyu Bai04124232012-06-28 15:26:19 -07001219 }
1220 mActiveIdleTimers.remove(iface);
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +09001221 mDaemonHandler.post(() -> notifyInterfaceClassActivity(params.type, false,
1222 SystemClock.elapsedRealtimeNanos(), -1, false));
Haoyu Bai04124232012-06-28 15:26:19 -07001223 }
1224 }
1225
1226 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001227 public void setInterfaceQuota(String iface, long quotaBytes) {
paulhu59148b72019-08-12 16:25:11 +08001228 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001229
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001230 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001231 if (mActiveQuotas.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001232 throw new IllegalStateException("iface " + iface + " already has quota");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001233 }
1234
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001235 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001236 // TODO: support quota shared across interfaces
Luke Huangc7bea8662018-08-07 16:04:26 +08001237 mNetdService.bandwidthSetInterfaceQuota(iface, quotaBytes);
1238
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001239 mActiveQuotas.put(iface, quotaBytes);
Luke Huangc7bea8662018-08-07 16:04:26 +08001240 } catch (RemoteException | ServiceSpecificException e) {
1241 throw new IllegalStateException(e);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001242 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001243
1244 synchronized (mTetheringStatsProviders) {
1245 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1246 try {
1247 provider.setInterfaceQuota(iface, quotaBytes);
1248 } catch (RemoteException e) {
1249 Log.e(TAG, "Problem setting tethering data limit on provider " +
1250 mTetheringStatsProviders.get(provider) + ": " + e);
1251 }
1252 }
1253 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001254 }
1255 }
1256
1257 @Override
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001258 public void removeInterfaceQuota(String iface) {
paulhu59148b72019-08-12 16:25:11 +08001259 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001260
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001261 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001262 if (!mActiveQuotas.containsKey(iface)) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001263 // TODO: eventually consider throwing
1264 return;
1265 }
1266
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001267 mActiveQuotas.remove(iface);
1268 mActiveAlerts.remove(iface);
Jeff Sharkey38ddeaa2011-11-08 13:04:22 -08001269
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001270 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001271 // TODO: support quota shared across interfaces
Luke Huangc7bea8662018-08-07 16:04:26 +08001272 mNetdService.bandwidthRemoveInterfaceQuota(iface);
1273 } catch (RemoteException | ServiceSpecificException e) {
1274 throw new IllegalStateException(e);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001275 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001276
1277 synchronized (mTetheringStatsProviders) {
1278 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1279 try {
1280 provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
1281 } catch (RemoteException e) {
1282 Log.e(TAG, "Problem removing tethering data limit on provider " +
1283 mTetheringStatsProviders.get(provider) + ": " + e);
1284 }
1285 }
1286 }
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001287 }
1288 }
1289
1290 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001291 public void setInterfaceAlert(String iface, long alertBytes) {
paulhu59148b72019-08-12 16:25:11 +08001292 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001293
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001294 // quick sanity check
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001295 if (!mActiveQuotas.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001296 throw new IllegalStateException("setting alert requires existing quota on iface");
1297 }
1298
1299 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001300 if (mActiveAlerts.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001301 throw new IllegalStateException("iface " + iface + " already has alert");
1302 }
1303
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001304 try {
1305 // TODO: support alert shared across interfaces
Luke Huangc7bea8662018-08-07 16:04:26 +08001306 mNetdService.bandwidthSetInterfaceAlert(iface, alertBytes);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001307 mActiveAlerts.put(iface, alertBytes);
Luke Huangc7bea8662018-08-07 16:04:26 +08001308 } catch (RemoteException | ServiceSpecificException e) {
1309 throw new IllegalStateException(e);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001310 }
1311 }
1312 }
1313
1314 @Override
1315 public void removeInterfaceAlert(String iface) {
paulhu59148b72019-08-12 16:25:11 +08001316 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001317
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001318 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001319 if (!mActiveAlerts.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001320 // TODO: eventually consider throwing
1321 return;
1322 }
1323
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001324 try {
1325 // TODO: support alert shared across interfaces
Luke Huangc7bea8662018-08-07 16:04:26 +08001326 mNetdService.bandwidthRemoveInterfaceAlert(iface);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001327 mActiveAlerts.remove(iface);
Luke Huangc7bea8662018-08-07 16:04:26 +08001328 } catch (RemoteException | ServiceSpecificException e) {
1329 throw new IllegalStateException(e);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001330 }
1331 }
1332 }
1333
1334 @Override
1335 public void setGlobalAlert(long alertBytes) {
paulhu59148b72019-08-12 16:25:11 +08001336 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001337
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001338 try {
Luke Huangc7bea8662018-08-07 16:04:26 +08001339 mNetdService.bandwidthSetGlobalAlert(alertBytes);
1340 } catch (RemoteException | ServiceSpecificException e) {
1341 throw new IllegalStateException(e);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001342 }
1343 }
1344
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001345 private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
paulhu59148b72019-08-12 16:25:11 +08001346 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001347
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001348 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001349 boolean oldEnable;
1350 SparseBooleanArray quotaList;
1351 synchronized (mRulesLock) {
1352 quotaList = blacklist ? mUidRejectOnMetered : mUidAllowOnMetered;
1353 oldEnable = quotaList.get(uid, false);
1354 }
Felipe Leme65be3022016-03-22 14:53:13 -07001355 if (oldEnable == enable) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001356 // TODO: eventually consider throwing
1357 return;
1358 }
1359
Felipe Leme29e72ea2016-09-08 13:26:55 -07001360 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001361 try {
Luke Huangc7bea8662018-08-07 16:04:26 +08001362 if (blacklist) {
1363 if (enable) {
1364 mNetdService.bandwidthAddNaughtyApp(uid);
1365 } else {
1366 mNetdService.bandwidthRemoveNaughtyApp(uid);
1367 }
1368 } else {
1369 if (enable) {
1370 mNetdService.bandwidthAddNiceApp(uid);
1371 } else {
1372 mNetdService.bandwidthRemoveNiceApp(uid);
1373 }
1374 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001375 synchronized (mRulesLock) {
1376 if (enable) {
1377 quotaList.put(uid, true);
1378 } else {
1379 quotaList.delete(uid);
1380 }
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001381 }
Luke Huangc7bea8662018-08-07 16:04:26 +08001382 } catch (RemoteException | ServiceSpecificException e) {
1383 throw new IllegalStateException(e);
Felipe Leme29e72ea2016-09-08 13:26:55 -07001384 } finally {
1385 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001386 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001387 }
1388 }
1389
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001390 @Override
Felipe Leme65be3022016-03-22 14:53:13 -07001391 public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001392 setUidOnMeteredNetworkList(uid, true, enable);
Felipe Leme65be3022016-03-22 14:53:13 -07001393 }
1394
1395 @Override
1396 public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001397 setUidOnMeteredNetworkList(uid, false, enable);
Felipe Leme65be3022016-03-22 14:53:13 -07001398 }
1399
1400 @Override
1401 public boolean setDataSaverModeEnabled(boolean enable) {
Sehee Parka9139bc2017-12-22 13:54:05 +09001402 mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
1403
Felipe Leme65be3022016-03-22 14:53:13 -07001404 if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
1405 synchronized (mQuotaLock) {
1406 if (mDataSaverMode == enable) {
1407 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
1408 return true;
1409 }
Felipe Leme29e72ea2016-09-08 13:26:55 -07001410 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
Felipe Leme65be3022016-03-22 14:53:13 -07001411 try {
1412 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
1413 if (changed) {
1414 mDataSaverMode = enable;
1415 } else {
1416 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
1417 }
1418 return changed;
1419 } catch (RemoteException e) {
1420 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
1421 return false;
Felipe Leme29e72ea2016-09-08 13:26:55 -07001422 } finally {
1423 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
Felipe Leme65be3022016-03-22 14:53:13 -07001424 }
1425 }
1426 }
1427
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001428 private static UidRangeParcel makeUidRangeParcel(int start, int stop) {
1429 UidRangeParcel range = new UidRangeParcel();
1430 range.start = start;
1431 range.stop = stop;
1432 return range;
1433 }
1434
1435 private static UidRangeParcel[] toStableParcels(UidRange[] ranges) {
1436 UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.length];
1437 for (int i = 0; i < ranges.length; i++) {
1438 stableRanges[i] = makeUidRangeParcel(ranges[i].start, ranges[i].stop);
1439 }
1440 return stableRanges;
1441 }
1442
Felipe Leme65be3022016-03-22 14:53:13 -07001443 @Override
Robin Lee17e61832016-05-09 13:46:28 +01001444 public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
1445 throws ServiceSpecificException {
paulhu59148b72019-08-12 16:25:11 +08001446 NetworkStack.checkNetworkStackPermission(mContext);
Robin Lee17e61832016-05-09 13:46:28 +01001447 try {
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001448 mNetdService.networkRejectNonSecureVpn(add, toStableParcels(uidRanges));
Robin Lee17e61832016-05-09 13:46:28 +01001449 } catch (ServiceSpecificException e) {
1450 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1451 + ": netd command failed", e);
1452 throw e;
1453 } catch (RemoteException e) {
1454 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1455 + ": netd command failed", e);
1456 throw e.rethrowAsRuntimeException();
1457 }
1458 }
1459
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001460 private void applyUidCleartextNetworkPolicy(int uid, int policy) {
Luke Huang473eb872018-07-26 17:33:14 +08001461 final int policyValue;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001462 switch (policy) {
1463 case StrictMode.NETWORK_POLICY_ACCEPT:
Luke Huang473eb872018-07-26 17:33:14 +08001464 policyValue = INetd.PENALTY_POLICY_ACCEPT;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001465 break;
1466 case StrictMode.NETWORK_POLICY_LOG:
Luke Huang473eb872018-07-26 17:33:14 +08001467 policyValue = INetd.PENALTY_POLICY_LOG;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001468 break;
1469 case StrictMode.NETWORK_POLICY_REJECT:
Luke Huang473eb872018-07-26 17:33:14 +08001470 policyValue = INetd.PENALTY_POLICY_REJECT;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001471 break;
1472 default:
1473 throw new IllegalArgumentException("Unknown policy " + policy);
1474 }
1475
1476 try {
Luke Huang473eb872018-07-26 17:33:14 +08001477 mNetdService.strictUidCleartextPenalty(uid, policyValue);
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001478 mUidCleartextPolicy.put(uid, policy);
Luke Huang473eb872018-07-26 17:33:14 +08001479 } catch (RemoteException | ServiceSpecificException e) {
1480 throw new IllegalStateException(e);
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001481 }
1482 }
1483
Robin Lee17e61832016-05-09 13:46:28 +01001484 @Override
Jeff Sharkey605eb792014-11-04 13:34:06 -08001485 public void setUidCleartextNetworkPolicy(int uid, int policy) {
1486 if (Binder.getCallingUid() != uid) {
paulhu59148b72019-08-12 16:25:11 +08001487 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001488 }
1489
1490 synchronized (mQuotaLock) {
1491 final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1492 if (oldPolicy == policy) {
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001493 // This also ensures we won't needlessly apply an ACCEPT policy if we've just
1494 // enabled strict and the underlying iptables rules are empty.
Jeff Sharkey605eb792014-11-04 13:34:06 -08001495 return;
1496 }
1497
Luke Huang473eb872018-07-26 17:33:14 +08001498 // TODO: remove this code after removing prepareNativeDaemon()
Jeff Sharkey605eb792014-11-04 13:34:06 -08001499 if (!mStrictEnabled) {
1500 // Module isn't enabled yet; stash the requested policy away to
1501 // apply later once the daemon is connected.
1502 mUidCleartextPolicy.put(uid, policy);
1503 return;
1504 }
1505
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001506 // netd does not keep state on strict mode policies, and cannot replace a non-accept
1507 // policy without deleting it first. Rather than add state to netd, just always send
1508 // it an accept policy when switching between two non-accept policies.
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001509 // TODO: consider keeping state in netd so we can simplify this code.
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001510 if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT &&
1511 policy != StrictMode.NETWORK_POLICY_ACCEPT) {
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001512 applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001513 }
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001514
1515 applyUidCleartextNetworkPolicy(uid, policy);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001516 }
1517 }
1518
1519 @Override
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001520 public boolean isBandwidthControlEnabled() {
Luke Huang56a03a02018-09-07 12:02:16 +08001521 return true;
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001522 }
1523
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001524 private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
1525 @Override
Lorenzo Colittif1912ca2017-08-17 19:23:08 +09001526 public NetworkStats getTetherStats(int how) {
1527 // We only need to return per-UID stats. Per-device stats are already counted by
1528 // interface counters.
1529 if (how != STATS_PER_UID) {
1530 return new NetworkStats(SystemClock.elapsedRealtime(), 0);
1531 }
1532
Luke Huang13b79e82018-09-26 14:53:42 +08001533 final TetherStatsParcel[] tetherStatsVec;
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001534 try {
Luke Huang13b79e82018-09-26 14:53:42 +08001535 tetherStatsVec = mNetdService.tetherGetStats();
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001536 } catch (RemoteException | ServiceSpecificException e) {
1537 throw new IllegalStateException("problem parsing tethering stats: ", e);
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001538 }
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001539
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001540 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
Luke Huang13b79e82018-09-26 14:53:42 +08001541 tetherStatsVec.length);
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001542 final NetworkStats.Entry entry = new NetworkStats.Entry();
1543
Luke Huang13b79e82018-09-26 14:53:42 +08001544 for (TetherStatsParcel tetherStats : tetherStatsVec) {
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001545 try {
Luke Huang13b79e82018-09-26 14:53:42 +08001546 entry.iface = tetherStats.iface;
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001547 entry.uid = UID_TETHERING;
1548 entry.set = SET_DEFAULT;
1549 entry.tag = TAG_NONE;
Luke Huang13b79e82018-09-26 14:53:42 +08001550 entry.rxBytes = tetherStats.rxBytes;
1551 entry.rxPackets = tetherStats.rxPackets;
1552 entry.txBytes = tetherStats.txBytes;
1553 entry.txPackets = tetherStats.txPackets;
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001554 stats.combineValues(entry);
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001555 } catch (ArrayIndexOutOfBoundsException e) {
Luke Huang13b79e82018-09-26 14:53:42 +08001556 throw new IllegalStateException("invalid tethering stats " + e);
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001557 }
1558 }
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001559
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001560 return stats;
1561 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001562
1563 @Override
1564 public void setInterfaceQuota(String iface, long quotaBytes) {
1565 // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
1566 }
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001567 }
1568
1569 @Override
Lorenzo Colittif1912ca2017-08-17 19:23:08 +09001570 public NetworkStats getNetworkStatsTethering(int how) {
paulhu59148b72019-08-12 16:25:11 +08001571 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001572
1573 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1574 synchronized (mTetheringStatsProviders) {
1575 for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
1576 try {
Lorenzo Colittif1912ca2017-08-17 19:23:08 +09001577 stats.combineAllValues(provider.getTetherStats(how));
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001578 } catch (RemoteException e) {
1579 Log.e(TAG, "Problem reading tethering stats from " +
1580 mTetheringStatsProviders.get(provider) + ": " + e);
1581 }
1582 }
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001583 }
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001584 return stats;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001585 }
1586
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001587 @Override
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04001588 public void addVpnUidRanges(int netId, UidRange[] ranges) {
paulhu59148b72019-08-12 16:25:11 +08001589 NetworkStack.checkNetworkStackPermission(mContext);
Luke Huang8a462ec2018-08-24 20:33:16 +08001590
1591 try {
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001592 mNetdService.networkAddUidRanges(netId, toStableParcels(ranges));
Luke Huang8a462ec2018-08-24 20:33:16 +08001593 } catch (RemoteException | ServiceSpecificException e) {
1594 throw new IllegalStateException(e);
Chad Brubaker3277620a2013-06-12 13:37:30 -07001595 }
1596 }
1597
1598 @Override
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04001599 public void removeVpnUidRanges(int netId, UidRange[] ranges) {
paulhu59148b72019-08-12 16:25:11 +08001600 NetworkStack.checkNetworkStackPermission(mContext);
Luke Huang8a462ec2018-08-24 20:33:16 +08001601 try {
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001602 mNetdService.networkRemoveUidRanges(netId, toStableParcels(ranges));
Luke Huang8a462ec2018-08-24 20:33:16 +08001603 } catch (RemoteException | ServiceSpecificException e) {
1604 throw new IllegalStateException(e);
Chad Brubakercca54c42013-06-27 17:41:38 -07001605 }
1606 }
1607
1608 @Override
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001609 public void setFirewallEnabled(boolean enabled) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07001610 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001611 try {
Luke Huanga241db92018-07-31 20:15:24 +08001612 mNetdService.firewallSetFirewallType(
1613 enabled ? INetd.FIREWALL_WHITELIST : INetd.FIREWALL_BLACKLIST);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001614 mFirewallEnabled = enabled;
Luke Huanga241db92018-07-31 20:15:24 +08001615 } catch (RemoteException | ServiceSpecificException e) {
1616 throw new IllegalStateException(e);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001617 }
1618 }
1619
1620 @Override
1621 public boolean isFirewallEnabled() {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07001622 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001623 return mFirewallEnabled;
1624 }
1625
1626 @Override
Jeff Sharkey2c092982012-08-24 11:44:40 -07001627 public void setFirewallInterfaceRule(String iface, boolean allow) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07001628 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001629 Preconditions.checkState(mFirewallEnabled);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001630 try {
Luke Huanga241db92018-07-31 20:15:24 +08001631 mNetdService.firewallSetInterfaceRule(iface,
1632 allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY);
1633 } catch (RemoteException | ServiceSpecificException e) {
1634 throw new IllegalStateException(e);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001635 }
1636 }
1637
Lorenzo Colitti3fef7232016-04-29 18:00:03 +09001638 private void closeSocketsForFirewallChainLocked(int chain, String chainName) {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001639 // UID ranges to close sockets on.
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001640 UidRangeParcel[] ranges;
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001641 // UID ranges whose sockets we won't touch.
1642 int[] exemptUids;
1643
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001644 int numUids = 0;
Luke Huanga241db92018-07-31 20:15:24 +08001645 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001646 if (getFirewallType(chain) == FIREWALL_WHITELIST) {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001647 // Close all sockets on all non-system UIDs...
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001648 ranges = new UidRangeParcel[] {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001649 // TODO: is there a better way of finding all existing users? If so, we could
1650 // specify their ranges here.
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001651 makeUidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001652 };
1653 // ... except for the UIDs that have allow rules.
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001654 synchronized (mRulesLock) {
1655 final SparseIntArray rules = getUidFirewallRulesLR(chain);
1656 exemptUids = new int[rules.size()];
1657 for (int i = 0; i < exemptUids.length; i++) {
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001658 if (rules.valueAt(i) == FIREWALL_RULE_ALLOW) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001659 exemptUids[numUids] = rules.keyAt(i);
1660 numUids++;
1661 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001662 }
1663 }
1664 // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
1665 // But the code does not guarantee this in any way, and at least in one case - if we add
1666 // a UID rule to the firewall, and then disable the firewall - the chains can contain
1667 // the wrong type of rule. In this case, don't close connections that we shouldn't.
1668 //
1669 // TODO: tighten up this code by ensuring we never set the wrong type of rule, and
1670 // fix setFirewallEnabled to grab mQuotaLock and clear rules.
1671 if (numUids != exemptUids.length) {
1672 exemptUids = Arrays.copyOf(exemptUids, numUids);
1673 }
1674 } else {
1675 // Close sockets for every UID that has a deny rule...
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001676 synchronized (mRulesLock) {
1677 final SparseIntArray rules = getUidFirewallRulesLR(chain);
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001678 ranges = new UidRangeParcel[rules.size()];
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001679 for (int i = 0; i < ranges.length; i++) {
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001680 if (rules.valueAt(i) == FIREWALL_RULE_DENY) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001681 int uid = rules.keyAt(i);
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001682 ranges[numUids] = makeUidRangeParcel(uid, uid);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001683 numUids++;
1684 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001685 }
1686 }
1687 // As above; usually numUids == ranges.length, but not always.
1688 if (numUids != ranges.length) {
1689 ranges = Arrays.copyOf(ranges, numUids);
1690 }
1691 // ... with no exceptions.
1692 exemptUids = new int[0];
1693 }
1694
1695 try {
1696 mNetdService.socketDestroy(ranges, exemptUids);
1697 } catch(RemoteException | ServiceSpecificException e) {
1698 Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e);
1699 }
1700 }
1701
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001702 @Override
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001703 public void setFirewallChainEnabled(int chain, boolean enable) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07001704 enforceSystemUid();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001705 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001706 synchronized (mRulesLock) {
1707 if (getFirewallChainState(chain) == enable) {
1708 // All is the same, nothing to do. This relies on the fact that netd has child
1709 // chains default detached.
1710 return;
1711 }
1712 setFirewallChainState(chain, enable);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001713 }
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001714
Luke Huang615e1022018-10-25 11:54:05 +09001715 final String chainName = getFirewallChainName(chain);
Luke Huanga241db92018-07-31 20:15:24 +08001716 if (chain == FIREWALL_CHAIN_NONE) {
Luke Huang615e1022018-10-25 11:54:05 +09001717 throw new IllegalArgumentException("Bad child chain: " + chainName);
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001718 }
1719
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001720 try {
Luke Huanga241db92018-07-31 20:15:24 +08001721 mNetdService.firewallEnableChildChain(chain, enable);
1722 } catch (RemoteException | ServiceSpecificException e) {
1723 throw new IllegalStateException(e);
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001724 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001725
1726 // Close any sockets that were opened by the affected UIDs. This has to be done after
1727 // disabling network connectivity, in case they react to the socket close by reopening
1728 // the connection and race with the iptables commands that enable the firewall. All
1729 // whitelist and blacklist chains allow RSTs through.
1730 if (enable) {
Luke Huang615e1022018-10-25 11:54:05 +09001731 closeSocketsForFirewallChainLocked(chain, chainName);
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001732 }
Amith Yamasani15e472352015-04-24 19:06:07 -07001733 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001734 }
1735
Luke Huanga241db92018-07-31 20:15:24 +08001736 private String getFirewallChainName(int chain) {
1737 switch (chain) {
1738 case FIREWALL_CHAIN_STANDBY:
1739 return FIREWALL_CHAIN_NAME_STANDBY;
1740 case FIREWALL_CHAIN_DOZABLE:
1741 return FIREWALL_CHAIN_NAME_DOZABLE;
1742 case FIREWALL_CHAIN_POWERSAVE:
1743 return FIREWALL_CHAIN_NAME_POWERSAVE;
1744 default:
1745 throw new IllegalArgumentException("Bad child chain: " + chain);
1746 }
1747 }
1748
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001749 private int getFirewallType(int chain) {
1750 switch (chain) {
1751 case FIREWALL_CHAIN_STANDBY:
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001752 return FIREWALL_BLACKLIST;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001753 case FIREWALL_CHAIN_DOZABLE:
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001754 return FIREWALL_WHITELIST;
Felipe Leme011b98f2016-02-10 17:28:31 -08001755 case FIREWALL_CHAIN_POWERSAVE:
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001756 return FIREWALL_WHITELIST;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001757 default:
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001758 return isFirewallEnabled() ? FIREWALL_WHITELIST : FIREWALL_BLACKLIST;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001759 }
1760 }
1761
1762 @Override
1763 public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
1764 enforceSystemUid();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001765 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001766 synchronized (mRulesLock) {
1767 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
1768 SparseIntArray newRules = new SparseIntArray();
1769 // apply new set of rules
1770 for (int index = uids.length - 1; index >= 0; --index) {
1771 int uid = uids[index];
1772 int rule = rules[index];
1773 updateFirewallUidRuleLocked(chain, uid, rule);
1774 newRules.put(uid, rule);
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001775 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001776 // collect the rules to remove.
1777 SparseIntArray rulesToRemove = new SparseIntArray();
1778 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
1779 int uid = uidFirewallRules.keyAt(index);
1780 if (newRules.indexOfKey(uid) < 0) {
1781 rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
1782 }
1783 }
1784 // remove dead rules
1785 for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
1786 int uid = rulesToRemove.keyAt(index);
1787 updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
1788 }
Felipe Lemea701cad2016-05-12 09:58:14 -07001789 }
1790 try {
1791 switch (chain) {
1792 case FIREWALL_CHAIN_DOZABLE:
1793 mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
1794 break;
1795 case FIREWALL_CHAIN_STANDBY:
1796 mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
1797 break;
1798 case FIREWALL_CHAIN_POWERSAVE:
1799 mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
1800 break;
1801 case FIREWALL_CHAIN_NONE:
1802 default:
1803 Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
1804 }
1805 } catch (RemoteException e) {
1806 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001807 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001808 }
1809 }
1810
1811 @Override
1812 public void setFirewallUidRule(int chain, int uid, int rule) {
1813 enforceSystemUid();
Felipe Lemea701cad2016-05-12 09:58:14 -07001814 synchronized (mQuotaLock) {
1815 setFirewallUidRuleLocked(chain, uid, rule);
1816 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001817 }
1818
Felipe Lemea701cad2016-05-12 09:58:14 -07001819 private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
1820 if (updateFirewallUidRuleLocked(chain, uid, rule)) {
Luke Huanga241db92018-07-31 20:15:24 +08001821 final int ruleType = getFirewallRuleType(chain, rule);
Amith Yamasani15e472352015-04-24 19:06:07 -07001822 try {
Luke Huanga241db92018-07-31 20:15:24 +08001823 mNetdService.firewallSetUidRule(chain, uid, ruleType);
1824 } catch (RemoteException | ServiceSpecificException e) {
1825 throw new IllegalStateException(e);
Amith Yamasani15e472352015-04-24 19:06:07 -07001826 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001827 }
1828 }
1829
Felipe Lemea701cad2016-05-12 09:58:14 -07001830 // TODO: now that netd supports batching, NMS should not keep these data structures anymore...
1831 private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001832 synchronized (mRulesLock) {
1833 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
Felipe Lemea701cad2016-05-12 09:58:14 -07001834
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001835 final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
1836 if (DBG) {
1837 Slog.d(TAG, "oldRule = " + oldUidFirewallRule
1838 + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain);
1839 }
1840 if (oldUidFirewallRule == rule) {
1841 if (DBG) Slog.d(TAG, "!!!!! Skipping change");
1842 // TODO: eventually consider throwing
1843 return false;
1844 }
Felipe Lemea701cad2016-05-12 09:58:14 -07001845
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001846 String ruleName = getFirewallRuleName(chain, rule);
1847 String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
Felipe Lemea701cad2016-05-12 09:58:14 -07001848
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001849 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
1850 uidFirewallRules.delete(uid);
1851 } else {
1852 uidFirewallRules.put(uid, rule);
1853 }
1854 return !ruleName.equals(oldRuleName);
Felipe Lemea701cad2016-05-12 09:58:14 -07001855 }
Felipe Lemea701cad2016-05-12 09:58:14 -07001856 }
1857
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001858 private @NonNull String getFirewallRuleName(int chain, int rule) {
1859 String ruleName;
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001860 if (getFirewallType(chain) == FIREWALL_WHITELIST) {
1861 if (rule == FIREWALL_RULE_ALLOW) {
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001862 ruleName = "allow";
1863 } else {
1864 ruleName = "deny";
1865 }
1866 } else { // Blacklist mode
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001867 if (rule == FIREWALL_RULE_DENY) {
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001868 ruleName = "deny";
1869 } else {
1870 ruleName = "allow";
1871 }
1872 }
1873 return ruleName;
1874 }
1875
Andreas Gampeaae5aa32018-07-20 12:55:38 -07001876 @GuardedBy("mRulesLock")
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001877 private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) {
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001878 switch (chain) {
1879 case FIREWALL_CHAIN_STANDBY:
1880 return mUidFirewallStandbyRules;
1881 case FIREWALL_CHAIN_DOZABLE:
1882 return mUidFirewallDozableRules;
Felipe Leme011b98f2016-02-10 17:28:31 -08001883 case FIREWALL_CHAIN_POWERSAVE:
1884 return mUidFirewallPowerSaveRules;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001885 case FIREWALL_CHAIN_NONE:
1886 return mUidFirewallRules;
1887 default:
1888 throw new IllegalArgumentException("Unknown chain:" + chain);
1889 }
1890 }
1891
Luke Huanga241db92018-07-31 20:15:24 +08001892 private int getFirewallRuleType(int chain, int rule) {
Luke Huang615e1022018-10-25 11:54:05 +09001893 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001894 return getFirewallType(chain) == FIREWALL_WHITELIST
Luke Huang615e1022018-10-25 11:54:05 +09001895 ? INetd.FIREWALL_RULE_DENY : INetd.FIREWALL_RULE_ALLOW;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001896 }
Luke Huang615e1022018-10-25 11:54:05 +09001897 return rule;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001898 }
1899
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07001900 private static void enforceSystemUid() {
1901 final int uid = Binder.getCallingUid();
1902 if (uid != Process.SYSTEM_UID) {
1903 throw new SecurityException("Only available to AID_SYSTEM");
1904 }
1905 }
1906
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001907 @Override
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001908 public void registerNetworkActivityListener(INetworkActivityListener listener) {
1909 mNetworkActivityListeners.register(listener);
1910 }
1911
1912 @Override
1913 public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
1914 mNetworkActivityListeners.unregister(listener);
1915 }
1916
1917 @Override
1918 public boolean isNetworkActive() {
1919 synchronized (mNetworkActivityListeners) {
1920 return mNetworkActive || mActiveIdleTimers.isEmpty();
1921 }
1922 }
1923
1924 private void reportNetworkActive() {
1925 final int length = mNetworkActivityListeners.beginBroadcast();
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07001926 try {
1927 for (int i = 0; i < length; i++) {
1928 try {
1929 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
Felipe Leme03e689d2016-03-02 16:17:38 -08001930 } catch (RemoteException | RuntimeException e) {
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07001931 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001932 }
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07001933 } finally {
1934 mNetworkActivityListeners.finishBroadcast();
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001935 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001936 }
1937
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001938 @Override
1939 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06001940 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001941
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07001942 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
1943 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
1944 pw.print("mNetworkActive="); pw.println(mNetworkActive);
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001945
1946 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001947 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
1948 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
Felipe Leme65be3022016-03-22 14:53:13 -07001949 pw.print("Data saver mode: "); pw.println(mDataSaverMode);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001950 synchronized (mRulesLock) {
1951 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
1952 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
1953 }
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001954 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001955
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001956 synchronized (mRulesLock) {
Felipe Leme011b98f2016-02-10 17:28:31 -08001957 dumpUidFirewallRule(pw, "", mUidFirewallRules);
Amith Yamasani15e472352015-04-24 19:06:07 -07001958
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001959 pw.print("UID firewall standby chain enabled: "); pw.println(
1960 getFirewallChainState(FIREWALL_CHAIN_STANDBY));
Felipe Leme011b98f2016-02-10 17:28:31 -08001961 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001962
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001963 pw.print("UID firewall dozable chain enabled: "); pw.println(
1964 getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
Felipe Leme011b98f2016-02-10 17:28:31 -08001965 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
Felipe Leme011b98f2016-02-10 17:28:31 -08001966
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001967 pw.println("UID firewall powersave chain enabled: " +
1968 getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
Felipe Leme011b98f2016-02-10 17:28:31 -08001969 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001970 }
1971
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001972 synchronized (mIdleTimerLock) {
1973 pw.println("Idle timers:");
1974 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
1975 pw.print(" "); pw.print(ent.getKey()); pw.println(":");
1976 IdleTimerParams params = ent.getValue();
1977 pw.print(" timeout="); pw.print(params.timeout);
1978 pw.print(" type="); pw.print(params.type);
1979 pw.print(" networkCount="); pw.println(params.networkCount);
1980 }
1981 }
1982
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001983 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
Felipe Leme65be3022016-03-22 14:53:13 -07001984 pw.print("Netd service status: " );
1985 if (mNetdService == null) {
1986 pw.println("disconnected");
1987 } else {
1988 try {
1989 final boolean alive = mNetdService.isAlive();
1990 pw.println(alive ? "alive": "dead");
1991 } catch (RemoteException e) {
1992 pw.println("unreachable");
1993 }
1994 }
1995 }
1996
1997 private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
1998 pw.print("UID bandwith control ");
1999 pw.print(name);
2000 pw.print(" rule: [");
2001 final int size = list.size();
2002 for (int i = 0; i < size; i++) {
2003 pw.print(list.keyAt(i));
2004 if (i < size - 1) pw.print(",");
2005 }
2006 pw.println("]");
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002007 }
Robert Greenwalt9ba9c582014-03-19 17:56:12 -07002008
Felipe Leme011b98f2016-02-10 17:28:31 -08002009 private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002010 pw.print("UID firewall ");
Felipe Leme011b98f2016-02-10 17:28:31 -08002011 pw.print(name);
2012 pw.print(" rule: [");
2013 final int size = rules.size();
2014 for (int i = 0; i < size; i++) {
2015 pw.print(rules.keyAt(i));
2016 pw.print(":");
2017 pw.print(rules.valueAt(i));
2018 if (i < size - 1) pw.print(",");
2019 }
2020 pw.println("]");
2021 }
2022
Robert Greenwalt568891d2014-04-04 13:38:00 -07002023 @Override
Paul Jensen992f2522014-04-28 10:33:11 -04002024 public void addInterfaceToNetwork(String iface, int netId) {
Luke Huang8a462ec2018-08-24 20:33:16 +08002025 modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, netId, iface);
Paul Jensen992f2522014-04-28 10:33:11 -04002026 }
2027
2028 @Override
2029 public void removeInterfaceFromNetwork(String iface, int netId) {
Luke Huang8a462ec2018-08-24 20:33:16 +08002030 modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, netId, iface);
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002031 }
Paul Jensen992f2522014-04-28 10:33:11 -04002032
Luke Huang8a462ec2018-08-24 20:33:16 +08002033 private void modifyInterfaceInNetwork(boolean add, int netId, String iface) {
paulhu59148b72019-08-12 16:25:11 +08002034 NetworkStack.checkNetworkStackPermission(mContext);
Paul Jensen992f2522014-04-28 10:33:11 -04002035 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002036 if (add) {
2037 mNetdService.networkAddInterface(netId, iface);
2038 } else {
2039 mNetdService.networkRemoveInterface(netId, iface);
2040 }
2041 } catch (RemoteException | ServiceSpecificException e) {
2042 throw new IllegalStateException(e);
Paul Jensen992f2522014-04-28 10:33:11 -04002043 }
2044 }
2045
2046 @Override
Robert Greenwalt913c8952014-04-07 17:36:35 -07002047 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
paulhu59148b72019-08-12 16:25:11 +08002048 NetworkStack.checkNetworkStackPermission(mContext);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002049
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -07002050 final LinkAddress la = routeInfo.getDestinationLinkAddress();
Luke Huang8a462ec2018-08-24 20:33:16 +08002051 final String ifName = routeInfo.getInterface();
2052 final String dst = la.toString();
2053 final String nextHop;
Robert Greenwalt568891d2014-04-04 13:38:00 -07002054
Luke Huang8a462ec2018-08-24 20:33:16 +08002055 if (routeInfo.hasGateway()) {
2056 nextHop = routeInfo.getGateway().getHostAddress();
2057 } else {
2058 nextHop = "";
2059 }
Robert Greenwalt568891d2014-04-04 13:38:00 -07002060 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002061 mNetdService.networkAddLegacyRoute(netId, ifName, dst, nextHop, uid);
2062 } catch (RemoteException | ServiceSpecificException e) {
2063 throw new IllegalStateException(e);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002064 }
2065 }
2066
2067 @Override
Sreeram Ramachandranf047f2a2014-04-15 16:04:26 -07002068 public void setDefaultNetId(int netId) {
paulhu59148b72019-08-12 16:25:11 +08002069 NetworkStack.checkNetworkStackPermission(mContext);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002070
2071 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002072 mNetdService.networkSetDefault(netId);
2073 } catch (RemoteException | ServiceSpecificException e) {
2074 throw new IllegalStateException(e);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002075 }
2076 }
2077
2078 @Override
2079 public void clearDefaultNetId() {
paulhu59148b72019-08-12 16:25:11 +08002080 NetworkStack.checkNetworkStackPermission(mContext);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002081
2082 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002083 mNetdService.networkClearDefault();
2084 } catch (RemoteException | ServiceSpecificException e) {
2085 throw new IllegalStateException(e);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002086 }
2087 }
2088
2089 @Override
Luke Huang8a462ec2018-08-24 20:33:16 +08002090 public void setNetworkPermission(int netId, int permission) {
paulhu59148b72019-08-12 16:25:11 +08002091 NetworkStack.checkNetworkStackPermission(mContext);
Paul Jensen487ffe72015-07-24 15:57:11 -04002092
2093 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002094 mNetdService.networkSetPermissionForNetwork(netId, permission);
2095 } catch (RemoteException | ServiceSpecificException e) {
2096 throw new IllegalStateException(e);
Paul Jensen487ffe72015-07-24 15:57:11 -04002097 }
2098 }
2099
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002100 @Override
2101 public void allowProtect(int uid) {
paulhu59148b72019-08-12 16:25:11 +08002102 NetworkStack.checkNetworkStackPermission(mContext);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002103
2104 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002105 mNetdService.networkSetProtectAllow(uid);
2106 } catch (RemoteException | ServiceSpecificException e) {
2107 throw new IllegalStateException(e);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002108 }
2109 }
2110
2111 @Override
2112 public void denyProtect(int uid) {
paulhu59148b72019-08-12 16:25:11 +08002113 NetworkStack.checkNetworkStackPermission(mContext);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002114
2115 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002116 mNetdService.networkSetProtectDeny(uid);
2117 } catch (RemoteException | ServiceSpecificException e) {
2118 throw new IllegalStateException(e);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002119 }
2120 }
2121
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002122 @Override
2123 public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
Luke Huang706d7ab2018-10-16 15:42:15 +08002124 modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002125
2126 for (RouteInfo route : routes) {
2127 if (!route.isDefaultRoute()) {
Luke Huang706d7ab2018-10-16 15:42:15 +08002128 modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route);
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002129 }
2130 }
Jimmy Chen086779d2019-03-07 14:15:36 +08002131
2132 // IPv6 link local should be activated always.
2133 modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID,
2134 new RouteInfo(new IpPrefix("fe80::/64"), null, iface));
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002135 }
2136
2137 @Override
2138 public void removeInterfaceFromLocalNetwork(String iface) {
Luke Huang706d7ab2018-10-16 15:42:15 +08002139 modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, iface);
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002140 }
Erik Kline6599ee82016-07-17 21:28:39 +09002141
2142 @Override
2143 public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
2144 int failures = 0;
2145
2146 for (RouteInfo route : routes) {
2147 try {
Luke Huang706d7ab2018-10-16 15:42:15 +08002148 modifyRoute(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, route);
Erik Kline6599ee82016-07-17 21:28:39 +09002149 } catch (IllegalStateException e) {
2150 failures++;
2151 }
2152 }
2153
2154 return failures;
2155 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002156
Sudheer Shankab8f23162017-08-04 13:30:10 -07002157 @Override
2158 public boolean isNetworkRestricted(int uid) {
paulhu59148b72019-08-12 16:25:11 +08002159 mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
Sudheer Shankab8f23162017-08-04 13:30:10 -07002160 return isNetworkRestrictedInternal(uid);
2161 }
2162
2163 private boolean isNetworkRestrictedInternal(int uid) {
2164 synchronized (mRulesLock) {
2165 if (getFirewallChainState(FIREWALL_CHAIN_STANDBY)
2166 && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) {
2167 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode");
2168 return true;
2169 }
2170 if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE)
2171 && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) {
2172 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode");
2173 return true;
2174 }
2175 if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)
2176 && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) {
2177 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
2178 return true;
2179 }
2180 if (mUidRejectOnMetered.get(uid)) {
2181 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
2182 + " in the background");
2183 return true;
2184 }
2185 if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) {
2186 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode");
2187 return true;
2188 }
2189 return false;
2190 }
2191 }
2192
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002193 private void setFirewallChainState(int chain, boolean state) {
2194 synchronized (mRulesLock) {
2195 mFirewallChainStates.put(chain, state);
2196 }
2197 }
2198
2199 private boolean getFirewallChainState(int chain) {
2200 synchronized (mRulesLock) {
2201 return mFirewallChainStates.get(chain);
2202 }
2203 }
2204
2205 @VisibleForTesting
2206 class LocalService extends NetworkManagementInternal {
2207 @Override
2208 public boolean isNetworkRestrictedForUid(int uid) {
Sudheer Shankab8f23162017-08-04 13:30:10 -07002209 return isNetworkRestrictedInternal(uid);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002210 }
2211 }
2212
2213 @VisibleForTesting
2214 Injector getInjector() {
2215 return new Injector();
2216 }
2217
2218 @VisibleForTesting
2219 class Injector {
2220 void setDataSaverMode(boolean dataSaverMode) {
2221 mDataSaverMode = dataSaverMode;
2222 }
2223
2224 void setFirewallChainState(int chain, boolean state) {
2225 NetworkManagementService.this.setFirewallChainState(chain, state);
2226 }
2227
2228 void setFirewallRule(int chain, int uid, int rule) {
2229 synchronized (mRulesLock) {
2230 getUidFirewallRulesLR(chain).put(uid, rule);
2231 }
2232 }
2233
2234 void setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable) {
2235 synchronized (mRulesLock) {
2236 if (blacklist) {
2237 mUidRejectOnMetered.put(uid, enable);
2238 } else {
2239 mUidAllowOnMetered.put(uid, enable);
2240 }
2241 }
2242 }
2243
2244 void reset() {
2245 synchronized (mRulesLock) {
2246 setDataSaverMode(false);
2247 final int[] chains = {
2248 FIREWALL_CHAIN_DOZABLE,
2249 FIREWALL_CHAIN_STANDBY,
2250 FIREWALL_CHAIN_POWERSAVE
2251 };
2252 for (int chain : chains) {
2253 setFirewallChainState(chain, false);
2254 getUidFirewallRulesLR(chain).clear();
2255 }
2256 mUidAllowOnMetered.clear();
2257 mUidRejectOnMetered.clear();
2258 }
2259 }
2260 }
San Mehat873f2142010-01-14 10:25:07 -08002261}