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