• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.server;
18 
19 import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
20 import static android.Manifest.permission.DUMP;
21 import static android.Manifest.permission.NETWORK_STACK;
22 import static android.Manifest.permission.SHUTDOWN;
23 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
24 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
25 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
26 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
27 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
28 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
29 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
30 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
31 import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
32 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
33 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
34 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
35 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST;
36 import static android.net.NetworkStats.SET_DEFAULT;
37 import static android.net.NetworkStats.STATS_PER_UID;
38 import static android.net.NetworkStats.TAG_ALL;
39 import static android.net.NetworkStats.TAG_NONE;
40 import static android.net.NetworkStats.UID_ALL;
41 import static android.net.TrafficStats.UID_TETHERING;
42 import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult;
43 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
44 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
45 import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult;
46 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult;
47 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult;
48 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult;
49 import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult;
50 import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
51 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
52 
53 import android.annotation.NonNull;
54 import android.app.ActivityManager;
55 import android.content.ContentResolver;
56 import android.content.Context;
57 import android.net.ConnectivityManager;
58 import android.net.INetd;
59 import android.net.INetworkManagementEventObserver;
60 import android.net.ITetheringStatsProvider;
61 import android.net.InterfaceConfiguration;
62 import android.net.IpPrefix;
63 import android.net.LinkAddress;
64 import android.net.Network;
65 import android.net.NetworkPolicyManager;
66 import android.net.NetworkStats;
67 import android.net.NetworkUtils;
68 import android.net.RouteInfo;
69 import android.net.UidRange;
70 import android.net.util.NetdService;
71 import android.net.wifi.WifiConfiguration;
72 import android.net.wifi.WifiConfiguration.KeyMgmt;
73 import android.os.BatteryStats;
74 import android.os.Binder;
75 import android.os.Handler;
76 import android.os.INetworkActivityListener;
77 import android.os.INetworkManagementService;
78 import android.os.PowerManager;
79 import android.os.Process;
80 import android.os.RemoteCallbackList;
81 import android.os.RemoteException;
82 import android.os.ServiceManager;
83 import android.os.ServiceSpecificException;
84 import android.os.StrictMode;
85 import android.os.SystemClock;
86 import android.os.SystemProperties;
87 import android.os.Trace;
88 import android.provider.Settings;
89 import android.telephony.DataConnectionRealTimeInfo;
90 import android.telephony.PhoneStateListener;
91 import android.telephony.SubscriptionManager;
92 import android.telephony.TelephonyManager;
93 import android.util.Log;
94 import android.util.Slog;
95 import android.util.SparseBooleanArray;
96 import android.util.SparseIntArray;
97 
98 import com.android.internal.annotations.GuardedBy;
99 import com.android.internal.annotations.VisibleForTesting;
100 import com.android.internal.app.IBatteryStats;
101 import com.android.internal.net.NetworkStatsFactory;
102 import com.android.internal.util.DumpUtils;
103 import com.android.internal.util.HexDump;
104 import com.android.internal.util.Preconditions;
105 import com.android.server.NativeDaemonConnector.Command;
106 import com.android.server.NativeDaemonConnector.SensitiveArg;
107 import com.google.android.collect.Maps;
108 
109 import java.io.BufferedReader;
110 import java.io.DataInputStream;
111 import java.io.File;
112 import java.io.FileDescriptor;
113 import java.io.FileInputStream;
114 import java.io.IOException;
115 import java.io.InputStreamReader;
116 import java.io.PrintWriter;
117 import java.net.InetAddress;
118 import java.net.InterfaceAddress;
119 import java.net.NetworkInterface;
120 import java.net.SocketException;
121 import java.util.ArrayList;
122 import java.util.Arrays;
123 import java.util.HashMap;
124 import java.util.List;
125 import java.util.Map;
126 import java.util.NoSuchElementException;
127 import java.util.StringTokenizer;
128 import java.util.concurrent.CountDownLatch;
129 
130 /**
131  * @hide
132  */
133 public class NetworkManagementService extends INetworkManagementService.Stub
134         implements Watchdog.Monitor {
135     private static final String TAG = "NetworkManagement";
136     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
137     private static final String NETD_TAG = "NetdConnector";
138     private static final String NETD_SERVICE_NAME = "netd";
139 
140     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
141 
142     /**
143      * Name representing {@link #setGlobalAlert(long)} limit when delivered to
144      * {@link INetworkManagementEventObserver#limitReached(String, String)}.
145      */
146     public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
147 
148     /**
149      * String to pass to netd to indicate that a network is only accessible
150      * to apps that have the CHANGE_NETWORK_STATE permission.
151      */
152     public static final String PERMISSION_NETWORK = "NETWORK";
153 
154     /**
155      * String to pass to netd to indicate that a network is only
156      * accessible to system apps and those with the CONNECTIVITY_INTERNAL
157      * permission.
158      */
159     public static final String PERMISSION_SYSTEM = "SYSTEM";
160 
161     static class NetdResponseCode {
162         /* Keep in sync with system/netd/server/ResponseCode.h */
163         public static final int InterfaceListResult       = 110;
164         public static final int TetherInterfaceListResult = 111;
165         public static final int TetherDnsFwdTgtListResult = 112;
166         public static final int TtyListResult             = 113;
167         public static final int TetheringStatsListResult  = 114;
168 
169         public static final int TetherStatusResult        = 210;
170         public static final int IpFwdStatusResult         = 211;
171         public static final int InterfaceGetCfgResult     = 213;
172         public static final int SoftapStatusResult        = 214;
173         public static final int InterfaceRxCounterResult  = 216;
174         public static final int InterfaceTxCounterResult  = 217;
175         public static final int QuotaCounterResult        = 220;
176         public static final int TetheringStatsResult      = 221;
177         public static final int DnsProxyQueryResult       = 222;
178         public static final int ClatdStatusResult         = 223;
179 
180         public static final int InterfaceChange           = 600;
181         public static final int BandwidthControl          = 601;
182         public static final int InterfaceClassActivity    = 613;
183         public static final int InterfaceAddressChange    = 614;
184         public static final int InterfaceDnsServerInfo    = 615;
185         public static final int RouteChange               = 616;
186         public static final int StrictCleartext           = 617;
187     }
188 
189     /* Defaults for resolver parameters. */
190     public static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
191     public static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
192     public static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
193     public static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
194 
195     /**
196      * String indicating a softap command.
197      */
198     static final String SOFT_AP_COMMAND = "softap";
199 
200     /**
201      * String passed back to netd connector indicating softap command success.
202      */
203     static final String SOFT_AP_COMMAND_SUCCESS = "Ok";
204 
205     static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
206 
207     /**
208      * Binder context for this service
209      */
210     private final Context mContext;
211 
212     /**
213      * connector object for communicating with netd
214      */
215     private final NativeDaemonConnector mConnector;
216 
217     private final Handler mFgHandler;
218     private final Handler mDaemonHandler;
219 
220     private INetd mNetdService;
221 
222     private IBatteryStats mBatteryStats;
223 
224     private final Thread mThread;
225     private CountDownLatch mConnectedSignal = new CountDownLatch(1);
226 
227     private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
228             new RemoteCallbackList<>();
229 
230     private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
231 
232     @GuardedBy("mTetheringStatsProviders")
233     private final HashMap<ITetheringStatsProvider, String>
234             mTetheringStatsProviders = Maps.newHashMap();
235 
236     /**
237      * If both locks need to be held, then they should be obtained in the order:
238      * first {@link #mQuotaLock} and then {@link #mRulesLock}.
239      */
240     private final Object mQuotaLock = new Object();
241     private final Object mRulesLock = new Object();
242 
243     /** Set of interfaces with active quotas. */
244     @GuardedBy("mQuotaLock")
245     private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
246     /** Set of interfaces with active alerts. */
247     @GuardedBy("mQuotaLock")
248     private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
249     /** Set of UIDs blacklisted on metered networks. */
250     @GuardedBy("mRulesLock")
251     private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
252     /** Set of UIDs whitelisted on metered networks. */
253     @GuardedBy("mRulesLock")
254     private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
255     /** Set of UIDs with cleartext penalties. */
256     @GuardedBy("mQuotaLock")
257     private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
258     /** Set of UIDs that are to be blocked/allowed by firewall controller. */
259     @GuardedBy("mRulesLock")
260     private SparseIntArray mUidFirewallRules = new SparseIntArray();
261     /**
262      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
263      * to application idles.
264      */
265     @GuardedBy("mRulesLock")
266     private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
267     /**
268      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
269      * to device idles.
270      */
271     @GuardedBy("mRulesLock")
272     private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
273     /**
274      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
275      * to device on power-save mode.
276      */
277     @GuardedBy("mRulesLock")
278     private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
279     /** Set of states for the child firewall chains. True if the chain is active. */
280     @GuardedBy("mRulesLock")
281     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
282 
283     @GuardedBy("mQuotaLock")
284     private volatile boolean mDataSaverMode;
285 
286     private final Object mIdleTimerLock = new Object();
287     /** Set of interfaces with active idle timers. */
288     private static class IdleTimerParams {
289         public final int timeout;
290         public final int type;
291         public int networkCount;
292 
IdleTimerParams(int timeout, int type)293         IdleTimerParams(int timeout, int type) {
294             this.timeout = timeout;
295             this.type = type;
296             this.networkCount = 1;
297         }
298     }
299     private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
300 
301     private volatile boolean mBandwidthControlEnabled;
302     private volatile boolean mFirewallEnabled;
303     private volatile boolean mStrictEnabled;
304 
305     private boolean mMobileActivityFromRadio = false;
306     private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
307     private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
308 
309     private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
310             new RemoteCallbackList<>();
311     private boolean mNetworkActive;
312 
313     /**
314      * Constructs a new NetworkManagementService instance
315      *
316      * @param context  Binder context for this service
317      */
NetworkManagementService(Context context, String socket)318     private NetworkManagementService(Context context, String socket) {
319         mContext = context;
320 
321         // make sure this is on the same looper as our NativeDaemonConnector for sync purposes
322         mFgHandler = new Handler(FgThread.get().getLooper());
323 
324         // Don't need this wake lock, since we now have a time stamp for when
325         // the network actually went inactive.  (It might be nice to still do this,
326         // but I don't want to do it through the power manager because that pollutes the
327         // battery stats history with pointless noise.)
328         //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
329         PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
330 
331         mConnector = new NativeDaemonConnector(
332                 new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
333                 FgThread.get().getLooper());
334         mThread = new Thread(mConnector, NETD_TAG);
335 
336         mDaemonHandler = new Handler(FgThread.get().getLooper());
337 
338         // Add ourself to the Watchdog monitors.
339         Watchdog.getInstance().addMonitor(this);
340 
341         LocalServices.addService(NetworkManagementInternal.class, new LocalService());
342 
343         synchronized (mTetheringStatsProviders) {
344             mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
345         }
346     }
347 
348     @VisibleForTesting
NetworkManagementService()349     NetworkManagementService() {
350         mConnector = null;
351         mContext = null;
352         mDaemonHandler = null;
353         mFgHandler = null;
354         mThread = null;
355     }
356 
create(Context context, String socket)357     static NetworkManagementService create(Context context, String socket)
358             throws InterruptedException {
359         final NetworkManagementService service = new NetworkManagementService(context, socket);
360         final CountDownLatch connectedSignal = service.mConnectedSignal;
361         if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
362         service.mThread.start();
363         if (DBG) Slog.d(TAG, "Awaiting socket connection");
364         connectedSignal.await();
365         if (DBG) Slog.d(TAG, "Connected");
366         if (DBG) Slog.d(TAG, "Connecting native netd service");
367         service.connectNativeNetdService();
368         if (DBG) Slog.d(TAG, "Connected");
369         return service;
370     }
371 
create(Context context)372     public static NetworkManagementService create(Context context) throws InterruptedException {
373         return create(context, NETD_SERVICE_NAME);
374     }
375 
systemReady()376     public void systemReady() {
377         if (DBG) {
378             final long start = System.currentTimeMillis();
379             prepareNativeDaemon();
380             final long delta = System.currentTimeMillis() - start;
381             Slog.d(TAG, "Prepared in " + delta + "ms");
382             return;
383         } else {
384             prepareNativeDaemon();
385         }
386     }
387 
getBatteryStats()388     private IBatteryStats getBatteryStats() {
389         synchronized (this) {
390             if (mBatteryStats != null) {
391                 return mBatteryStats;
392             }
393             mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
394                     BatteryStats.SERVICE_NAME));
395             return mBatteryStats;
396         }
397     }
398 
399     @Override
registerObserver(INetworkManagementEventObserver observer)400     public void registerObserver(INetworkManagementEventObserver observer) {
401         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
402         mObservers.register(observer);
403     }
404 
405     @Override
unregisterObserver(INetworkManagementEventObserver observer)406     public void unregisterObserver(INetworkManagementEventObserver observer) {
407         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
408         mObservers.unregister(observer);
409     }
410 
411     @FunctionalInterface
412     private interface NetworkManagementEventCallback {
sendCallback(INetworkManagementEventObserver o)413         public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
414     }
415 
invokeForAllObservers(NetworkManagementEventCallback eventCallback)416     private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
417         final int length = mObservers.beginBroadcast();
418         try {
419             for (int i = 0; i < length; i++) {
420                 try {
421                     eventCallback.sendCallback(mObservers.getBroadcastItem(i));
422                 } catch (RemoteException | RuntimeException e) {
423                 }
424             }
425         } finally {
426             mObservers.finishBroadcast();
427         }
428     }
429 
430     /**
431      * Notify our observers of an interface status change
432      */
notifyInterfaceStatusChanged(String iface, boolean up)433     private void notifyInterfaceStatusChanged(String iface, boolean up) {
434         invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
435     }
436 
437     /**
438      * Notify our observers of an interface link state change
439      * (typically, an Ethernet cable has been plugged-in or unplugged).
440      */
notifyInterfaceLinkStateChanged(String iface, boolean up)441     private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
442         invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
443     }
444 
445     /**
446      * Notify our observers of an interface addition.
447      */
notifyInterfaceAdded(String iface)448     private void notifyInterfaceAdded(String iface) {
449         invokeForAllObservers(o -> o.interfaceAdded(iface));
450     }
451 
452     /**
453      * Notify our observers of an interface removal.
454      */
notifyInterfaceRemoved(String iface)455     private void notifyInterfaceRemoved(String iface) {
456         // netd already clears out quota and alerts for removed ifaces; update
457         // our sanity-checking state.
458         mActiveAlerts.remove(iface);
459         mActiveQuotas.remove(iface);
460 
461         invokeForAllObservers(o -> o.interfaceRemoved(iface));
462     }
463 
464     /**
465      * Notify our observers of a limit reached.
466      */
notifyLimitReached(String limitName, String iface)467     private void notifyLimitReached(String limitName, String iface) {
468         invokeForAllObservers(o -> o.limitReached(limitName, iface));
469     }
470 
471     /**
472      * Notify our observers of a change in the data activity state of the interface
473      */
notifyInterfaceClassActivity(int type, int powerState, long tsNanos, int uid, boolean fromRadio)474     private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos,
475             int uid, boolean fromRadio) {
476         final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
477         if (isMobile) {
478             if (!fromRadio) {
479                 if (mMobileActivityFromRadio) {
480                     // If this call is not coming from a report from the radio itself, but we
481                     // have previously received reports from the radio, then we will take the
482                     // power state to just be whatever the radio last reported.
483                     powerState = mLastPowerStateFromRadio;
484                 }
485             } else {
486                 mMobileActivityFromRadio = true;
487             }
488             if (mLastPowerStateFromRadio != powerState) {
489                 mLastPowerStateFromRadio = powerState;
490                 try {
491                     getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
492                 } catch (RemoteException e) {
493                 }
494             }
495         }
496 
497         if (ConnectivityManager.isNetworkTypeWifi(type)) {
498             if (mLastPowerStateFromWifi != powerState) {
499                 mLastPowerStateFromWifi = powerState;
500                 try {
501                     getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
502                 } catch (RemoteException e) {
503                 }
504             }
505         }
506 
507         boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
508                 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
509 
510         if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
511             // Report the change in data activity.  We don't do this if this is a change
512             // on the mobile network, that is not coming from the radio itself, and we
513             // have previously seen change reports from the radio.  In that case only
514             // the radio is the authority for the current state.
515             final boolean active = isActive;
516             invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
517                     Integer.toString(type), active, tsNanos));
518         }
519 
520         boolean report = false;
521         synchronized (mIdleTimerLock) {
522             if (mActiveIdleTimers.isEmpty()) {
523                 // If there are no idle timers, we are not monitoring activity, so we
524                 // are always considered active.
525                 isActive = true;
526             }
527             if (mNetworkActive != isActive) {
528                 mNetworkActive = isActive;
529                 report = isActive;
530             }
531         }
532         if (report) {
533             reportNetworkActive();
534         }
535     }
536 
537     @Override
registerTetheringStatsProvider(ITetheringStatsProvider provider, String name)538     public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
539         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
540         Preconditions.checkNotNull(provider);
541         synchronized(mTetheringStatsProviders) {
542             mTetheringStatsProviders.put(provider, name);
543         }
544     }
545 
546     @Override
unregisterTetheringStatsProvider(ITetheringStatsProvider provider)547     public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
548         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
549         synchronized(mTetheringStatsProviders) {
550             mTetheringStatsProviders.remove(provider);
551         }
552     }
553 
554     @Override
tetherLimitReached(ITetheringStatsProvider provider)555     public void tetherLimitReached(ITetheringStatsProvider provider) {
556         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
557         synchronized(mTetheringStatsProviders) {
558             if (!mTetheringStatsProviders.containsKey(provider)) {
559                 return;
560             }
561             // No current code examines the interface parameter in a global alert. Just pass null.
562             notifyLimitReached(LIMIT_GLOBAL_ALERT, null);
563         }
564     }
565 
566     // Sync the state of the given chain with the native daemon.
syncFirewallChainLocked(int chain, String name)567     private void syncFirewallChainLocked(int chain, String name) {
568         SparseIntArray rules;
569         synchronized (mRulesLock) {
570             final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
571             // Make a copy of the current rules, and then clear them. This is because
572             // setFirewallUidRuleInternal only pushes down rules to the native daemon if they
573             // are different from the current rules stored in the mUidFirewall*Rules array for
574             // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal
575             // will do nothing.
576             rules = uidFirewallRules.clone();
577             uidFirewallRules.clear();
578         }
579         if (rules.size() > 0) {
580             // Now push the rules. setFirewallUidRuleInternal will push each of these down to the
581             // native daemon, and also add them to the mUidFirewall*Rules array for the specified
582             // chain.
583             if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall "
584                     + name + "UID rules");
585             for (int i = 0; i < rules.size(); i++) {
586                 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i));
587             }
588         }
589     }
590 
connectNativeNetdService()591     private void connectNativeNetdService() {
592         mNetdService = NetdService.get();
593     }
594 
595     /**
596      * Prepare native daemon once connected, enabling modules and pushing any
597      * existing in-memory rules.
598      */
prepareNativeDaemon()599     private void prepareNativeDaemon() {
600 
601         mBandwidthControlEnabled = false;
602 
603         // only enable bandwidth control when support exists
604         final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
605 
606         // push any existing quota or UID rules
607         synchronized (mQuotaLock) {
608 
609             if (hasKernelSupport) {
610                 Slog.d(TAG, "enabling bandwidth control");
611                 try {
612                     mConnector.execute("bandwidth", "enable");
613                     mBandwidthControlEnabled = true;
614                 } catch (NativeDaemonConnectorException e) {
615                     Log.wtf(TAG, "problem enabling bandwidth controls", e);
616                 }
617             } else {
618                 Slog.i(TAG, "not enabling bandwidth control");
619             }
620 
621             SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
622 
623             try {
624                 mConnector.execute("strict", "enable");
625                 mStrictEnabled = true;
626             } catch (NativeDaemonConnectorException e) {
627                 Log.wtf(TAG, "Failed strict enable", e);
628             }
629 
630             setDataSaverModeEnabled(mDataSaverMode);
631 
632             int size = mActiveQuotas.size();
633             if (size > 0) {
634                 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
635                 final HashMap<String, Long> activeQuotas = mActiveQuotas;
636                 mActiveQuotas = Maps.newHashMap();
637                 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
638                     setInterfaceQuota(entry.getKey(), entry.getValue());
639                 }
640             }
641 
642             size = mActiveAlerts.size();
643             if (size > 0) {
644                 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
645                 final HashMap<String, Long> activeAlerts = mActiveAlerts;
646                 mActiveAlerts = Maps.newHashMap();
647                 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
648                     setInterfaceAlert(entry.getKey(), entry.getValue());
649                 }
650             }
651 
652             SparseBooleanArray uidRejectOnQuota = null;
653             SparseBooleanArray uidAcceptOnQuota = null;
654             synchronized (mRulesLock) {
655                 size = mUidRejectOnMetered.size();
656                 if (size > 0) {
657                     if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
658                     uidRejectOnQuota = mUidRejectOnMetered;
659                     mUidRejectOnMetered = new SparseBooleanArray();
660                 }
661 
662                 size = mUidAllowOnMetered.size();
663                 if (size > 0) {
664                     if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
665                     uidAcceptOnQuota = mUidAllowOnMetered;
666                     mUidAllowOnMetered = new SparseBooleanArray();
667                 }
668             }
669             if (uidRejectOnQuota != null) {
670                 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
671                     setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
672                             uidRejectOnQuota.valueAt(i));
673                 }
674             }
675             if (uidAcceptOnQuota != null) {
676                 for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
677                     setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
678                             uidAcceptOnQuota.valueAt(i));
679                 }
680             }
681 
682             size = mUidCleartextPolicy.size();
683             if (size > 0) {
684                 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
685                 final SparseIntArray local = mUidCleartextPolicy;
686                 mUidCleartextPolicy = new SparseIntArray();
687                 for (int i = 0; i < local.size(); i++) {
688                     setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
689                 }
690             }
691 
692             setFirewallEnabled(mFirewallEnabled);
693 
694             syncFirewallChainLocked(FIREWALL_CHAIN_NONE, "");
695             syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
696             syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
697             syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
698 
699             final int[] chains =
700                     {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
701             for (int chain : chains) {
702                 if (getFirewallChainState(chain)) {
703                     setFirewallChainEnabled(chain, true);
704                 }
705             }
706         }
707 
708         if (mBandwidthControlEnabled) {
709             try {
710                 getBatteryStats().noteNetworkStatsEnabled();
711             } catch (RemoteException e) {
712             }
713         }
714 
715     }
716 
717     /**
718      * Notify our observers of a new or updated interface address.
719      */
notifyAddressUpdated(String iface, LinkAddress address)720     private void notifyAddressUpdated(String iface, LinkAddress address) {
721         invokeForAllObservers(o -> o.addressUpdated(iface, address));
722     }
723 
724     /**
725      * Notify our observers of a deleted interface address.
726      */
notifyAddressRemoved(String iface, LinkAddress address)727     private void notifyAddressRemoved(String iface, LinkAddress address) {
728         invokeForAllObservers(o -> o.addressRemoved(iface, address));
729     }
730 
731     /**
732      * Notify our observers of DNS server information received.
733      */
notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses)734     private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
735         invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
736     }
737 
738     /**
739      * Notify our observers of a route change.
740      */
notifyRouteChange(String action, RouteInfo route)741     private void notifyRouteChange(String action, RouteInfo route) {
742         if (action.equals("updated")) {
743             invokeForAllObservers(o -> o.routeUpdated(route));
744         } else {
745             invokeForAllObservers(o -> o.routeRemoved(route));
746         }
747     }
748 
749     //
750     // Netd Callback handling
751     //
752 
753     private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
754         @Override
onDaemonConnected()755         public void onDaemonConnected() {
756             Slog.i(TAG, "onDaemonConnected()");
757             // event is dispatched from internal NDC thread, so we prepare the
758             // daemon back on main thread.
759             if (mConnectedSignal != null) {
760                 // The system is booting and we're connecting to netd for the first time.
761                 mConnectedSignal.countDown();
762                 mConnectedSignal = null;
763             } else {
764                 // We're reconnecting to netd after the socket connection
765                 // was interrupted (e.g., if it crashed).
766                 mFgHandler.post(new Runnable() {
767                     @Override
768                     public void run() {
769                         connectNativeNetdService();
770                         prepareNativeDaemon();
771                     }
772                 });
773             }
774         }
775 
776         @Override
onCheckHoldWakeLock(int code)777         public boolean onCheckHoldWakeLock(int code) {
778             return code == NetdResponseCode.InterfaceClassActivity;
779         }
780 
781         @Override
onEvent(int code, String raw, String[] cooked)782         public boolean onEvent(int code, String raw, String[] cooked) {
783             String errorMessage = String.format("Invalid event from daemon (%s)", raw);
784             switch (code) {
785             case NetdResponseCode.InterfaceChange:
786                     /*
787                      * a network interface change occured
788                      * Format: "NNN Iface added <name>"
789                      *         "NNN Iface removed <name>"
790                      *         "NNN Iface changed <name> <up/down>"
791                      *         "NNN Iface linkstatus <name> <up/down>"
792                      */
793                     if (cooked.length < 4 || !cooked[1].equals("Iface")) {
794                         throw new IllegalStateException(errorMessage);
795                     }
796                     if (cooked[2].equals("added")) {
797                         notifyInterfaceAdded(cooked[3]);
798                         return true;
799                     } else if (cooked[2].equals("removed")) {
800                         notifyInterfaceRemoved(cooked[3]);
801                         return true;
802                     } else if (cooked[2].equals("changed") && cooked.length == 5) {
803                         notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
804                         return true;
805                     } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
806                         notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
807                         return true;
808                     }
809                     throw new IllegalStateException(errorMessage);
810                     // break;
811             case NetdResponseCode.BandwidthControl:
812                     /*
813                      * Bandwidth control needs some attention
814                      * Format: "NNN limit alert <alertName> <ifaceName>"
815                      */
816                     if (cooked.length < 5 || !cooked[1].equals("limit")) {
817                         throw new IllegalStateException(errorMessage);
818                     }
819                     if (cooked[2].equals("alert")) {
820                         notifyLimitReached(cooked[3], cooked[4]);
821                         return true;
822                     }
823                     throw new IllegalStateException(errorMessage);
824                     // break;
825             case NetdResponseCode.InterfaceClassActivity:
826                     /*
827                      * An network interface class state changed (active/idle)
828                      * Format: "NNN IfaceClass <active/idle> <label>"
829                      */
830                     if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
831                         throw new IllegalStateException(errorMessage);
832                     }
833                     long timestampNanos = 0;
834                     int processUid = -1;
835                     if (cooked.length >= 5) {
836                         try {
837                             timestampNanos = Long.parseLong(cooked[4]);
838                             if (cooked.length == 6) {
839                                 processUid = Integer.parseInt(cooked[5]);
840                             }
841                         } catch(NumberFormatException ne) {}
842                     } else {
843                         timestampNanos = SystemClock.elapsedRealtimeNanos();
844                     }
845                     boolean isActive = cooked[2].equals("active");
846                     notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
847                             isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
848                             : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
849                             timestampNanos, processUid, false);
850                     return true;
851                     // break;
852             case NetdResponseCode.InterfaceAddressChange:
853                     /*
854                      * A network address change occurred
855                      * Format: "NNN Address updated <addr> <iface> <flags> <scope>"
856                      *         "NNN Address removed <addr> <iface> <flags> <scope>"
857                      */
858                     if (cooked.length < 7 || !cooked[1].equals("Address")) {
859                         throw new IllegalStateException(errorMessage);
860                     }
861 
862                     String iface = cooked[4];
863                     LinkAddress address;
864                     try {
865                         int flags = Integer.parseInt(cooked[5]);
866                         int scope = Integer.parseInt(cooked[6]);
867                         address = new LinkAddress(cooked[3], flags, scope);
868                     } catch(NumberFormatException e) {     // Non-numeric lifetime or scope.
869                         throw new IllegalStateException(errorMessage, e);
870                     } catch(IllegalArgumentException e) {  // Malformed/invalid IP address.
871                         throw new IllegalStateException(errorMessage, e);
872                     }
873 
874                     if (cooked[2].equals("updated")) {
875                         notifyAddressUpdated(iface, address);
876                     } else {
877                         notifyAddressRemoved(iface, address);
878                     }
879                     return true;
880                     // break;
881             case NetdResponseCode.InterfaceDnsServerInfo:
882                     /*
883                      * Information about available DNS servers has been received.
884                      * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>"
885                      */
886                     long lifetime;  // Actually a 32-bit unsigned integer.
887 
888                     if (cooked.length == 6 &&
889                         cooked[1].equals("DnsInfo") &&
890                         cooked[2].equals("servers")) {
891                         try {
892                             lifetime = Long.parseLong(cooked[4]);
893                         } catch (NumberFormatException e) {
894                             throw new IllegalStateException(errorMessage);
895                         }
896                         String[] servers = cooked[5].split(",");
897                         notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
898                     }
899                     return true;
900                     // break;
901             case NetdResponseCode.RouteChange:
902                     /*
903                      * A route has been updated or removed.
904                      * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]"
905                      */
906                     if (!cooked[1].equals("Route") || cooked.length < 6) {
907                         throw new IllegalStateException(errorMessage);
908                     }
909 
910                     String via = null;
911                     String dev = null;
912                     boolean valid = true;
913                     for (int i = 4; (i + 1) < cooked.length && valid; i += 2) {
914                         if (cooked[i].equals("dev")) {
915                             if (dev == null) {
916                                 dev = cooked[i+1];
917                             } else {
918                                 valid = false;  // Duplicate interface.
919                             }
920                         } else if (cooked[i].equals("via")) {
921                             if (via == null) {
922                                 via = cooked[i+1];
923                             } else {
924                                 valid = false;  // Duplicate gateway.
925                             }
926                         } else {
927                             valid = false;      // Unknown syntax.
928                         }
929                     }
930                     if (valid) {
931                         try {
932                             // InetAddress.parseNumericAddress(null) inexplicably returns ::1.
933                             InetAddress gateway = null;
934                             if (via != null) gateway = InetAddress.parseNumericAddress(via);
935                             RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
936                             notifyRouteChange(cooked[2], route);
937                             return true;
938                         } catch (IllegalArgumentException e) {}
939                     }
940                     throw new IllegalStateException(errorMessage);
941                     // break;
942             case NetdResponseCode.StrictCleartext:
943                 final int uid = Integer.parseInt(cooked[1]);
944                 final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]);
945                 try {
946                     ActivityManager.getService().notifyCleartextNetwork(uid, firstPacket);
947                 } catch (RemoteException ignored) {
948                 }
949                 break;
950             default: break;
951             }
952             return false;
953         }
954     }
955 
956 
957     //
958     // INetworkManagementService members
959     //
960     @Override
getNetdService()961     public INetd getNetdService() throws RemoteException {
962         final CountDownLatch connectedSignal = mConnectedSignal;
963         if (connectedSignal != null) {
964             try {
965                 connectedSignal.await();
966             } catch (InterruptedException ignored) {}
967         }
968 
969         return mNetdService;
970     }
971 
972     @Override
listInterfaces()973     public String[] listInterfaces() {
974         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
975         try {
976             return NativeDaemonEvent.filterMessageList(
977                     mConnector.executeForList("interface", "list"), InterfaceListResult);
978         } catch (NativeDaemonConnectorException e) {
979             throw e.rethrowAsParcelableException();
980         }
981     }
982 
983     @Override
getInterfaceConfig(String iface)984     public InterfaceConfiguration getInterfaceConfig(String iface) {
985         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
986 
987         final NativeDaemonEvent event;
988         try {
989             event = mConnector.execute("interface", "getcfg", iface);
990         } catch (NativeDaemonConnectorException e) {
991             throw e.rethrowAsParcelableException();
992         }
993 
994         event.checkCode(InterfaceGetCfgResult);
995 
996         // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3
997         final StringTokenizer st = new StringTokenizer(event.getMessage());
998 
999         InterfaceConfiguration cfg;
1000         try {
1001             cfg = new InterfaceConfiguration();
1002             cfg.setHardwareAddress(st.nextToken(" "));
1003             InetAddress addr = null;
1004             int prefixLength = 0;
1005             try {
1006                 addr = NetworkUtils.numericToInetAddress(st.nextToken());
1007             } catch (IllegalArgumentException iae) {
1008                 Slog.e(TAG, "Failed to parse ipaddr", iae);
1009             }
1010 
1011             try {
1012                 prefixLength = Integer.parseInt(st.nextToken());
1013             } catch (NumberFormatException nfe) {
1014                 Slog.e(TAG, "Failed to parse prefixLength", nfe);
1015             }
1016 
1017             cfg.setLinkAddress(new LinkAddress(addr, prefixLength));
1018             while (st.hasMoreTokens()) {
1019                 cfg.setFlag(st.nextToken());
1020             }
1021         } catch (NoSuchElementException nsee) {
1022             throw new IllegalStateException("Invalid response from daemon: " + event);
1023         }
1024         return cfg;
1025     }
1026 
1027     @Override
setInterfaceConfig(String iface, InterfaceConfiguration cfg)1028     public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
1029         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1030         LinkAddress linkAddr = cfg.getLinkAddress();
1031         if (linkAddr == null || linkAddr.getAddress() == null) {
1032             throw new IllegalStateException("Null LinkAddress given");
1033         }
1034 
1035         final Command cmd = new Command("interface", "setcfg", iface,
1036                 linkAddr.getAddress().getHostAddress(),
1037                 linkAddr.getPrefixLength());
1038         for (String flag : cfg.getFlags()) {
1039             cmd.appendArg(flag);
1040         }
1041 
1042         try {
1043             mConnector.execute(cmd);
1044         } catch (NativeDaemonConnectorException e) {
1045             throw e.rethrowAsParcelableException();
1046         }
1047     }
1048 
1049     @Override
setInterfaceDown(String iface)1050     public void setInterfaceDown(String iface) {
1051         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1052         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
1053         ifcg.setInterfaceDown();
1054         setInterfaceConfig(iface, ifcg);
1055     }
1056 
1057     @Override
setInterfaceUp(String iface)1058     public void setInterfaceUp(String iface) {
1059         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1060         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
1061         ifcg.setInterfaceUp();
1062         setInterfaceConfig(iface, ifcg);
1063     }
1064 
1065     @Override
setInterfaceIpv6PrivacyExtensions(String iface, boolean enable)1066     public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
1067         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1068         try {
1069             mConnector.execute(
1070                     "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable");
1071         } catch (NativeDaemonConnectorException e) {
1072             throw e.rethrowAsParcelableException();
1073         }
1074     }
1075 
1076     /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
1077        IPv6 addresses on interface down, but we need to do full clean up here */
1078     @Override
clearInterfaceAddresses(String iface)1079     public void clearInterfaceAddresses(String iface) {
1080         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1081         try {
1082             mConnector.execute("interface", "clearaddrs", iface);
1083         } catch (NativeDaemonConnectorException e) {
1084             throw e.rethrowAsParcelableException();
1085         }
1086     }
1087 
1088     @Override
enableIpv6(String iface)1089     public void enableIpv6(String iface) {
1090         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1091         try {
1092             mConnector.execute("interface", "ipv6", iface, "enable");
1093         } catch (NativeDaemonConnectorException e) {
1094             throw e.rethrowAsParcelableException();
1095         }
1096     }
1097 
1098     @Override
setIPv6AddrGenMode(String iface, int mode)1099     public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
1100         try {
1101             mNetdService.setIPv6AddrGenMode(iface, mode);
1102         } catch (RemoteException e) {
1103             throw e.rethrowAsRuntimeException();
1104         }
1105     }
1106 
1107     @Override
disableIpv6(String iface)1108     public void disableIpv6(String iface) {
1109         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1110         try {
1111             mConnector.execute("interface", "ipv6", iface, "disable");
1112         } catch (NativeDaemonConnectorException e) {
1113             throw e.rethrowAsParcelableException();
1114         }
1115     }
1116 
1117     @Override
setInterfaceIpv6NdOffload(String iface, boolean enable)1118     public void setInterfaceIpv6NdOffload(String iface, boolean enable) {
1119         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1120         try {
1121             mConnector.execute(
1122                     "interface", "ipv6ndoffload", iface, (enable ? "enable" : "disable"));
1123         } catch (NativeDaemonConnectorException e) {
1124             throw e.rethrowAsParcelableException();
1125         }
1126     }
1127 
1128     @Override
addRoute(int netId, RouteInfo route)1129     public void addRoute(int netId, RouteInfo route) {
1130         modifyRoute("add", "" + netId, route);
1131     }
1132 
1133     @Override
removeRoute(int netId, RouteInfo route)1134     public void removeRoute(int netId, RouteInfo route) {
1135         modifyRoute("remove", "" + netId, route);
1136     }
1137 
modifyRoute(String action, String netId, RouteInfo route)1138     private void modifyRoute(String action, String netId, RouteInfo route) {
1139         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1140 
1141         final Command cmd = new Command("network", "route", action, netId);
1142 
1143         // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
1144         cmd.appendArg(route.getInterface());
1145         cmd.appendArg(route.getDestination().toString());
1146 
1147         switch (route.getType()) {
1148             case RouteInfo.RTN_UNICAST:
1149                 if (route.hasGateway()) {
1150                     cmd.appendArg(route.getGateway().getHostAddress());
1151                 }
1152                 break;
1153             case RouteInfo.RTN_UNREACHABLE:
1154                 cmd.appendArg("unreachable");
1155                 break;
1156             case RouteInfo.RTN_THROW:
1157                 cmd.appendArg("throw");
1158                 break;
1159         }
1160 
1161         try {
1162             mConnector.execute(cmd);
1163         } catch (NativeDaemonConnectorException e) {
1164             throw e.rethrowAsParcelableException();
1165         }
1166     }
1167 
readRouteList(String filename)1168     private ArrayList<String> readRouteList(String filename) {
1169         FileInputStream fstream = null;
1170         ArrayList<String> list = new ArrayList<>();
1171 
1172         try {
1173             fstream = new FileInputStream(filename);
1174             DataInputStream in = new DataInputStream(fstream);
1175             BufferedReader br = new BufferedReader(new InputStreamReader(in));
1176             String s;
1177 
1178             // throw away the title line
1179 
1180             while (((s = br.readLine()) != null) && (s.length() != 0)) {
1181                 list.add(s);
1182             }
1183         } catch (IOException ex) {
1184             // return current list, possibly empty
1185         } finally {
1186             if (fstream != null) {
1187                 try {
1188                     fstream.close();
1189                 } catch (IOException ex) {}
1190             }
1191         }
1192 
1193         return list;
1194     }
1195 
1196     @Override
setMtu(String iface, int mtu)1197     public void setMtu(String iface, int mtu) {
1198         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1199 
1200         final NativeDaemonEvent event;
1201         try {
1202             event = mConnector.execute("interface", "setmtu", iface, mtu);
1203         } catch (NativeDaemonConnectorException e) {
1204             throw e.rethrowAsParcelableException();
1205         }
1206     }
1207 
1208     @Override
shutdown()1209     public void shutdown() {
1210         // TODO: remove from aidl if nobody calls externally
1211         mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
1212 
1213         Slog.i(TAG, "Shutting down");
1214     }
1215 
1216     @Override
getIpForwardingEnabled()1217     public boolean getIpForwardingEnabled() throws IllegalStateException{
1218         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1219 
1220         final NativeDaemonEvent event;
1221         try {
1222             event = mConnector.execute("ipfwd", "status");
1223         } catch (NativeDaemonConnectorException e) {
1224             throw e.rethrowAsParcelableException();
1225         }
1226 
1227         // 211 Forwarding enabled
1228         event.checkCode(IpFwdStatusResult);
1229         return event.getMessage().endsWith("enabled");
1230     }
1231 
1232     @Override
setIpForwardingEnabled(boolean enable)1233     public void setIpForwardingEnabled(boolean enable) {
1234         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1235         try {
1236             mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering");
1237         } catch (NativeDaemonConnectorException e) {
1238             throw e.rethrowAsParcelableException();
1239         }
1240     }
1241 
1242     @Override
startTethering(String[] dhcpRange)1243     public void startTethering(String[] dhcpRange) {
1244         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1245         // cmd is "tether start first_start first_stop second_start second_stop ..."
1246         // an odd number of addrs will fail
1247 
1248         final Command cmd = new Command("tether", "start");
1249         for (String d : dhcpRange) {
1250             cmd.appendArg(d);
1251         }
1252 
1253         try {
1254             mConnector.execute(cmd);
1255         } catch (NativeDaemonConnectorException e) {
1256             throw e.rethrowAsParcelableException();
1257         }
1258     }
1259 
1260     @Override
stopTethering()1261     public void stopTethering() {
1262         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1263         try {
1264             mConnector.execute("tether", "stop");
1265         } catch (NativeDaemonConnectorException e) {
1266             throw e.rethrowAsParcelableException();
1267         }
1268     }
1269 
1270     @Override
isTetheringStarted()1271     public boolean isTetheringStarted() {
1272         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1273 
1274         final NativeDaemonEvent event;
1275         try {
1276             event = mConnector.execute("tether", "status");
1277         } catch (NativeDaemonConnectorException e) {
1278             throw e.rethrowAsParcelableException();
1279         }
1280 
1281         // 210 Tethering services started
1282         event.checkCode(TetherStatusResult);
1283         return event.getMessage().endsWith("started");
1284     }
1285 
1286     @Override
tetherInterface(String iface)1287     public void tetherInterface(String iface) {
1288         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1289         try {
1290             mConnector.execute("tether", "interface", "add", iface);
1291         } catch (NativeDaemonConnectorException e) {
1292             throw e.rethrowAsParcelableException();
1293         }
1294         List<RouteInfo> routes = new ArrayList<>();
1295         // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
1296         // suitable to use as a route destination.
1297         routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
1298         addInterfaceToLocalNetwork(iface, routes);
1299     }
1300 
1301     @Override
untetherInterface(String iface)1302     public void untetherInterface(String iface) {
1303         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1304         try {
1305             mConnector.execute("tether", "interface", "remove", iface);
1306         } catch (NativeDaemonConnectorException e) {
1307             throw e.rethrowAsParcelableException();
1308         } finally {
1309             removeInterfaceFromLocalNetwork(iface);
1310         }
1311     }
1312 
1313     @Override
listTetheredInterfaces()1314     public String[] listTetheredInterfaces() {
1315         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1316         try {
1317             return NativeDaemonEvent.filterMessageList(
1318                     mConnector.executeForList("tether", "interface", "list"),
1319                     TetherInterfaceListResult);
1320         } catch (NativeDaemonConnectorException e) {
1321             throw e.rethrowAsParcelableException();
1322         }
1323     }
1324 
1325     @Override
setDnsForwarders(Network network, String[] dns)1326     public void setDnsForwarders(Network network, String[] dns) {
1327         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1328 
1329         int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
1330         final Command cmd = new Command("tether", "dns", "set", netId);
1331 
1332         for (String s : dns) {
1333             cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
1334         }
1335 
1336         try {
1337             mConnector.execute(cmd);
1338         } catch (NativeDaemonConnectorException e) {
1339             throw e.rethrowAsParcelableException();
1340         }
1341     }
1342 
1343     @Override
getDnsForwarders()1344     public String[] getDnsForwarders() {
1345         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1346         try {
1347             return NativeDaemonEvent.filterMessageList(
1348                     mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult);
1349         } catch (NativeDaemonConnectorException e) {
1350             throw e.rethrowAsParcelableException();
1351         }
1352     }
1353 
excludeLinkLocal(List<InterfaceAddress> addresses)1354     private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
1355         ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
1356         for (InterfaceAddress ia : addresses) {
1357             if (!ia.getAddress().isLinkLocalAddress())
1358                 filtered.add(ia);
1359         }
1360         return filtered;
1361     }
1362 
modifyInterfaceForward(boolean add, String fromIface, String toIface)1363     private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
1364         final Command cmd = new Command("ipfwd", add ? "add" : "remove", fromIface, toIface);
1365         try {
1366             mConnector.execute(cmd);
1367         } catch (NativeDaemonConnectorException e) {
1368             throw e.rethrowAsParcelableException();
1369         }
1370     }
1371 
1372     @Override
startInterfaceForwarding(String fromIface, String toIface)1373     public void startInterfaceForwarding(String fromIface, String toIface) {
1374         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1375         modifyInterfaceForward(true, fromIface, toIface);
1376     }
1377 
1378     @Override
stopInterfaceForwarding(String fromIface, String toIface)1379     public void stopInterfaceForwarding(String fromIface, String toIface) {
1380         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1381         modifyInterfaceForward(false, fromIface, toIface);
1382     }
1383 
modifyNat(String action, String internalInterface, String externalInterface)1384     private void modifyNat(String action, String internalInterface, String externalInterface)
1385             throws SocketException {
1386         final Command cmd = new Command("nat", action, internalInterface, externalInterface);
1387 
1388         final NetworkInterface internalNetworkInterface = NetworkInterface.getByName(
1389                 internalInterface);
1390         if (internalNetworkInterface == null) {
1391             cmd.appendArg("0");
1392         } else {
1393             // Don't touch link-local routes, as link-local addresses aren't routable,
1394             // kernel creates link-local routes on all interfaces automatically
1395             List<InterfaceAddress> interfaceAddresses = excludeLinkLocal(
1396                     internalNetworkInterface.getInterfaceAddresses());
1397             cmd.appendArg(interfaceAddresses.size());
1398             for (InterfaceAddress ia : interfaceAddresses) {
1399                 InetAddress addr = NetworkUtils.getNetworkPart(
1400                         ia.getAddress(), ia.getNetworkPrefixLength());
1401                 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength());
1402             }
1403         }
1404 
1405         try {
1406             mConnector.execute(cmd);
1407         } catch (NativeDaemonConnectorException e) {
1408             throw e.rethrowAsParcelableException();
1409         }
1410     }
1411 
1412     @Override
enableNat(String internalInterface, String externalInterface)1413     public void enableNat(String internalInterface, String externalInterface) {
1414         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1415         try {
1416             modifyNat("enable", internalInterface, externalInterface);
1417         } catch (SocketException e) {
1418             throw new IllegalStateException(e);
1419         }
1420     }
1421 
1422     @Override
disableNat(String internalInterface, String externalInterface)1423     public void disableNat(String internalInterface, String externalInterface) {
1424         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1425         try {
1426             modifyNat("disable", internalInterface, externalInterface);
1427         } catch (SocketException e) {
1428             throw new IllegalStateException(e);
1429         }
1430     }
1431 
1432     @Override
listTtys()1433     public String[] listTtys() {
1434         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1435         try {
1436             return NativeDaemonEvent.filterMessageList(
1437                     mConnector.executeForList("list_ttys"), TtyListResult);
1438         } catch (NativeDaemonConnectorException e) {
1439             throw e.rethrowAsParcelableException();
1440         }
1441     }
1442 
1443     @Override
attachPppd( String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr)1444     public void attachPppd(
1445             String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
1446         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1447         try {
1448             mConnector.execute("pppd", "attach", tty,
1449                     NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
1450                     NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
1451                     NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
1452                     NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress());
1453         } catch (NativeDaemonConnectorException e) {
1454             throw e.rethrowAsParcelableException();
1455         }
1456     }
1457 
1458     @Override
detachPppd(String tty)1459     public void detachPppd(String tty) {
1460         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1461         try {
1462             mConnector.execute("pppd", "detach", tty);
1463         } catch (NativeDaemonConnectorException e) {
1464             throw e.rethrowAsParcelableException();
1465         }
1466     }
1467 
1468     @Override
addIdleTimer(String iface, int timeout, final int type)1469     public void addIdleTimer(String iface, int timeout, final int type) {
1470         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1471 
1472         if (DBG) Slog.d(TAG, "Adding idletimer");
1473 
1474         synchronized (mIdleTimerLock) {
1475             IdleTimerParams params = mActiveIdleTimers.get(iface);
1476             if (params != null) {
1477                 // the interface already has idletimer, update network count
1478                 params.networkCount++;
1479                 return;
1480             }
1481 
1482             try {
1483                 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout),
1484                         Integer.toString(type));
1485             } catch (NativeDaemonConnectorException e) {
1486                 throw e.rethrowAsParcelableException();
1487             }
1488             mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
1489 
1490             // Networks start up.
1491             if (ConnectivityManager.isNetworkTypeMobile(type)) {
1492                 mNetworkActive = false;
1493             }
1494             mDaemonHandler.post(new Runnable() {
1495                 @Override public void run() {
1496                     notifyInterfaceClassActivity(type,
1497                             DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
1498                             SystemClock.elapsedRealtimeNanos(), -1, false);
1499                 }
1500             });
1501         }
1502     }
1503 
1504     @Override
removeIdleTimer(String iface)1505     public void removeIdleTimer(String iface) {
1506         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1507 
1508         if (DBG) Slog.d(TAG, "Removing idletimer");
1509 
1510         synchronized (mIdleTimerLock) {
1511             final IdleTimerParams params = mActiveIdleTimers.get(iface);
1512             if (params == null || --(params.networkCount) > 0) {
1513                 return;
1514             }
1515 
1516             try {
1517                 mConnector.execute("idletimer", "remove", iface,
1518                         Integer.toString(params.timeout), Integer.toString(params.type));
1519             } catch (NativeDaemonConnectorException e) {
1520                 throw e.rethrowAsParcelableException();
1521             }
1522             mActiveIdleTimers.remove(iface);
1523             mDaemonHandler.post(new Runnable() {
1524                 @Override public void run() {
1525                     notifyInterfaceClassActivity(params.type,
1526                             DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
1527                             SystemClock.elapsedRealtimeNanos(), -1, false);
1528                 }
1529             });
1530         }
1531     }
1532 
1533     @Override
getNetworkStatsSummaryDev()1534     public NetworkStats getNetworkStatsSummaryDev() {
1535         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1536         try {
1537             return mStatsFactory.readNetworkStatsSummaryDev();
1538         } catch (IOException e) {
1539             throw new IllegalStateException(e);
1540         }
1541     }
1542 
1543     @Override
getNetworkStatsSummaryXt()1544     public NetworkStats getNetworkStatsSummaryXt() {
1545         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1546         try {
1547             return mStatsFactory.readNetworkStatsSummaryXt();
1548         } catch (IOException e) {
1549             throw new IllegalStateException(e);
1550         }
1551     }
1552 
1553     @Override
getNetworkStatsDetail()1554     public NetworkStats getNetworkStatsDetail() {
1555         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1556         try {
1557             return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
1558         } catch (IOException e) {
1559             throw new IllegalStateException(e);
1560         }
1561     }
1562 
1563     @Override
setInterfaceQuota(String iface, long quotaBytes)1564     public void setInterfaceQuota(String iface, long quotaBytes) {
1565         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1566 
1567         // silently discard when control disabled
1568         // TODO: eventually migrate to be always enabled
1569         if (!mBandwidthControlEnabled) return;
1570 
1571         synchronized (mQuotaLock) {
1572             if (mActiveQuotas.containsKey(iface)) {
1573                 throw new IllegalStateException("iface " + iface + " already has quota");
1574             }
1575 
1576             try {
1577                 // TODO: support quota shared across interfaces
1578                 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes);
1579                 mActiveQuotas.put(iface, quotaBytes);
1580             } catch (NativeDaemonConnectorException e) {
1581                 throw e.rethrowAsParcelableException();
1582             }
1583 
1584             synchronized (mTetheringStatsProviders) {
1585                 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1586                     try {
1587                         provider.setInterfaceQuota(iface, quotaBytes);
1588                     } catch (RemoteException e) {
1589                         Log.e(TAG, "Problem setting tethering data limit on provider " +
1590                                 mTetheringStatsProviders.get(provider) + ": " + e);
1591                     }
1592                 }
1593             }
1594         }
1595     }
1596 
1597     @Override
removeInterfaceQuota(String iface)1598     public void removeInterfaceQuota(String iface) {
1599         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1600 
1601         // silently discard when control disabled
1602         // TODO: eventually migrate to be always enabled
1603         if (!mBandwidthControlEnabled) return;
1604 
1605         synchronized (mQuotaLock) {
1606             if (!mActiveQuotas.containsKey(iface)) {
1607                 // TODO: eventually consider throwing
1608                 return;
1609             }
1610 
1611             mActiveQuotas.remove(iface);
1612             mActiveAlerts.remove(iface);
1613 
1614             try {
1615                 // TODO: support quota shared across interfaces
1616                 mConnector.execute("bandwidth", "removeiquota", iface);
1617             } catch (NativeDaemonConnectorException e) {
1618                 throw e.rethrowAsParcelableException();
1619             }
1620 
1621             synchronized (mTetheringStatsProviders) {
1622                 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1623                     try {
1624                         provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
1625                     } catch (RemoteException e) {
1626                         Log.e(TAG, "Problem removing tethering data limit on provider " +
1627                                 mTetheringStatsProviders.get(provider) + ": " + e);
1628                     }
1629                 }
1630             }
1631         }
1632     }
1633 
1634     @Override
setInterfaceAlert(String iface, long alertBytes)1635     public void setInterfaceAlert(String iface, long alertBytes) {
1636         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1637 
1638         // silently discard when control disabled
1639         // TODO: eventually migrate to be always enabled
1640         if (!mBandwidthControlEnabled) return;
1641 
1642         // quick sanity check
1643         if (!mActiveQuotas.containsKey(iface)) {
1644             throw new IllegalStateException("setting alert requires existing quota on iface");
1645         }
1646 
1647         synchronized (mQuotaLock) {
1648             if (mActiveAlerts.containsKey(iface)) {
1649                 throw new IllegalStateException("iface " + iface + " already has alert");
1650             }
1651 
1652             try {
1653                 // TODO: support alert shared across interfaces
1654                 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes);
1655                 mActiveAlerts.put(iface, alertBytes);
1656             } catch (NativeDaemonConnectorException e) {
1657                 throw e.rethrowAsParcelableException();
1658             }
1659         }
1660     }
1661 
1662     @Override
removeInterfaceAlert(String iface)1663     public void removeInterfaceAlert(String iface) {
1664         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1665 
1666         // silently discard when control disabled
1667         // TODO: eventually migrate to be always enabled
1668         if (!mBandwidthControlEnabled) return;
1669 
1670         synchronized (mQuotaLock) {
1671             if (!mActiveAlerts.containsKey(iface)) {
1672                 // TODO: eventually consider throwing
1673                 return;
1674             }
1675 
1676             try {
1677                 // TODO: support alert shared across interfaces
1678                 mConnector.execute("bandwidth", "removeinterfacealert", iface);
1679                 mActiveAlerts.remove(iface);
1680             } catch (NativeDaemonConnectorException e) {
1681                 throw e.rethrowAsParcelableException();
1682             }
1683         }
1684     }
1685 
1686     @Override
setGlobalAlert(long alertBytes)1687     public void setGlobalAlert(long alertBytes) {
1688         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1689 
1690         // silently discard when control disabled
1691         // TODO: eventually migrate to be always enabled
1692         if (!mBandwidthControlEnabled) return;
1693 
1694         try {
1695             mConnector.execute("bandwidth", "setglobalalert", alertBytes);
1696         } catch (NativeDaemonConnectorException e) {
1697             throw e.rethrowAsParcelableException();
1698         }
1699     }
1700 
setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable)1701     private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
1702         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1703 
1704         // silently discard when control disabled
1705         // TODO: eventually migrate to be always enabled
1706         if (!mBandwidthControlEnabled) return;
1707 
1708         final String chain = blacklist ? "naughtyapps" : "niceapps";
1709         final String suffix = enable ? "add" : "remove";
1710 
1711         synchronized (mQuotaLock) {
1712             boolean oldEnable;
1713             SparseBooleanArray quotaList;
1714             synchronized (mRulesLock) {
1715                 quotaList = blacklist ? mUidRejectOnMetered : mUidAllowOnMetered;
1716                 oldEnable = quotaList.get(uid, false);
1717             }
1718             if (oldEnable == enable) {
1719                 // TODO: eventually consider throwing
1720                 return;
1721             }
1722 
1723             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
1724             try {
1725                 mConnector.execute("bandwidth", suffix + chain, uid);
1726                 synchronized (mRulesLock) {
1727                     if (enable) {
1728                         quotaList.put(uid, true);
1729                     } else {
1730                         quotaList.delete(uid);
1731                     }
1732                 }
1733             } catch (NativeDaemonConnectorException e) {
1734                 throw e.rethrowAsParcelableException();
1735             } finally {
1736                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
1737             }
1738         }
1739     }
1740 
1741     @Override
setUidMeteredNetworkBlacklist(int uid, boolean enable)1742     public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
1743         setUidOnMeteredNetworkList(uid, true, enable);
1744     }
1745 
1746     @Override
setUidMeteredNetworkWhitelist(int uid, boolean enable)1747     public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
1748         setUidOnMeteredNetworkList(uid, false, enable);
1749     }
1750 
1751     @Override
setDataSaverModeEnabled(boolean enable)1752     public boolean setDataSaverModeEnabled(boolean enable) {
1753         if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
1754         synchronized (mQuotaLock) {
1755             if (mDataSaverMode == enable) {
1756                 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
1757                 return true;
1758             }
1759             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
1760             try {
1761                 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
1762                 if (changed) {
1763                     mDataSaverMode = enable;
1764                 } else {
1765                     Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
1766                 }
1767                 return changed;
1768             } catch (RemoteException e) {
1769                 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
1770                 return false;
1771             } finally {
1772                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
1773             }
1774         }
1775     }
1776 
1777     @Override
setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)1778     public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
1779             throws ServiceSpecificException {
1780         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
1781 
1782         try {
1783             mNetdService.networkRejectNonSecureVpn(add, uidRanges);
1784         } catch (ServiceSpecificException e) {
1785             Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1786                     + ": netd command failed", e);
1787             throw e;
1788         } catch (RemoteException e) {
1789             Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1790                     + ": netd command failed", e);
1791             throw e.rethrowAsRuntimeException();
1792         }
1793     }
1794 
applyUidCleartextNetworkPolicy(int uid, int policy)1795     private void applyUidCleartextNetworkPolicy(int uid, int policy) {
1796         final String policyString;
1797         switch (policy) {
1798             case StrictMode.NETWORK_POLICY_ACCEPT:
1799                 policyString = "accept";
1800                 break;
1801             case StrictMode.NETWORK_POLICY_LOG:
1802                 policyString = "log";
1803                 break;
1804             case StrictMode.NETWORK_POLICY_REJECT:
1805                 policyString = "reject";
1806                 break;
1807             default:
1808                 throw new IllegalArgumentException("Unknown policy " + policy);
1809         }
1810 
1811         try {
1812             mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString);
1813             mUidCleartextPolicy.put(uid, policy);
1814         } catch (NativeDaemonConnectorException e) {
1815             throw e.rethrowAsParcelableException();
1816         }
1817     }
1818 
1819     @Override
setUidCleartextNetworkPolicy(int uid, int policy)1820     public void setUidCleartextNetworkPolicy(int uid, int policy) {
1821         if (Binder.getCallingUid() != uid) {
1822             mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1823         }
1824 
1825         synchronized (mQuotaLock) {
1826             final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1827             if (oldPolicy == policy) {
1828                 // This also ensures we won't needlessly apply an ACCEPT policy if we've just
1829                 // enabled strict and the underlying iptables rules are empty.
1830                 return;
1831             }
1832 
1833             if (!mStrictEnabled) {
1834                 // Module isn't enabled yet; stash the requested policy away to
1835                 // apply later once the daemon is connected.
1836                 mUidCleartextPolicy.put(uid, policy);
1837                 return;
1838             }
1839 
1840             // netd does not keep state on strict mode policies, and cannot replace a non-accept
1841             // policy without deleting it first. Rather than add state to netd, just always send
1842             // it an accept policy when switching between two non-accept policies.
1843             // TODO: consider keeping state in netd so we can simplify this code.
1844             if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT &&
1845                     policy != StrictMode.NETWORK_POLICY_ACCEPT) {
1846                 applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1847             }
1848 
1849             applyUidCleartextNetworkPolicy(uid, policy);
1850         }
1851     }
1852 
1853     @Override
isBandwidthControlEnabled()1854     public boolean isBandwidthControlEnabled() {
1855         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1856         return mBandwidthControlEnabled;
1857     }
1858 
1859     @Override
getNetworkStatsUidDetail(int uid)1860     public NetworkStats getNetworkStatsUidDetail(int uid) {
1861         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1862         try {
1863             return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null);
1864         } catch (IOException e) {
1865             throw new IllegalStateException(e);
1866         }
1867     }
1868 
1869     private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
1870         @Override
getTetherStats(int how)1871         public NetworkStats getTetherStats(int how) {
1872             // We only need to return per-UID stats. Per-device stats are already counted by
1873             // interface counters.
1874             if (how != STATS_PER_UID) {
1875                 return new NetworkStats(SystemClock.elapsedRealtime(), 0);
1876             }
1877 
1878             final NativeDaemonEvent[] events;
1879             try {
1880                 events = mConnector.executeForList("bandwidth", "gettetherstats");
1881             } catch (NativeDaemonConnectorException e) {
1882                 throw e.rethrowAsParcelableException();
1883             }
1884             final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1885             for (NativeDaemonEvent event : events) {
1886                 if (event.getCode() != TetheringStatsListResult) continue;
1887 
1888                 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
1889                 final StringTokenizer tok = new StringTokenizer(event.getMessage());
1890                 try {
1891                     final String ifaceIn = tok.nextToken();
1892                     final String ifaceOut = tok.nextToken();
1893 
1894                     final NetworkStats.Entry entry = new NetworkStats.Entry();
1895                     entry.iface = ifaceOut;
1896                     entry.uid = UID_TETHERING;
1897                     entry.set = SET_DEFAULT;
1898                     entry.tag = TAG_NONE;
1899                     entry.rxBytes = Long.parseLong(tok.nextToken());
1900                     entry.rxPackets = Long.parseLong(tok.nextToken());
1901                     entry.txBytes = Long.parseLong(tok.nextToken());
1902                     entry.txPackets = Long.parseLong(tok.nextToken());
1903                     stats.combineValues(entry);
1904                 } catch (NoSuchElementException e) {
1905                     throw new IllegalStateException("problem parsing tethering stats: " + event);
1906                 } catch (NumberFormatException e) {
1907                     throw new IllegalStateException("problem parsing tethering stats: " + event);
1908                 }
1909             }
1910             return stats;
1911         }
1912 
1913         @Override
setInterfaceQuota(String iface, long quotaBytes)1914         public void setInterfaceQuota(String iface, long quotaBytes) {
1915             // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
1916         }
1917     }
1918 
1919     @Override
getNetworkStatsTethering(int how)1920     public NetworkStats getNetworkStatsTethering(int how) {
1921         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1922 
1923         final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1924         synchronized (mTetheringStatsProviders) {
1925             for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
1926                 try {
1927                     stats.combineAllValues(provider.getTetherStats(how));
1928                 } catch (RemoteException e) {
1929                     Log.e(TAG, "Problem reading tethering stats from " +
1930                             mTetheringStatsProviders.get(provider) + ": " + e);
1931                 }
1932             }
1933         }
1934         return stats;
1935     }
1936 
1937     @Override
setDnsConfigurationForNetwork(int netId, String[] servers, String domains)1938     public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) {
1939         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1940 
1941         ContentResolver resolver = mContext.getContentResolver();
1942 
1943         int sampleValidity = Settings.Global.getInt(resolver,
1944                 Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
1945                 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
1946         if (sampleValidity < 0 || sampleValidity > 65535) {
1947             Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" +
1948                     DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
1949             sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
1950         }
1951 
1952         int successThreshold = Settings.Global.getInt(resolver,
1953                 Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
1954                 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
1955         if (successThreshold < 0 || successThreshold > 100) {
1956             Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" +
1957                     DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
1958             successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
1959         }
1960 
1961         int minSamples = Settings.Global.getInt(resolver,
1962                 Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
1963         int maxSamples = Settings.Global.getInt(resolver,
1964                 Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
1965         if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) {
1966             Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples +
1967                     "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
1968                     DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
1969             minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
1970             maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
1971         }
1972 
1973         final String[] domainStrs = domains == null ? new String[0] : domains.split(" ");
1974         final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples };
1975         try {
1976             mNetdService.setResolverConfiguration(netId, servers, domainStrs, params);
1977         } catch (RemoteException e) {
1978             throw new RuntimeException(e);
1979         }
1980     }
1981 
1982     @Override
addVpnUidRanges(int netId, UidRange[] ranges)1983     public void addVpnUidRanges(int netId, UidRange[] ranges) {
1984         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1985         Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
1986         argv[0] = "users";
1987         argv[1] = "add";
1988         argv[2] = netId;
1989         int argc = 3;
1990         // Avoid overly long commands by limiting number of UID ranges per command.
1991         for (int i = 0; i < ranges.length; i++) {
1992             argv[argc++] = ranges[i].toString();
1993             if (i == (ranges.length - 1) || argc == argv.length) {
1994                 try {
1995                     mConnector.execute("network", Arrays.copyOf(argv, argc));
1996                 } catch (NativeDaemonConnectorException e) {
1997                     throw e.rethrowAsParcelableException();
1998                 }
1999                 argc = 3;
2000             }
2001         }
2002     }
2003 
2004     @Override
removeVpnUidRanges(int netId, UidRange[] ranges)2005     public void removeVpnUidRanges(int netId, UidRange[] ranges) {
2006         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2007         Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2008         argv[0] = "users";
2009         argv[1] = "remove";
2010         argv[2] = netId;
2011         int argc = 3;
2012         // Avoid overly long commands by limiting number of UID ranges per command.
2013         for (int i = 0; i < ranges.length; i++) {
2014             argv[argc++] = ranges[i].toString();
2015             if (i == (ranges.length - 1) || argc == argv.length) {
2016                 try {
2017                     mConnector.execute("network", Arrays.copyOf(argv, argc));
2018                 } catch (NativeDaemonConnectorException e) {
2019                     throw e.rethrowAsParcelableException();
2020                 }
2021                 argc = 3;
2022             }
2023         }
2024     }
2025 
2026     @Override
setFirewallEnabled(boolean enabled)2027     public void setFirewallEnabled(boolean enabled) {
2028         enforceSystemUid();
2029         try {
2030             mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist");
2031             mFirewallEnabled = enabled;
2032         } catch (NativeDaemonConnectorException e) {
2033             throw e.rethrowAsParcelableException();
2034         }
2035     }
2036 
2037     @Override
isFirewallEnabled()2038     public boolean isFirewallEnabled() {
2039         enforceSystemUid();
2040         return mFirewallEnabled;
2041     }
2042 
2043     @Override
setFirewallInterfaceRule(String iface, boolean allow)2044     public void setFirewallInterfaceRule(String iface, boolean allow) {
2045         enforceSystemUid();
2046         Preconditions.checkState(mFirewallEnabled);
2047         final String rule = allow ? "allow" : "deny";
2048         try {
2049             mConnector.execute("firewall", "set_interface_rule", iface, rule);
2050         } catch (NativeDaemonConnectorException e) {
2051             throw e.rethrowAsParcelableException();
2052         }
2053     }
2054 
closeSocketsForFirewallChainLocked(int chain, String chainName)2055     private void closeSocketsForFirewallChainLocked(int chain, String chainName) {
2056         // UID ranges to close sockets on.
2057         UidRange[] ranges;
2058         // UID ranges whose sockets we won't touch.
2059         int[] exemptUids;
2060 
2061         int numUids = 0;
2062 
2063         if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
2064             // Close all sockets on all non-system UIDs...
2065             ranges = new UidRange[] {
2066                 // TODO: is there a better way of finding all existing users? If so, we could
2067                 // specify their ranges here.
2068                 new UidRange(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
2069             };
2070             // ... except for the UIDs that have allow rules.
2071             synchronized (mRulesLock) {
2072                 final SparseIntArray rules = getUidFirewallRulesLR(chain);
2073                 exemptUids = new int[rules.size()];
2074                 for (int i = 0; i < exemptUids.length; i++) {
2075                     if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
2076                         exemptUids[numUids] = rules.keyAt(i);
2077                         numUids++;
2078                     }
2079                 }
2080             }
2081             // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
2082             // But the code does not guarantee this in any way, and at least in one case - if we add
2083             // a UID rule to the firewall, and then disable the firewall - the chains can contain
2084             // the wrong type of rule. In this case, don't close connections that we shouldn't.
2085             //
2086             // TODO: tighten up this code by ensuring we never set the wrong type of rule, and
2087             // fix setFirewallEnabled to grab mQuotaLock and clear rules.
2088             if (numUids != exemptUids.length) {
2089                 exemptUids = Arrays.copyOf(exemptUids, numUids);
2090             }
2091         } else {
2092             // Close sockets for every UID that has a deny rule...
2093             synchronized (mRulesLock) {
2094                 final SparseIntArray rules = getUidFirewallRulesLR(chain);
2095                 ranges = new UidRange[rules.size()];
2096                 for (int i = 0; i < ranges.length; i++) {
2097                     if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_DENY) {
2098                         int uid = rules.keyAt(i);
2099                         ranges[numUids] = new UidRange(uid, uid);
2100                         numUids++;
2101                     }
2102                 }
2103             }
2104             // As above; usually numUids == ranges.length, but not always.
2105             if (numUids != ranges.length) {
2106                 ranges = Arrays.copyOf(ranges, numUids);
2107             }
2108             // ... with no exceptions.
2109             exemptUids = new int[0];
2110         }
2111 
2112         try {
2113             mNetdService.socketDestroy(ranges, exemptUids);
2114         } catch(RemoteException | ServiceSpecificException e) {
2115             Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e);
2116         }
2117     }
2118 
2119     @Override
setFirewallChainEnabled(int chain, boolean enable)2120     public void setFirewallChainEnabled(int chain, boolean enable) {
2121         enforceSystemUid();
2122         synchronized (mQuotaLock) {
2123             synchronized (mRulesLock) {
2124                 if (getFirewallChainState(chain) == enable) {
2125                     // All is the same, nothing to do.  This relies on the fact that netd has child
2126                     // chains default detached.
2127                     return;
2128                 }
2129                 setFirewallChainState(chain, enable);
2130             }
2131 
2132             final String operation = enable ? "enable_chain" : "disable_chain";
2133             final String chainName;
2134             switch(chain) {
2135                 case FIREWALL_CHAIN_STANDBY:
2136                     chainName = FIREWALL_CHAIN_NAME_STANDBY;
2137                     break;
2138                 case FIREWALL_CHAIN_DOZABLE:
2139                     chainName = FIREWALL_CHAIN_NAME_DOZABLE;
2140                     break;
2141                 case FIREWALL_CHAIN_POWERSAVE:
2142                     chainName = FIREWALL_CHAIN_NAME_POWERSAVE;
2143                     break;
2144                 default:
2145                     throw new IllegalArgumentException("Bad child chain: " + chain);
2146             }
2147 
2148             try {
2149                 mConnector.execute("firewall", operation, chainName);
2150             } catch (NativeDaemonConnectorException e) {
2151                 throw e.rethrowAsParcelableException();
2152             }
2153 
2154             // Close any sockets that were opened by the affected UIDs. This has to be done after
2155             // disabling network connectivity, in case they react to the socket close by reopening
2156             // the connection and race with the iptables commands that enable the firewall. All
2157             // whitelist and blacklist chains allow RSTs through.
2158             if (enable) {
2159                 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
2160                 closeSocketsForFirewallChainLocked(chain, chainName);
2161             }
2162         }
2163     }
2164 
getFirewallType(int chain)2165     private int getFirewallType(int chain) {
2166         switch (chain) {
2167             case FIREWALL_CHAIN_STANDBY:
2168                 return FIREWALL_TYPE_BLACKLIST;
2169             case FIREWALL_CHAIN_DOZABLE:
2170                 return FIREWALL_TYPE_WHITELIST;
2171             case FIREWALL_CHAIN_POWERSAVE:
2172                 return FIREWALL_TYPE_WHITELIST;
2173             default:
2174                 return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
2175         }
2176     }
2177 
2178     @Override
setFirewallUidRules(int chain, int[] uids, int[] rules)2179     public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
2180         enforceSystemUid();
2181         synchronized (mQuotaLock) {
2182             synchronized (mRulesLock) {
2183                 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
2184                 SparseIntArray newRules = new SparseIntArray();
2185                 // apply new set of rules
2186                 for (int index = uids.length - 1; index >= 0; --index) {
2187                     int uid = uids[index];
2188                     int rule = rules[index];
2189                     updateFirewallUidRuleLocked(chain, uid, rule);
2190                     newRules.put(uid, rule);
2191                 }
2192                 // collect the rules to remove.
2193                 SparseIntArray rulesToRemove = new SparseIntArray();
2194                 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
2195                     int uid = uidFirewallRules.keyAt(index);
2196                     if (newRules.indexOfKey(uid) < 0) {
2197                         rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
2198                     }
2199                 }
2200                 // remove dead rules
2201                 for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
2202                     int uid = rulesToRemove.keyAt(index);
2203                     updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
2204                 }
2205             }
2206             try {
2207                 switch (chain) {
2208                     case FIREWALL_CHAIN_DOZABLE:
2209                         mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
2210                         break;
2211                     case FIREWALL_CHAIN_STANDBY:
2212                         mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
2213                         break;
2214                     case FIREWALL_CHAIN_POWERSAVE:
2215                         mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
2216                         break;
2217                     case FIREWALL_CHAIN_NONE:
2218                     default:
2219                         Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
2220                 }
2221             } catch (RemoteException e) {
2222                 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
2223             }
2224         }
2225     }
2226 
2227     @Override
setFirewallUidRule(int chain, int uid, int rule)2228     public void setFirewallUidRule(int chain, int uid, int rule) {
2229         enforceSystemUid();
2230         synchronized (mQuotaLock) {
2231             setFirewallUidRuleLocked(chain, uid, rule);
2232         }
2233     }
2234 
setFirewallUidRuleLocked(int chain, int uid, int rule)2235     private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
2236         if (updateFirewallUidRuleLocked(chain, uid, rule)) {
2237             try {
2238                 mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
2239                         getFirewallRuleName(chain, rule));
2240             } catch (NativeDaemonConnectorException e) {
2241                 throw e.rethrowAsParcelableException();
2242             }
2243         }
2244     }
2245 
2246     // TODO: now that netd supports batching, NMS should not keep these data structures anymore...
updateFirewallUidRuleLocked(int chain, int uid, int rule)2247     private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) {
2248         synchronized (mRulesLock) {
2249             SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
2250 
2251             final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
2252             if (DBG) {
2253                 Slog.d(TAG, "oldRule = " + oldUidFirewallRule
2254                         + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain);
2255             }
2256             if (oldUidFirewallRule == rule) {
2257                 if (DBG) Slog.d(TAG, "!!!!! Skipping change");
2258                 // TODO: eventually consider throwing
2259                 return false;
2260             }
2261 
2262             String ruleName = getFirewallRuleName(chain, rule);
2263             String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
2264 
2265             if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
2266                 uidFirewallRules.delete(uid);
2267             } else {
2268                 uidFirewallRules.put(uid, rule);
2269             }
2270             return !ruleName.equals(oldRuleName);
2271         }
2272     }
2273 
getFirewallRuleName(int chain, int rule)2274     private @NonNull String getFirewallRuleName(int chain, int rule) {
2275         String ruleName;
2276         if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
2277             if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
2278                 ruleName = "allow";
2279             } else {
2280                 ruleName = "deny";
2281             }
2282         } else { // Blacklist mode
2283             if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
2284                 ruleName = "deny";
2285             } else {
2286                 ruleName = "allow";
2287             }
2288         }
2289         return ruleName;
2290     }
2291 
getUidFirewallRulesLR(int chain)2292     private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) {
2293         switch (chain) {
2294             case FIREWALL_CHAIN_STANDBY:
2295                 return mUidFirewallStandbyRules;
2296             case FIREWALL_CHAIN_DOZABLE:
2297                 return mUidFirewallDozableRules;
2298             case FIREWALL_CHAIN_POWERSAVE:
2299                 return mUidFirewallPowerSaveRules;
2300             case FIREWALL_CHAIN_NONE:
2301                 return mUidFirewallRules;
2302             default:
2303                 throw new IllegalArgumentException("Unknown chain:" + chain);
2304         }
2305     }
2306 
getFirewallChainName(int chain)2307     public @NonNull String getFirewallChainName(int chain) {
2308         switch (chain) {
2309             case FIREWALL_CHAIN_STANDBY:
2310                 return FIREWALL_CHAIN_NAME_STANDBY;
2311             case FIREWALL_CHAIN_DOZABLE:
2312                 return FIREWALL_CHAIN_NAME_DOZABLE;
2313             case FIREWALL_CHAIN_POWERSAVE:
2314                 return FIREWALL_CHAIN_NAME_POWERSAVE;
2315             case FIREWALL_CHAIN_NONE:
2316                 return FIREWALL_CHAIN_NAME_NONE;
2317             default:
2318                 throw new IllegalArgumentException("Unknown chain:" + chain);
2319         }
2320     }
2321 
enforceSystemUid()2322     private static void enforceSystemUid() {
2323         final int uid = Binder.getCallingUid();
2324         if (uid != Process.SYSTEM_UID) {
2325             throw new SecurityException("Only available to AID_SYSTEM");
2326         }
2327     }
2328 
2329     @Override
startClatd(String interfaceName)2330     public void startClatd(String interfaceName) throws IllegalStateException {
2331         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2332 
2333         try {
2334             mConnector.execute("clatd", "start", interfaceName);
2335         } catch (NativeDaemonConnectorException e) {
2336             throw e.rethrowAsParcelableException();
2337         }
2338     }
2339 
2340     @Override
stopClatd(String interfaceName)2341     public void stopClatd(String interfaceName) throws IllegalStateException {
2342         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2343 
2344         try {
2345             mConnector.execute("clatd", "stop", interfaceName);
2346         } catch (NativeDaemonConnectorException e) {
2347             throw e.rethrowAsParcelableException();
2348         }
2349     }
2350 
2351     @Override
isClatdStarted(String interfaceName)2352     public boolean isClatdStarted(String interfaceName) {
2353         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2354 
2355         final NativeDaemonEvent event;
2356         try {
2357             event = mConnector.execute("clatd", "status", interfaceName);
2358         } catch (NativeDaemonConnectorException e) {
2359             throw e.rethrowAsParcelableException();
2360         }
2361 
2362         event.checkCode(ClatdStatusResult);
2363         return event.getMessage().endsWith("started");
2364     }
2365 
2366     @Override
registerNetworkActivityListener(INetworkActivityListener listener)2367     public void registerNetworkActivityListener(INetworkActivityListener listener) {
2368         mNetworkActivityListeners.register(listener);
2369     }
2370 
2371     @Override
unregisterNetworkActivityListener(INetworkActivityListener listener)2372     public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
2373         mNetworkActivityListeners.unregister(listener);
2374     }
2375 
2376     @Override
isNetworkActive()2377     public boolean isNetworkActive() {
2378         synchronized (mNetworkActivityListeners) {
2379             return mNetworkActive || mActiveIdleTimers.isEmpty();
2380         }
2381     }
2382 
reportNetworkActive()2383     private void reportNetworkActive() {
2384         final int length = mNetworkActivityListeners.beginBroadcast();
2385         try {
2386             for (int i = 0; i < length; i++) {
2387                 try {
2388                     mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
2389                 } catch (RemoteException | RuntimeException e) {
2390                 }
2391             }
2392         } finally {
2393             mNetworkActivityListeners.finishBroadcast();
2394         }
2395     }
2396 
2397     /** {@inheritDoc} */
2398     @Override
monitor()2399     public void monitor() {
2400         if (mConnector != null) {
2401             mConnector.monitor();
2402         }
2403     }
2404 
2405     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)2406     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2407         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
2408 
2409         pw.println("NetworkManagementService NativeDaemonConnector Log:");
2410         mConnector.dump(fd, pw, args);
2411         pw.println();
2412 
2413         pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
2414         pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
2415                 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
2416         pw.print("mNetworkActive="); pw.println(mNetworkActive);
2417 
2418         synchronized (mQuotaLock) {
2419             pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
2420             pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
2421             pw.print("Data saver mode: "); pw.println(mDataSaverMode);
2422             synchronized (mRulesLock) {
2423                 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
2424                 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
2425             }
2426         }
2427 
2428         synchronized (mRulesLock) {
2429             dumpUidFirewallRule(pw, "", mUidFirewallRules);
2430 
2431             pw.print("UID firewall standby chain enabled: "); pw.println(
2432                     getFirewallChainState(FIREWALL_CHAIN_STANDBY));
2433             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
2434 
2435             pw.print("UID firewall dozable chain enabled: "); pw.println(
2436                     getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
2437             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
2438 
2439             pw.println("UID firewall powersave chain enabled: " +
2440                     getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
2441             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
2442         }
2443 
2444         synchronized (mIdleTimerLock) {
2445             pw.println("Idle timers:");
2446             for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
2447                 pw.print("  "); pw.print(ent.getKey()); pw.println(":");
2448                 IdleTimerParams params = ent.getValue();
2449                 pw.print("    timeout="); pw.print(params.timeout);
2450                 pw.print(" type="); pw.print(params.type);
2451                 pw.print(" networkCount="); pw.println(params.networkCount);
2452             }
2453         }
2454 
2455         pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
2456         pw.print("Netd service status: " );
2457         if (mNetdService == null) {
2458             pw.println("disconnected");
2459         } else {
2460             try {
2461                 final boolean alive = mNetdService.isAlive();
2462                 pw.println(alive ? "alive": "dead");
2463             } catch (RemoteException e) {
2464                 pw.println("unreachable");
2465             }
2466         }
2467     }
2468 
dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list)2469     private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
2470         pw.print("UID bandwith control ");
2471         pw.print(name);
2472         pw.print(" rule: [");
2473         final int size = list.size();
2474         for (int i = 0; i < size; i++) {
2475             pw.print(list.keyAt(i));
2476             if (i < size - 1) pw.print(",");
2477         }
2478         pw.println("]");
2479     }
2480 
dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules)2481     private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
2482         pw.print("UID firewall ");
2483         pw.print(name);
2484         pw.print(" rule: [");
2485         final int size = rules.size();
2486         for (int i = 0; i < size; i++) {
2487             pw.print(rules.keyAt(i));
2488             pw.print(":");
2489             pw.print(rules.valueAt(i));
2490             if (i < size - 1) pw.print(",");
2491         }
2492         pw.println("]");
2493     }
2494 
2495     @Override
createPhysicalNetwork(int netId, String permission)2496     public void createPhysicalNetwork(int netId, String permission) {
2497         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2498 
2499         try {
2500             if (permission != null) {
2501                 mConnector.execute("network", "create", netId, permission);
2502             } else {
2503                 mConnector.execute("network", "create", netId);
2504             }
2505         } catch (NativeDaemonConnectorException e) {
2506             throw e.rethrowAsParcelableException();
2507         }
2508     }
2509 
2510     @Override
createVirtualNetwork(int netId, boolean hasDNS, boolean secure)2511     public void createVirtualNetwork(int netId, boolean hasDNS, boolean secure) {
2512         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2513 
2514         try {
2515             mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0",
2516                     secure ? "1" : "0");
2517         } catch (NativeDaemonConnectorException e) {
2518             throw e.rethrowAsParcelableException();
2519         }
2520     }
2521 
2522     @Override
removeNetwork(int netId)2523     public void removeNetwork(int netId) {
2524         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2525 
2526         try {
2527             mConnector.execute("network", "destroy", netId);
2528         } catch (NativeDaemonConnectorException e) {
2529             throw e.rethrowAsParcelableException();
2530         }
2531     }
2532 
2533     @Override
addInterfaceToNetwork(String iface, int netId)2534     public void addInterfaceToNetwork(String iface, int netId) {
2535         modifyInterfaceInNetwork("add", "" + netId, iface);
2536     }
2537 
2538     @Override
removeInterfaceFromNetwork(String iface, int netId)2539     public void removeInterfaceFromNetwork(String iface, int netId) {
2540         modifyInterfaceInNetwork("remove", "" + netId, iface);
2541     }
2542 
modifyInterfaceInNetwork(String action, String netId, String iface)2543     private void modifyInterfaceInNetwork(String action, String netId, String iface) {
2544         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2545         try {
2546             mConnector.execute("network", "interface", action, netId, iface);
2547         } catch (NativeDaemonConnectorException e) {
2548             throw e.rethrowAsParcelableException();
2549         }
2550     }
2551 
2552     @Override
addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid)2553     public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
2554         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2555 
2556         final Command cmd = new Command("network", "route", "legacy", uid, "add", netId);
2557 
2558         // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
2559         final LinkAddress la = routeInfo.getDestinationLinkAddress();
2560         cmd.appendArg(routeInfo.getInterface());
2561         cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength());
2562         if (routeInfo.hasGateway()) {
2563             cmd.appendArg(routeInfo.getGateway().getHostAddress());
2564         }
2565 
2566         try {
2567             mConnector.execute(cmd);
2568         } catch (NativeDaemonConnectorException e) {
2569             throw e.rethrowAsParcelableException();
2570         }
2571     }
2572 
2573     @Override
setDefaultNetId(int netId)2574     public void setDefaultNetId(int netId) {
2575         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2576 
2577         try {
2578             mConnector.execute("network", "default", "set", netId);
2579         } catch (NativeDaemonConnectorException e) {
2580             throw e.rethrowAsParcelableException();
2581         }
2582     }
2583 
2584     @Override
clearDefaultNetId()2585     public void clearDefaultNetId() {
2586         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2587 
2588         try {
2589             mConnector.execute("network", "default", "clear");
2590         } catch (NativeDaemonConnectorException e) {
2591             throw e.rethrowAsParcelableException();
2592         }
2593     }
2594 
2595     @Override
setNetworkPermission(int netId, String permission)2596     public void setNetworkPermission(int netId, String permission) {
2597         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2598 
2599         try {
2600             if (permission != null) {
2601                 mConnector.execute("network", "permission", "network", "set", permission, netId);
2602             } else {
2603                 mConnector.execute("network", "permission", "network", "clear", netId);
2604             }
2605         } catch (NativeDaemonConnectorException e) {
2606             throw e.rethrowAsParcelableException();
2607         }
2608     }
2609 
2610 
2611     @Override
setPermission(String permission, int[] uids)2612     public void setPermission(String permission, int[] uids) {
2613         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2614 
2615         Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND];
2616         argv[0] = "permission";
2617         argv[1] = "user";
2618         argv[2] = "set";
2619         argv[3] = permission;
2620         int argc = 4;
2621         // Avoid overly long commands by limiting number of UIDs per command.
2622         for (int i = 0; i < uids.length; ++i) {
2623             argv[argc++] = uids[i];
2624             if (i == uids.length - 1 || argc == argv.length) {
2625                 try {
2626                     mConnector.execute("network", Arrays.copyOf(argv, argc));
2627                 } catch (NativeDaemonConnectorException e) {
2628                     throw e.rethrowAsParcelableException();
2629                 }
2630                 argc = 4;
2631             }
2632         }
2633     }
2634 
2635     @Override
clearPermission(int[] uids)2636     public void clearPermission(int[] uids) {
2637         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2638 
2639         Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2640         argv[0] = "permission";
2641         argv[1] = "user";
2642         argv[2] = "clear";
2643         int argc = 3;
2644         // Avoid overly long commands by limiting number of UIDs per command.
2645         for (int i = 0; i < uids.length; ++i) {
2646             argv[argc++] = uids[i];
2647             if (i == uids.length - 1 || argc == argv.length) {
2648                 try {
2649                     mConnector.execute("network", Arrays.copyOf(argv, argc));
2650                 } catch (NativeDaemonConnectorException e) {
2651                     throw e.rethrowAsParcelableException();
2652                 }
2653                 argc = 3;
2654             }
2655         }
2656     }
2657 
2658     @Override
allowProtect(int uid)2659     public void allowProtect(int uid) {
2660         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2661 
2662         try {
2663             mConnector.execute("network", "protect", "allow", uid);
2664         } catch (NativeDaemonConnectorException e) {
2665             throw e.rethrowAsParcelableException();
2666         }
2667     }
2668 
2669     @Override
denyProtect(int uid)2670     public void denyProtect(int uid) {
2671         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2672 
2673         try {
2674             mConnector.execute("network", "protect", "deny", uid);
2675         } catch (NativeDaemonConnectorException e) {
2676             throw e.rethrowAsParcelableException();
2677         }
2678     }
2679 
2680     @Override
addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes)2681     public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
2682         modifyInterfaceInNetwork("add", "local", iface);
2683 
2684         for (RouteInfo route : routes) {
2685             if (!route.isDefaultRoute()) {
2686                 modifyRoute("add", "local", route);
2687             }
2688         }
2689     }
2690 
2691     @Override
removeInterfaceFromLocalNetwork(String iface)2692     public void removeInterfaceFromLocalNetwork(String iface) {
2693         modifyInterfaceInNetwork("remove", "local", iface);
2694     }
2695 
2696     @Override
removeRoutesFromLocalNetwork(List<RouteInfo> routes)2697     public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
2698         int failures = 0;
2699 
2700         for (RouteInfo route : routes) {
2701             try {
2702                 modifyRoute("remove", "local", route);
2703             } catch (IllegalStateException e) {
2704                 failures++;
2705             }
2706         }
2707 
2708         return failures;
2709     }
2710 
2711     @Override
isNetworkRestricted(int uid)2712     public boolean isNetworkRestricted(int uid) {
2713         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2714         return isNetworkRestrictedInternal(uid);
2715     }
2716 
isNetworkRestrictedInternal(int uid)2717     private boolean isNetworkRestrictedInternal(int uid) {
2718         synchronized (mRulesLock) {
2719             if (getFirewallChainState(FIREWALL_CHAIN_STANDBY)
2720                     && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) {
2721                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode");
2722                 return true;
2723             }
2724             if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE)
2725                     && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) {
2726                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode");
2727                 return true;
2728             }
2729             if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)
2730                     && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) {
2731                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
2732                 return true;
2733             }
2734             if (mUidRejectOnMetered.get(uid)) {
2735                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
2736                         + " in the background");
2737                 return true;
2738             }
2739             if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) {
2740                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode");
2741                 return true;
2742             }
2743             return false;
2744         }
2745     }
2746 
setFirewallChainState(int chain, boolean state)2747     private void setFirewallChainState(int chain, boolean state) {
2748         synchronized (mRulesLock) {
2749             mFirewallChainStates.put(chain, state);
2750         }
2751     }
2752 
getFirewallChainState(int chain)2753     private boolean getFirewallChainState(int chain) {
2754         synchronized (mRulesLock) {
2755             return mFirewallChainStates.get(chain);
2756         }
2757     }
2758 
2759     @VisibleForTesting
2760     class LocalService extends NetworkManagementInternal {
2761         @Override
isNetworkRestrictedForUid(int uid)2762         public boolean isNetworkRestrictedForUid(int uid) {
2763             return isNetworkRestrictedInternal(uid);
2764         }
2765     }
2766 
2767     @VisibleForTesting
getInjector()2768     Injector getInjector() {
2769         return new Injector();
2770     }
2771 
2772     @VisibleForTesting
2773     class Injector {
setDataSaverMode(boolean dataSaverMode)2774         void setDataSaverMode(boolean dataSaverMode) {
2775             mDataSaverMode = dataSaverMode;
2776         }
2777 
setFirewallChainState(int chain, boolean state)2778         void setFirewallChainState(int chain, boolean state) {
2779             NetworkManagementService.this.setFirewallChainState(chain, state);
2780         }
2781 
setFirewallRule(int chain, int uid, int rule)2782         void setFirewallRule(int chain, int uid, int rule) {
2783             synchronized (mRulesLock) {
2784                 getUidFirewallRulesLR(chain).put(uid, rule);
2785             }
2786         }
2787 
setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable)2788         void setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable) {
2789             synchronized (mRulesLock) {
2790                 if (blacklist) {
2791                     mUidRejectOnMetered.put(uid, enable);
2792                 } else {
2793                     mUidAllowOnMetered.put(uid, enable);
2794                 }
2795             }
2796         }
2797 
reset()2798         void reset() {
2799             synchronized (mRulesLock) {
2800                 setDataSaverMode(false);
2801                 final int[] chains = {
2802                         FIREWALL_CHAIN_DOZABLE,
2803                         FIREWALL_CHAIN_STANDBY,
2804                         FIREWALL_CHAIN_POWERSAVE
2805                 };
2806                 for (int chain : chains) {
2807                     setFirewallChainState(chain, false);
2808                     getUidFirewallRulesLR(chain).clear();
2809                 }
2810                 mUidAllowOnMetered.clear();
2811                 mUidRejectOnMetered.clear();
2812             }
2813         }
2814     }
2815 }
2816