2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server;
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_DEFAULT;
31 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
32 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST;
33 import static android.net.NetworkStats.SET_DEFAULT;
34 import static android.net.NetworkStats.TAG_ALL;
35 import static android.net.NetworkStats.TAG_NONE;
36 import static android.net.NetworkStats.UID_ALL;
37 import static android.net.TrafficStats.UID_TETHERING;
38 import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult;
39 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
40 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
41 import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult;
42 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult;
43 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult;
44 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult;
45 import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult;
46 import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
47 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
48 import android.annotation.NonNull;
49 import android.app.ActivityManagerNative;
50 import android.content.ContentResolver;
51 import android.content.Context;
52 import android.net.ConnectivityManager;
53 import android.net.INetd;
54 import android.net.INetworkManagementEventObserver;
55 import android.net.InterfaceConfiguration;
56 import android.net.IpPrefix;
57 import android.net.LinkAddress;
58 import android.net.Network;
59 import android.net.NetworkPolicyManager;
60 import android.net.NetworkStats;
61 import android.net.NetworkUtils;
62 import android.net.RouteInfo;
63 import android.net.UidRange;
64 import android.net.wifi.WifiConfiguration;
65 import android.net.wifi.WifiConfiguration.KeyMgmt;
66 import android.os.BatteryStats;
67 import android.os.Binder;
68 import android.os.Handler;
69 import android.os.INetworkActivityListener;
70 import android.os.INetworkManagementService;
71 import android.os.PowerManager;
72 import android.os.Process;
73 import android.os.RemoteCallbackList;
74 import android.os.RemoteException;
75 import android.os.ServiceManager;
76 import android.os.ServiceSpecificException;
77 import android.os.StrictMode;
78 import android.os.SystemClock;
79 import android.os.SystemProperties;
80 import android.provider.Settings;
81 import android.telephony.DataConnectionRealTimeInfo;
82 import android.telephony.PhoneStateListener;
83 import android.telephony.SubscriptionManager;
84 import android.telephony.TelephonyManager;
85 import android.util.Log;
86 import android.util.Slog;
87 import android.util.SparseBooleanArray;
88 import android.util.SparseIntArray;
90 import com.android.internal.annotations.GuardedBy;
91 import com.android.internal.app.IBatteryStats;
92 import com.android.internal.net.NetworkStatsFactory;
93 import com.android.internal.util.HexDump;
94 import com.android.internal.util.Preconditions;
95 import com.android.server.NativeDaemonConnector.Command;
96 import com.android.server.NativeDaemonConnector.SensitiveArg;
97 import com.android.server.net.LockdownVpnTracker;
98 import com.google.android.collect.Maps;
100 import java.io.BufferedReader;
101 import java.io.DataInputStream;
103 import java.io.FileDescriptor;
104 import java.io.FileInputStream;
105 import java.io.IOException;
106 import java.io.InputStreamReader;
107 import java.io.PrintWriter;
108 import java.net.InetAddress;
109 import java.net.InterfaceAddress;
110 import java.net.NetworkInterface;
111 import java.net.SocketException;
112 import java.util.ArrayList;
113 import java.util.Arrays;
114 import java.util.HashMap;
115 import java.util.List;
116 import java.util.Map;
117 import java.util.NoSuchElementException;
118 import java.util.StringTokenizer;
119 import java.util.concurrent.CountDownLatch;
124 public class NetworkManagementService extends INetworkManagementService.Stub
125 implements Watchdog.Monitor {
126 private static final String TAG = "NetworkManagement";
127 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
128 private static final String NETD_TAG = "NetdConnector";
129 private static final String NETD_SERVICE_NAME = "netd";
131 private static final int MAX_UID_RANGES_PER_COMMAND = 10;
134 * Name representing {@link #setGlobalAlert(long)} limit when delivered to
135 * {@link INetworkManagementEventObserver#limitReached(String, String)}.
137 public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
140 * String to pass to netd to indicate that a network is only accessible
141 * to apps that have the CHANGE_NETWORK_STATE permission.
143 public static final String PERMISSION_NETWORK = "NETWORK";
146 * String to pass to netd to indicate that a network is only
147 * accessible to system apps and those with the CONNECTIVITY_INTERNAL
150 public static final String PERMISSION_SYSTEM = "SYSTEM";
152 class NetdResponseCode {
153 /* Keep in sync with system/netd/server/ResponseCode.h */
154 public static final int InterfaceListResult = 110;
155 public static final int TetherInterfaceListResult = 111;
156 public static final int TetherDnsFwdTgtListResult = 112;
157 public static final int TtyListResult = 113;
158 public static final int TetheringStatsListResult = 114;
160 public static final int TetherStatusResult = 210;
161 public static final int IpFwdStatusResult = 211;
162 public static final int InterfaceGetCfgResult = 213;
163 public static final int SoftapStatusResult = 214;
164 public static final int InterfaceRxCounterResult = 216;
165 public static final int InterfaceTxCounterResult = 217;
166 public static final int QuotaCounterResult = 220;
167 public static final int TetheringStatsResult = 221;
168 public static final int DnsProxyQueryResult = 222;
169 public static final int ClatdStatusResult = 223;
171 public static final int InterfaceChange = 600;
172 public static final int BandwidthControl = 601;
173 public static final int InterfaceClassActivity = 613;
174 public static final int InterfaceAddressChange = 614;
175 public static final int InterfaceDnsServerInfo = 615;
176 public static final int RouteChange = 616;
177 public static final int StrictCleartext = 617;
180 /* Defaults for resolver parameters. */
181 public static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
182 public static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
183 public static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
184 public static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
187 * String indicating a softap command.
189 static final String SOFT_AP_COMMAND = "softap";
192 * String passed back to netd connector indicating softap command success.
194 static final String SOFT_AP_COMMAND_SUCCESS = "Ok";
196 static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
199 * Binder context for this service
201 private final Context mContext;
204 * connector object for communicating with netd
206 private final NativeDaemonConnector mConnector;
208 private final Handler mFgHandler;
209 private final Handler mDaemonHandler;
211 private INetd mNetdService;
213 private IBatteryStats mBatteryStats;
215 private final Thread mThread;
216 private CountDownLatch mConnectedSignal = new CountDownLatch(1);
218 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
219 new RemoteCallbackList<INetworkManagementEventObserver>();
221 private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
223 private Object mQuotaLock = new Object();
225 /** Set of interfaces with active quotas. */
226 @GuardedBy("mQuotaLock")
227 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
228 /** Set of interfaces with active alerts. */
229 @GuardedBy("mQuotaLock")
230 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
231 /** Set of UIDs blacklisted on metered networks. */
232 @GuardedBy("mQuotaLock")
233 private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
234 /** Set of UIDs whitelisted on metered networks. */
235 @GuardedBy("mQuotaLock")
236 private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
237 /** Set of UIDs with cleartext penalties. */
238 @GuardedBy("mQuotaLock")
239 private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
240 /** Set of UIDs that are to be blocked/allowed by firewall controller. */
241 @GuardedBy("mQuotaLock")
242 private SparseIntArray mUidFirewallRules = new SparseIntArray();
244 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
245 * to application idles.
247 @GuardedBy("mQuotaLock")
248 private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
250 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
253 @GuardedBy("mQuotaLock")
254 private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
256 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
257 * to device on power-save mode.
259 @GuardedBy("mQuotaLock")
260 private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
261 /** Set of states for the child firewall chains. True if the chain is active. */
262 @GuardedBy("mQuotaLock")
263 final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
265 @GuardedBy("mQuotaLock")
266 private boolean mDataSaverMode;
268 private Object mIdleTimerLock = new Object();
269 /** Set of interfaces with active idle timers. */
270 private static class IdleTimerParams {
271 public final int timeout;
272 public final int type;
273 public int networkCount;
275 IdleTimerParams(int timeout, int type) {
276 this.timeout = timeout;
278 this.networkCount = 1;
281 private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
283 private volatile boolean mBandwidthControlEnabled;
284 private volatile boolean mFirewallEnabled;
285 private volatile boolean mStrictEnabled;
287 private boolean mMobileActivityFromRadio = false;
288 private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
289 private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
291 private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
292 new RemoteCallbackList<INetworkActivityListener>();
293 private boolean mNetworkActive;
296 * Constructs a new NetworkManagementService instance
298 * @param context Binder context for this service
300 private NetworkManagementService(Context context, String socket) {
303 // make sure this is on the same looper as our NativeDaemonConnector for sync purposes
304 mFgHandler = new Handler(FgThread.get().getLooper());
306 // Don't need this wake lock, since we now have a time stamp for when
307 // the network actually went inactive. (It might be nice to still do this,
308 // but I don't want to do it through the power manager because that pollutes the
309 // battery stats history with pointless noise.)
310 //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
311 PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
313 mConnector = new NativeDaemonConnector(
314 new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
315 FgThread.get().getLooper());
316 mThread = new Thread(mConnector, NETD_TAG);
318 mDaemonHandler = new Handler(FgThread.get().getLooper());
320 // Add ourself to the Watchdog monitors.
321 Watchdog.getInstance().addMonitor(this);
324 static NetworkManagementService create(Context context, String socket)
325 throws InterruptedException {
326 final NetworkManagementService service = new NetworkManagementService(context, socket);
327 final CountDownLatch connectedSignal = service.mConnectedSignal;
328 if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
329 service.mThread.start();
330 if (DBG) Slog.d(TAG, "Awaiting socket connection");
331 connectedSignal.await();
332 if (DBG) Slog.d(TAG, "Connected");
333 service.connectNativeNetdService();
337 public static NetworkManagementService create(Context context) throws InterruptedException {
338 return create(context, NETD_SERVICE_NAME);
341 public void systemReady() {
343 final long start = System.currentTimeMillis();
344 prepareNativeDaemon();
345 final long delta = System.currentTimeMillis() - start;
346 Slog.d(TAG, "Prepared in " + delta + "ms");
349 prepareNativeDaemon();
353 private IBatteryStats getBatteryStats() {
354 synchronized (this) {
355 if (mBatteryStats != null) {
356 return mBatteryStats;
358 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
359 BatteryStats.SERVICE_NAME));
360 return mBatteryStats;
365 public void registerObserver(INetworkManagementEventObserver observer) {
366 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
367 mObservers.register(observer);
371 public void unregisterObserver(INetworkManagementEventObserver observer) {
372 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
373 mObservers.unregister(observer);
377 * Notify our observers of an interface status change
379 private void notifyInterfaceStatusChanged(String iface, boolean up) {
380 final int length = mObservers.beginBroadcast();
382 for (int i = 0; i < length; i++) {
384 mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up);
385 } catch (RemoteException | RuntimeException e) {
389 mObservers.finishBroadcast();
394 * Notify our observers of an interface link state change
395 * (typically, an Ethernet cable has been plugged-in or unplugged).
397 private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
398 final int length = mObservers.beginBroadcast();
400 for (int i = 0; i < length; i++) {
402 mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up);
403 } catch (RemoteException | RuntimeException e) {
407 mObservers.finishBroadcast();
412 * Notify our observers of an interface addition.
414 private void notifyInterfaceAdded(String iface) {
415 final int length = mObservers.beginBroadcast();
417 for (int i = 0; i < length; i++) {
419 mObservers.getBroadcastItem(i).interfaceAdded(iface);
420 } catch (RemoteException | RuntimeException e) {
424 mObservers.finishBroadcast();
429 * Notify our observers of an interface removal.
431 private void notifyInterfaceRemoved(String iface) {
432 // netd already clears out quota and alerts for removed ifaces; update
433 // our sanity-checking state.
434 mActiveAlerts.remove(iface);
435 mActiveQuotas.remove(iface);
437 final int length = mObservers.beginBroadcast();
439 for (int i = 0; i < length; i++) {
441 mObservers.getBroadcastItem(i).interfaceRemoved(iface);
442 } catch (RemoteException | RuntimeException e) {
446 mObservers.finishBroadcast();
451 * Notify our observers of a limit reached.
453 private void notifyLimitReached(String limitName, String iface) {
454 final int length = mObservers.beginBroadcast();
456 for (int i = 0; i < length; i++) {
458 mObservers.getBroadcastItem(i).limitReached(limitName, iface);
459 } catch (RemoteException | RuntimeException e) {
463 mObservers.finishBroadcast();
468 * Notify our observers of a change in the data activity state of the interface
470 private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos,
471 int uid, boolean fromRadio) {
472 final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
475 if (mMobileActivityFromRadio) {
476 // If this call is not coming from a report from the radio itself, but we
477 // have previously received reports from the radio, then we will take the
478 // power state to just be whatever the radio last reported.
479 powerState = mLastPowerStateFromRadio;
482 mMobileActivityFromRadio = true;
484 if (mLastPowerStateFromRadio != powerState) {
485 mLastPowerStateFromRadio = powerState;
487 getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
488 } catch (RemoteException e) {
493 if (ConnectivityManager.isNetworkTypeWifi(type)) {
494 if (mLastPowerStateFromWifi != powerState) {
495 mLastPowerStateFromWifi = powerState;
497 getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
498 } catch (RemoteException e) {
503 boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
504 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
506 if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
507 // Report the change in data activity. We don't do this if this is a change
508 // on the mobile network, that is not coming from the radio itself, and we
509 // have previously seen change reports from the radio. In that case only
510 // the radio is the authority for the current state.
511 final int length = mObservers.beginBroadcast();
513 for (int i = 0; i < length; i++) {
515 mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(
516 Integer.toString(type), isActive, tsNanos);
517 } catch (RemoteException | RuntimeException e) {
521 mObservers.finishBroadcast();
525 boolean report = false;
526 synchronized (mIdleTimerLock) {
527 if (mActiveIdleTimers.isEmpty()) {
528 // If there are no idle timers, we are not monitoring activity, so we
529 // are always considered active.
532 if (mNetworkActive != isActive) {
533 mNetworkActive = isActive;
538 reportNetworkActive();
542 // Sync the state of the given chain with the native daemon.
543 private void syncFirewallChainLocked(int chain, SparseIntArray uidFirewallRules, String name) {
544 int size = uidFirewallRules.size();
546 // Make a copy of the current rules, and then clear them. This is because
547 // setFirewallUidRuleInternal only pushes down rules to the native daemon if they are
548 // different from the current rules stored in the mUidFirewall*Rules array for the
549 // specified chain. If we don't clear the rules, setFirewallUidRuleInternal will do
551 final SparseIntArray rules = uidFirewallRules.clone();
552 uidFirewallRules.clear();
554 // Now push the rules. setFirewallUidRuleInternal will push each of these down to the
555 // native daemon, and also add them to the mUidFirewall*Rules array for the specified
557 if (DBG) Slog.d(TAG, "Pushing " + size + " active firewall " + name + "UID rules");
558 for (int i = 0; i < rules.size(); i++) {
559 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i));
564 private void connectNativeNetdService() {
565 boolean nativeServiceAvailable = false;
567 mNetdService = INetd.Stub.asInterface(ServiceManager.getService(NETD_SERVICE_NAME));
568 nativeServiceAvailable = mNetdService.isAlive();
569 } catch (RemoteException e) {}
570 if (!nativeServiceAvailable) {
571 Slog.wtf(TAG, "Can't connect to NativeNetdService " + NETD_SERVICE_NAME);
576 * Prepare native daemon once connected, enabling modules and pushing any
577 * existing in-memory rules.
579 private void prepareNativeDaemon() {
581 mBandwidthControlEnabled = false;
583 // only enable bandwidth control when support exists
584 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
585 if (hasKernelSupport) {
586 Slog.d(TAG, "enabling bandwidth control");
588 mConnector.execute("bandwidth", "enable");
589 mBandwidthControlEnabled = true;
590 } catch (NativeDaemonConnectorException e) {
591 Log.wtf(TAG, "problem enabling bandwidth controls", e);
594 Slog.i(TAG, "not enabling bandwidth control");
597 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
599 if (mBandwidthControlEnabled) {
601 getBatteryStats().noteNetworkStatsEnabled();
602 } catch (RemoteException e) {
607 mConnector.execute("strict", "enable");
608 mStrictEnabled = true;
609 } catch (NativeDaemonConnectorException e) {
610 Log.wtf(TAG, "Failed strict enable", e);
613 // push any existing quota or UID rules
614 synchronized (mQuotaLock) {
616 setDataSaverModeEnabled(mDataSaverMode);
618 int size = mActiveQuotas.size();
620 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
621 final HashMap<String, Long> activeQuotas = mActiveQuotas;
622 mActiveQuotas = Maps.newHashMap();
623 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
624 setInterfaceQuota(entry.getKey(), entry.getValue());
628 size = mActiveAlerts.size();
630 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
631 final HashMap<String, Long> activeAlerts = mActiveAlerts;
632 mActiveAlerts = Maps.newHashMap();
633 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
634 setInterfaceAlert(entry.getKey(), entry.getValue());
638 size = mUidRejectOnMetered.size();
640 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
641 final SparseBooleanArray uidRejectOnQuota = mUidRejectOnMetered;
642 mUidRejectOnMetered = new SparseBooleanArray();
643 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
644 setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
645 uidRejectOnQuota.valueAt(i));
649 size = mUidAllowOnMetered.size();
651 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
652 final SparseBooleanArray uidAcceptOnQuota = mUidAllowOnMetered;
653 mUidAllowOnMetered = new SparseBooleanArray();
654 for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
655 setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
656 uidAcceptOnQuota.valueAt(i));
660 size = mUidCleartextPolicy.size();
662 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
663 final SparseIntArray local = mUidCleartextPolicy;
664 mUidCleartextPolicy = new SparseIntArray();
665 for (int i = 0; i < local.size(); i++) {
666 setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
670 setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled());
672 syncFirewallChainLocked(FIREWALL_CHAIN_NONE, mUidFirewallRules, "");
673 syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, mUidFirewallStandbyRules, "standby ");
674 syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mUidFirewallDozableRules, "dozable ");
675 syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, mUidFirewallPowerSaveRules,
678 if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)) {
679 setFirewallChainEnabled(FIREWALL_CHAIN_STANDBY, true);
681 if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)) {
682 setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true);
684 if (mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)) {
685 setFirewallChainEnabled(FIREWALL_CHAIN_POWERSAVE, true);
691 * Notify our observers of a new or updated interface address.
693 private void notifyAddressUpdated(String iface, LinkAddress address) {
694 final int length = mObservers.beginBroadcast();
696 for (int i = 0; i < length; i++) {
698 mObservers.getBroadcastItem(i).addressUpdated(iface, address);
699 } catch (RemoteException | RuntimeException e) {
703 mObservers.finishBroadcast();
708 * Notify our observers of a deleted interface address.
710 private void notifyAddressRemoved(String iface, LinkAddress address) {
711 final int length = mObservers.beginBroadcast();
713 for (int i = 0; i < length; i++) {
715 mObservers.getBroadcastItem(i).addressRemoved(iface, address);
716 } catch (RemoteException | RuntimeException e) {
720 mObservers.finishBroadcast();
725 * Notify our observers of DNS server information received.
727 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
728 final int length = mObservers.beginBroadcast();
730 for (int i = 0; i < length; i++) {
732 mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime,
734 } catch (RemoteException | RuntimeException e) {
738 mObservers.finishBroadcast();
743 * Notify our observers of a route change.
745 private void notifyRouteChange(String action, RouteInfo route) {
746 final int length = mObservers.beginBroadcast();
748 for (int i = 0; i < length; i++) {
750 if (action.equals("updated")) {
751 mObservers.getBroadcastItem(i).routeUpdated(route);
753 mObservers.getBroadcastItem(i).routeRemoved(route);
755 } catch (RemoteException | RuntimeException e) {
759 mObservers.finishBroadcast();
764 // Netd Callback handling
767 private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
769 public void onDaemonConnected() {
770 Slog.i(TAG, "onDaemonConnected()");
771 // event is dispatched from internal NDC thread, so we prepare the
772 // daemon back on main thread.
773 if (mConnectedSignal != null) {
774 // The system is booting and we're connecting to netd for the first time.
775 mConnectedSignal.countDown();
776 mConnectedSignal = null;
778 // We're reconnecting to netd after the socket connection
779 // was interrupted (e.g., if it crashed).
780 mFgHandler.post(new Runnable() {
783 connectNativeNetdService();
784 prepareNativeDaemon();
791 public boolean onCheckHoldWakeLock(int code) {
792 return code == NetdResponseCode.InterfaceClassActivity;
796 public boolean onEvent(int code, String raw, String[] cooked) {
797 String errorMessage = String.format("Invalid event from daemon (%s)", raw);
799 case NetdResponseCode.InterfaceChange:
801 * a network interface change occured
802 * Format: "NNN Iface added <name>"
803 * "NNN Iface removed <name>"
804 * "NNN Iface changed <name> <up/down>"
805 * "NNN Iface linkstatus <name> <up/down>"
807 if (cooked.length < 4 || !cooked[1].equals("Iface")) {
808 throw new IllegalStateException(errorMessage);
810 if (cooked[2].equals("added")) {
811 notifyInterfaceAdded(cooked[3]);
813 } else if (cooked[2].equals("removed")) {
814 notifyInterfaceRemoved(cooked[3]);
816 } else if (cooked[2].equals("changed") && cooked.length == 5) {
817 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
819 } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
820 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
823 throw new IllegalStateException(errorMessage);
825 case NetdResponseCode.BandwidthControl:
827 * Bandwidth control needs some attention
828 * Format: "NNN limit alert <alertName> <ifaceName>"
830 if (cooked.length < 5 || !cooked[1].equals("limit")) {
831 throw new IllegalStateException(errorMessage);
833 if (cooked[2].equals("alert")) {
834 notifyLimitReached(cooked[3], cooked[4]);
837 throw new IllegalStateException(errorMessage);
839 case NetdResponseCode.InterfaceClassActivity:
841 * An network interface class state changed (active/idle)
842 * Format: "NNN IfaceClass <active/idle> <label>"
844 if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
845 throw new IllegalStateException(errorMessage);
847 long timestampNanos = 0;
849 if (cooked.length >= 5) {
851 timestampNanos = Long.parseLong(cooked[4]);
852 if (cooked.length == 6) {
853 processUid = Integer.parseInt(cooked[5]);
855 } catch(NumberFormatException ne) {}
857 timestampNanos = SystemClock.elapsedRealtimeNanos();
859 boolean isActive = cooked[2].equals("active");
860 notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
861 isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
862 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
863 timestampNanos, processUid, false);
866 case NetdResponseCode.InterfaceAddressChange:
868 * A network address change occurred
869 * Format: "NNN Address updated <addr> <iface> <flags> <scope>"
870 * "NNN Address removed <addr> <iface> <flags> <scope>"
872 if (cooked.length < 7 || !cooked[1].equals("Address")) {
873 throw new IllegalStateException(errorMessage);
876 String iface = cooked[4];
879 int flags = Integer.parseInt(cooked[5]);
880 int scope = Integer.parseInt(cooked[6]);
881 address = new LinkAddress(cooked[3], flags, scope);
882 } catch(NumberFormatException e) { // Non-numeric lifetime or scope.
883 throw new IllegalStateException(errorMessage, e);
884 } catch(IllegalArgumentException e) { // Malformed/invalid IP address.
885 throw new IllegalStateException(errorMessage, e);
888 if (cooked[2].equals("updated")) {
889 notifyAddressUpdated(iface, address);
891 notifyAddressRemoved(iface, address);
895 case NetdResponseCode.InterfaceDnsServerInfo:
897 * Information about available DNS servers has been received.
898 * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>"
900 long lifetime; // Actually a 32-bit unsigned integer.
902 if (cooked.length == 6 &&
903 cooked[1].equals("DnsInfo") &&
904 cooked[2].equals("servers")) {
906 lifetime = Long.parseLong(cooked[4]);
907 } catch (NumberFormatException e) {
908 throw new IllegalStateException(errorMessage);
910 String[] servers = cooked[5].split(",");
911 notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
915 case NetdResponseCode.RouteChange:
917 * A route has been updated or removed.
918 * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]"
920 if (!cooked[1].equals("Route") || cooked.length < 6) {
921 throw new IllegalStateException(errorMessage);
926 boolean valid = true;
927 for (int i = 4; (i + 1) < cooked.length && valid; i += 2) {
928 if (cooked[i].equals("dev")) {
932 valid = false; // Duplicate interface.
934 } else if (cooked[i].equals("via")) {
938 valid = false; // Duplicate gateway.
941 valid = false; // Unknown syntax.
946 // InetAddress.parseNumericAddress(null) inexplicably returns ::1.
947 InetAddress gateway = null;
948 if (via != null) gateway = InetAddress.parseNumericAddress(via);
949 RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
950 notifyRouteChange(cooked[2], route);
952 } catch (IllegalArgumentException e) {}
954 throw new IllegalStateException(errorMessage);
956 case NetdResponseCode.StrictCleartext:
957 final int uid = Integer.parseInt(cooked[1]);
958 final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]);
960 ActivityManagerNative.getDefault().notifyCleartextNetwork(uid, firstPacket);
961 } catch (RemoteException ignored) {
972 // INetworkManagementService members
975 public INetd getNetdService() throws RemoteException {
976 final CountDownLatch connectedSignal = mConnectedSignal;
977 if (connectedSignal != null) {
979 connectedSignal.await();
980 } catch (InterruptedException ignored) {}
987 public String[] listInterfaces() {
988 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
990 return NativeDaemonEvent.filterMessageList(
991 mConnector.executeForList("interface", "list"), InterfaceListResult);
992 } catch (NativeDaemonConnectorException e) {
993 throw e.rethrowAsParcelableException();
998 public InterfaceConfiguration getInterfaceConfig(String iface) {
999 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1001 final NativeDaemonEvent event;
1003 event = mConnector.execute("interface", "getcfg", iface);
1004 } catch (NativeDaemonConnectorException e) {
1005 throw e.rethrowAsParcelableException();
1008 event.checkCode(InterfaceGetCfgResult);
1010 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3
1011 final StringTokenizer st = new StringTokenizer(event.getMessage());
1013 InterfaceConfiguration cfg;
1015 cfg = new InterfaceConfiguration();
1016 cfg.setHardwareAddress(st.nextToken(" "));
1017 InetAddress addr = null;
1018 int prefixLength = 0;
1020 addr = NetworkUtils.numericToInetAddress(st.nextToken());
1021 } catch (IllegalArgumentException iae) {
1022 Slog.e(TAG, "Failed to parse ipaddr", iae);
1026 prefixLength = Integer.parseInt(st.nextToken());
1027 } catch (NumberFormatException nfe) {
1028 Slog.e(TAG, "Failed to parse prefixLength", nfe);
1031 cfg.setLinkAddress(new LinkAddress(addr, prefixLength));
1032 while (st.hasMoreTokens()) {
1033 cfg.setFlag(st.nextToken());
1035 } catch (NoSuchElementException nsee) {
1036 throw new IllegalStateException("Invalid response from daemon: " + event);
1042 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
1043 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1044 LinkAddress linkAddr = cfg.getLinkAddress();
1045 if (linkAddr == null || linkAddr.getAddress() == null) {
1046 throw new IllegalStateException("Null LinkAddress given");
1049 final Command cmd = new Command("interface", "setcfg", iface,
1050 linkAddr.getAddress().getHostAddress(),
1051 linkAddr.getPrefixLength());
1052 for (String flag : cfg.getFlags()) {
1053 cmd.appendArg(flag);
1057 mConnector.execute(cmd);
1058 } catch (NativeDaemonConnectorException e) {
1059 throw e.rethrowAsParcelableException();
1064 public void setInterfaceDown(String iface) {
1065 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1066 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
1067 ifcg.setInterfaceDown();
1068 setInterfaceConfig(iface, ifcg);
1072 public void setInterfaceUp(String iface) {
1073 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1074 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
1075 ifcg.setInterfaceUp();
1076 setInterfaceConfig(iface, ifcg);
1080 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
1081 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1084 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable");
1085 } catch (NativeDaemonConnectorException e) {
1086 throw e.rethrowAsParcelableException();
1090 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
1091 IPv6 addresses on interface down, but we need to do full clean up here */
1093 public void clearInterfaceAddresses(String iface) {
1094 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1096 mConnector.execute("interface", "clearaddrs", iface);
1097 } catch (NativeDaemonConnectorException e) {
1098 throw e.rethrowAsParcelableException();
1103 public void enableIpv6(String iface) {
1104 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1106 mConnector.execute("interface", "ipv6", iface, "enable");
1107 } catch (NativeDaemonConnectorException e) {
1108 throw e.rethrowAsParcelableException();
1113 public void disableIpv6(String iface) {
1114 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1116 mConnector.execute("interface", "ipv6", iface, "disable");
1117 } catch (NativeDaemonConnectorException e) {
1118 throw e.rethrowAsParcelableException();
1123 public void setInterfaceIpv6NdOffload(String iface, boolean enable) {
1124 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1127 "interface", "ipv6ndoffload", iface, (enable ? "enable" : "disable"));
1128 } catch (NativeDaemonConnectorException e) {
1129 throw e.rethrowAsParcelableException();
1134 public void addRoute(int netId, RouteInfo route) {
1135 modifyRoute("add", "" + netId, route);
1139 public void removeRoute(int netId, RouteInfo route) {
1140 modifyRoute("remove", "" + netId, route);
1143 private void modifyRoute(String action, String netId, RouteInfo route) {
1144 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1146 final Command cmd = new Command("network", "route", action, netId);
1148 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
1149 cmd.appendArg(route.getInterface());
1150 cmd.appendArg(route.getDestination().toString());
1152 switch (route.getType()) {
1153 case RouteInfo.RTN_UNICAST:
1154 if (route.hasGateway()) {
1155 cmd.appendArg(route.getGateway().getHostAddress());
1158 case RouteInfo.RTN_UNREACHABLE:
1159 cmd.appendArg("unreachable");
1161 case RouteInfo.RTN_THROW:
1162 cmd.appendArg("throw");
1167 mConnector.execute(cmd);
1168 } catch (NativeDaemonConnectorException e) {
1169 throw e.rethrowAsParcelableException();
1173 private ArrayList<String> readRouteList(String filename) {
1174 FileInputStream fstream = null;
1175 ArrayList<String> list = new ArrayList<String>();
1178 fstream = new FileInputStream(filename);
1179 DataInputStream in = new DataInputStream(fstream);
1180 BufferedReader br = new BufferedReader(new InputStreamReader(in));
1183 // throw away the title line
1185 while (((s = br.readLine()) != null) && (s.length() != 0)) {
1188 } catch (IOException ex) {
1189 // return current list, possibly empty
1191 if (fstream != null) {
1194 } catch (IOException ex) {}
1202 public void setMtu(String iface, int mtu) {
1203 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1205 final NativeDaemonEvent event;
1207 event = mConnector.execute("interface", "setmtu", iface, mtu);
1208 } catch (NativeDaemonConnectorException e) {
1209 throw e.rethrowAsParcelableException();
1214 public void shutdown() {
1215 // TODO: remove from aidl if nobody calls externally
1216 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
1218 Slog.i(TAG, "Shutting down");
1222 public boolean getIpForwardingEnabled() throws IllegalStateException{
1223 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1225 final NativeDaemonEvent event;
1227 event = mConnector.execute("ipfwd", "status");
1228 } catch (NativeDaemonConnectorException e) {
1229 throw e.rethrowAsParcelableException();
1232 // 211 Forwarding enabled
1233 event.checkCode(IpFwdStatusResult);
1234 return event.getMessage().endsWith("enabled");
1238 public void setIpForwardingEnabled(boolean enable) {
1239 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1241 mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering");
1242 } catch (NativeDaemonConnectorException e) {
1243 throw e.rethrowAsParcelableException();
1248 public void startTethering(String[] dhcpRange) {
1249 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1250 // cmd is "tether start first_start first_stop second_start second_stop ..."
1251 // an odd number of addrs will fail
1253 final Command cmd = new Command("tether", "start");
1254 for (String d : dhcpRange) {
1259 mConnector.execute(cmd);
1260 } catch (NativeDaemonConnectorException e) {
1261 throw e.rethrowAsParcelableException();
1266 public void stopTethering() {
1267 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1269 mConnector.execute("tether", "stop");
1270 } catch (NativeDaemonConnectorException e) {
1271 throw e.rethrowAsParcelableException();
1276 public boolean isTetheringStarted() {
1277 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1279 final NativeDaemonEvent event;
1281 event = mConnector.execute("tether", "status");
1282 } catch (NativeDaemonConnectorException e) {
1283 throw e.rethrowAsParcelableException();
1286 // 210 Tethering services started
1287 event.checkCode(TetherStatusResult);
1288 return event.getMessage().endsWith("started");
1292 public void tetherInterface(String iface) {
1293 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1295 mConnector.execute("tether", "interface", "add", iface);
1296 } catch (NativeDaemonConnectorException e) {
1297 throw e.rethrowAsParcelableException();
1299 List<RouteInfo> routes = new ArrayList<RouteInfo>();
1300 // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
1301 // suitable to use as a route destination.
1302 routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
1303 addInterfaceToLocalNetwork(iface, routes);
1307 public void untetherInterface(String iface) {
1308 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1310 mConnector.execute("tether", "interface", "remove", iface);
1311 } catch (NativeDaemonConnectorException e) {
1312 throw e.rethrowAsParcelableException();
1314 removeInterfaceFromLocalNetwork(iface);
1319 public String[] listTetheredInterfaces() {
1320 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1322 return NativeDaemonEvent.filterMessageList(
1323 mConnector.executeForList("tether", "interface", "list"),
1324 TetherInterfaceListResult);
1325 } catch (NativeDaemonConnectorException e) {
1326 throw e.rethrowAsParcelableException();
1331 public void setDnsForwarders(Network network, String[] dns) {
1332 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1334 int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
1335 final Command cmd = new Command("tether", "dns", "set", netId);
1337 for (String s : dns) {
1338 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
1342 mConnector.execute(cmd);
1343 } catch (NativeDaemonConnectorException e) {
1344 throw e.rethrowAsParcelableException();
1349 public String[] getDnsForwarders() {
1350 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1352 return NativeDaemonEvent.filterMessageList(
1353 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult);
1354 } catch (NativeDaemonConnectorException e) {
1355 throw e.rethrowAsParcelableException();
1359 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
1360 ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size());
1361 for (InterfaceAddress ia : addresses) {
1362 if (!ia.getAddress().isLinkLocalAddress())
1368 private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
1369 final Command cmd = new Command("ipfwd", add ? "add" : "remove", fromIface, toIface);
1371 mConnector.execute(cmd);
1372 } catch (NativeDaemonConnectorException e) {
1373 throw e.rethrowAsParcelableException();
1378 public void startInterfaceForwarding(String fromIface, String toIface) {
1379 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1380 modifyInterfaceForward(true, fromIface, toIface);
1384 public void stopInterfaceForwarding(String fromIface, String toIface) {
1385 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1386 modifyInterfaceForward(false, fromIface, toIface);
1389 private void modifyNat(String action, String internalInterface, String externalInterface)
1390 throws SocketException {
1391 final Command cmd = new Command("nat", action, internalInterface, externalInterface);
1393 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName(
1395 if (internalNetworkInterface == null) {
1398 // Don't touch link-local routes, as link-local addresses aren't routable,
1399 // kernel creates link-local routes on all interfaces automatically
1400 List<InterfaceAddress> interfaceAddresses = excludeLinkLocal(
1401 internalNetworkInterface.getInterfaceAddresses());
1402 cmd.appendArg(interfaceAddresses.size());
1403 for (InterfaceAddress ia : interfaceAddresses) {
1404 InetAddress addr = NetworkUtils.getNetworkPart(
1405 ia.getAddress(), ia.getNetworkPrefixLength());
1406 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength());
1411 mConnector.execute(cmd);
1412 } catch (NativeDaemonConnectorException e) {
1413 throw e.rethrowAsParcelableException();
1418 public void enableNat(String internalInterface, String externalInterface) {
1419 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1421 modifyNat("enable", internalInterface, externalInterface);
1422 } catch (SocketException e) {
1423 throw new IllegalStateException(e);
1428 public void disableNat(String internalInterface, String externalInterface) {
1429 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1431 modifyNat("disable", internalInterface, externalInterface);
1432 } catch (SocketException e) {
1433 throw new IllegalStateException(e);
1438 public String[] listTtys() {
1439 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1441 return NativeDaemonEvent.filterMessageList(
1442 mConnector.executeForList("list_ttys"), TtyListResult);
1443 } catch (NativeDaemonConnectorException e) {
1444 throw e.rethrowAsParcelableException();
1449 public void attachPppd(
1450 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
1451 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1453 mConnector.execute("pppd", "attach", tty,
1454 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
1455 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
1456 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
1457 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress());
1458 } catch (NativeDaemonConnectorException e) {
1459 throw e.rethrowAsParcelableException();
1464 public void detachPppd(String tty) {
1465 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1467 mConnector.execute("pppd", "detach", tty);
1468 } catch (NativeDaemonConnectorException e) {
1469 throw e.rethrowAsParcelableException();
1474 * Private method used to call execute for a command given the provided arguments.
1476 * This function checks the returned NativeDaemonEvent for the provided expected response code
1477 * and message. If either of these is not correct, an error is logged.
1479 * @param String command The command to execute.
1480 * @param Object[] args If needed, arguments for the command to execute.
1481 * @param int expectedResponseCode The code expected to be returned in the corresponding event.
1482 * @param String expectedResponseMessage The message expected in the returned event.
1483 * @param String logMsg The message to log as an error (TAG will be applied).
1485 private void executeOrLogWithMessage(String command, Object[] args,
1486 int expectedResponseCode, String expectedResponseMessage, String logMsg)
1487 throws NativeDaemonConnectorException {
1488 NativeDaemonEvent event = mConnector.execute(command, args);
1489 if (event.getCode() != expectedResponseCode
1490 || !event.getMessage().equals(expectedResponseMessage)) {
1491 Log.e(TAG, logMsg + ": event = " + event);
1496 public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface) {
1497 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1499 String logMsg = "startAccessPoint Error setting up softap";
1501 if (wifiConfig == null) {
1502 args = new Object[] {"set", wlanIface};
1504 args = new Object[] {"set", wlanIface, wifiConfig.SSID,
1505 "broadcast", Integer.toString(wifiConfig.apChannel),
1506 getSecurityType(wifiConfig), new SensitiveArg(wifiConfig.preSharedKey)};
1508 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult,
1509 SOFT_AP_COMMAND_SUCCESS, logMsg);
1511 logMsg = "startAccessPoint Error starting softap";
1512 args = new Object[] {"startap"};
1513 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult,
1514 SOFT_AP_COMMAND_SUCCESS, logMsg);
1515 } catch (NativeDaemonConnectorException e) {
1516 throw e.rethrowAsParcelableException();
1520 private static String getSecurityType(WifiConfiguration wifiConfig) {
1521 switch (wifiConfig.getAuthType()) {
1522 case KeyMgmt.WPA_PSK:
1524 case KeyMgmt.WPA2_PSK:
1531 /* @param mode can be "AP", "STA" or "P2P" */
1533 public void wifiFirmwareReload(String wlanIface, String mode) {
1534 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1535 Object[] args = {"fwreload", wlanIface, mode};
1536 String logMsg = "wifiFirmwareReload Error reloading "
1537 + wlanIface + " fw in " + mode + " mode";
1539 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult,
1540 SOFT_AP_COMMAND_SUCCESS, logMsg);
1541 } catch (NativeDaemonConnectorException e) {
1542 throw e.rethrowAsParcelableException();
1545 // Ensure that before we return from this command, any asynchronous
1546 // notifications generated before the command completed have been
1547 // processed by all NetworkManagementEventObservers.
1548 mConnector.waitForCallbacks();
1552 public void stopAccessPoint(String wlanIface) {
1553 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1554 Object[] args = {"stopap"};
1555 String logMsg = "stopAccessPoint Error stopping softap";
1558 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult,
1559 SOFT_AP_COMMAND_SUCCESS, logMsg);
1560 wifiFirmwareReload(wlanIface, "STA");
1561 } catch (NativeDaemonConnectorException e) {
1562 throw e.rethrowAsParcelableException();
1567 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) {
1568 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1570 String logMsg = "startAccessPoint Error setting up softap";
1572 if (wifiConfig == null) {
1573 args = new Object[] {"set", wlanIface};
1575 // TODO: understand why this is set to "6" instead of
1576 // Integer.toString(wifiConfig.apChannel) as in startAccessPoint
1577 // TODO: should startAccessPoint call this instead of repeating code?
1578 args = new Object[] {"set", wlanIface, wifiConfig.SSID,
1580 getSecurityType(wifiConfig), new SensitiveArg(wifiConfig.preSharedKey)};
1582 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult,
1583 SOFT_AP_COMMAND_SUCCESS, logMsg);
1584 } catch (NativeDaemonConnectorException e) {
1585 throw e.rethrowAsParcelableException();
1590 public void addIdleTimer(String iface, int timeout, final int type) {
1591 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1593 if (DBG) Slog.d(TAG, "Adding idletimer");
1595 synchronized (mIdleTimerLock) {
1596 IdleTimerParams params = mActiveIdleTimers.get(iface);
1597 if (params != null) {
1598 // the interface already has idletimer, update network count
1599 params.networkCount++;
1604 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout),
1605 Integer.toString(type));
1606 } catch (NativeDaemonConnectorException e) {
1607 throw e.rethrowAsParcelableException();
1609 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
1611 // Networks start up.
1612 if (ConnectivityManager.isNetworkTypeMobile(type)) {
1613 mNetworkActive = false;
1615 mDaemonHandler.post(new Runnable() {
1616 @Override public void run() {
1617 notifyInterfaceClassActivity(type,
1618 DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
1619 SystemClock.elapsedRealtimeNanos(), -1, false);
1626 public void removeIdleTimer(String iface) {
1627 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1629 if (DBG) Slog.d(TAG, "Removing idletimer");
1631 synchronized (mIdleTimerLock) {
1632 final IdleTimerParams params = mActiveIdleTimers.get(iface);
1633 if (params == null || --(params.networkCount) > 0) {
1638 mConnector.execute("idletimer", "remove", iface,
1639 Integer.toString(params.timeout), Integer.toString(params.type));
1640 } catch (NativeDaemonConnectorException e) {
1641 throw e.rethrowAsParcelableException();
1643 mActiveIdleTimers.remove(iface);
1644 mDaemonHandler.post(new Runnable() {
1645 @Override public void run() {
1646 notifyInterfaceClassActivity(params.type,
1647 DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
1648 SystemClock.elapsedRealtimeNanos(), -1, false);
1655 public NetworkStats getNetworkStatsSummaryDev() {
1656 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1658 return mStatsFactory.readNetworkStatsSummaryDev();
1659 } catch (IOException e) {
1660 throw new IllegalStateException(e);
1665 public NetworkStats getNetworkStatsSummaryXt() {
1666 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1668 return mStatsFactory.readNetworkStatsSummaryXt();
1669 } catch (IOException e) {
1670 throw new IllegalStateException(e);
1675 public NetworkStats getNetworkStatsDetail() {
1676 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1678 return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
1679 } catch (IOException e) {
1680 throw new IllegalStateException(e);
1685 public void setInterfaceQuota(String iface, long quotaBytes) {
1686 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1688 // silently discard when control disabled
1689 // TODO: eventually migrate to be always enabled
1690 if (!mBandwidthControlEnabled) return;
1692 synchronized (mQuotaLock) {
1693 if (mActiveQuotas.containsKey(iface)) {
1694 throw new IllegalStateException("iface " + iface + " already has quota");
1698 // TODO: support quota shared across interfaces
1699 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes);
1700 mActiveQuotas.put(iface, quotaBytes);
1701 } catch (NativeDaemonConnectorException e) {
1702 throw e.rethrowAsParcelableException();
1708 public void removeInterfaceQuota(String iface) {
1709 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1711 // silently discard when control disabled
1712 // TODO: eventually migrate to be always enabled
1713 if (!mBandwidthControlEnabled) return;
1715 synchronized (mQuotaLock) {
1716 if (!mActiveQuotas.containsKey(iface)) {
1717 // TODO: eventually consider throwing
1721 mActiveQuotas.remove(iface);
1722 mActiveAlerts.remove(iface);
1725 // TODO: support quota shared across interfaces
1726 mConnector.execute("bandwidth", "removeiquota", iface);
1727 } catch (NativeDaemonConnectorException e) {
1728 throw e.rethrowAsParcelableException();
1734 public void setInterfaceAlert(String iface, long alertBytes) {
1735 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1737 // silently discard when control disabled
1738 // TODO: eventually migrate to be always enabled
1739 if (!mBandwidthControlEnabled) return;
1741 // quick sanity check
1742 if (!mActiveQuotas.containsKey(iface)) {
1743 throw new IllegalStateException("setting alert requires existing quota on iface");
1746 synchronized (mQuotaLock) {
1747 if (mActiveAlerts.containsKey(iface)) {
1748 throw new IllegalStateException("iface " + iface + " already has alert");
1752 // TODO: support alert shared across interfaces
1753 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes);
1754 mActiveAlerts.put(iface, alertBytes);
1755 } catch (NativeDaemonConnectorException e) {
1756 throw e.rethrowAsParcelableException();
1762 public void removeInterfaceAlert(String iface) {
1763 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1765 // silently discard when control disabled
1766 // TODO: eventually migrate to be always enabled
1767 if (!mBandwidthControlEnabled) return;
1769 synchronized (mQuotaLock) {
1770 if (!mActiveAlerts.containsKey(iface)) {
1771 // TODO: eventually consider throwing
1776 // TODO: support alert shared across interfaces
1777 mConnector.execute("bandwidth", "removeinterfacealert", iface);
1778 mActiveAlerts.remove(iface);
1779 } catch (NativeDaemonConnectorException e) {
1780 throw e.rethrowAsParcelableException();
1786 public void setGlobalAlert(long alertBytes) {
1787 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1789 // silently discard when control disabled
1790 // TODO: eventually migrate to be always enabled
1791 if (!mBandwidthControlEnabled) return;
1794 mConnector.execute("bandwidth", "setglobalalert", alertBytes);
1795 } catch (NativeDaemonConnectorException e) {
1796 throw e.rethrowAsParcelableException();
1800 private void setUidOnMeteredNetworkList(SparseBooleanArray quotaList, int uid,
1801 boolean blacklist, boolean enable) {
1802 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1804 // silently discard when control disabled
1805 // TODO: eventually migrate to be always enabled
1806 if (!mBandwidthControlEnabled) return;
1808 final String chain = blacklist ? "naughtyapps" : "niceapps";
1809 final String suffix = enable ? "add" : "remove";
1811 synchronized (mQuotaLock) {
1812 final boolean oldEnable = quotaList.get(uid, false);
1813 if (oldEnable == enable) {
1814 // TODO: eventually consider throwing
1819 mConnector.execute("bandwidth", suffix + chain, uid);
1821 quotaList.put(uid, true);
1823 quotaList.delete(uid);
1825 } catch (NativeDaemonConnectorException e) {
1826 throw e.rethrowAsParcelableException();
1832 public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
1833 setUidOnMeteredNetworkList(mUidRejectOnMetered, uid, true, enable);
1837 public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
1838 setUidOnMeteredNetworkList(mUidAllowOnMetered, uid, false, enable);
1842 public boolean setDataSaverModeEnabled(boolean enable) {
1843 if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
1844 synchronized (mQuotaLock) {
1845 if (mDataSaverMode == enable) {
1846 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
1850 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
1852 mDataSaverMode = enable;
1854 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
1857 } catch (RemoteException e) {
1858 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
1865 public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
1866 throws ServiceSpecificException {
1868 mNetdService.networkRejectNonSecureVpn(add, uidRanges);
1869 } catch (ServiceSpecificException e) {
1870 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1871 + ": netd command failed", e);
1873 } catch (RemoteException e) {
1874 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1875 + ": netd command failed", e);
1876 throw e.rethrowAsRuntimeException();
1881 public void setUidCleartextNetworkPolicy(int uid, int policy) {
1882 if (Binder.getCallingUid() != uid) {
1883 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1886 synchronized (mQuotaLock) {
1887 final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1888 if (oldPolicy == policy) {
1892 if (!mStrictEnabled) {
1893 // Module isn't enabled yet; stash the requested policy away to
1894 // apply later once the daemon is connected.
1895 mUidCleartextPolicy.put(uid, policy);
1899 final String policyString;
1901 case StrictMode.NETWORK_POLICY_ACCEPT:
1902 policyString = "accept";
1904 case StrictMode.NETWORK_POLICY_LOG:
1905 policyString = "log";
1907 case StrictMode.NETWORK_POLICY_REJECT:
1908 policyString = "reject";
1911 throw new IllegalArgumentException("Unknown policy " + policy);
1915 mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString);
1916 mUidCleartextPolicy.put(uid, policy);
1917 } catch (NativeDaemonConnectorException e) {
1918 throw e.rethrowAsParcelableException();
1924 public boolean isBandwidthControlEnabled() {
1925 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1926 return mBandwidthControlEnabled;
1930 public NetworkStats getNetworkStatsUidDetail(int uid) {
1931 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1933 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null);
1934 } catch (IOException e) {
1935 throw new IllegalStateException(e);
1940 public NetworkStats getNetworkStatsTethering() {
1941 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1943 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1945 final NativeDaemonEvent[] events = mConnector.executeForList(
1946 "bandwidth", "gettetherstats");
1947 for (NativeDaemonEvent event : events) {
1948 if (event.getCode() != TetheringStatsListResult) continue;
1950 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
1951 final StringTokenizer tok = new StringTokenizer(event.getMessage());
1953 final String ifaceIn = tok.nextToken();
1954 final String ifaceOut = tok.nextToken();
1956 final NetworkStats.Entry entry = new NetworkStats.Entry();
1957 entry.iface = ifaceOut;
1958 entry.uid = UID_TETHERING;
1959 entry.set = SET_DEFAULT;
1960 entry.tag = TAG_NONE;
1961 entry.rxBytes = Long.parseLong(tok.nextToken());
1962 entry.rxPackets = Long.parseLong(tok.nextToken());
1963 entry.txBytes = Long.parseLong(tok.nextToken());
1964 entry.txPackets = Long.parseLong(tok.nextToken());
1965 stats.combineValues(entry);
1966 } catch (NoSuchElementException e) {
1967 throw new IllegalStateException("problem parsing tethering stats: " + event);
1968 } catch (NumberFormatException e) {
1969 throw new IllegalStateException("problem parsing tethering stats: " + event);
1972 } catch (NativeDaemonConnectorException e) {
1973 throw e.rethrowAsParcelableException();
1979 public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) {
1980 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1982 ContentResolver resolver = mContext.getContentResolver();
1984 int sampleValidity = Settings.Global.getInt(resolver,
1985 Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
1986 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
1987 if (sampleValidity < 0 || sampleValidity > 65535) {
1988 Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" +
1989 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
1990 sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
1993 int successThreshold = Settings.Global.getInt(resolver,
1994 Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
1995 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
1996 if (successThreshold < 0 || successThreshold > 100) {
1997 Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" +
1998 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
1999 successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
2002 int minSamples = Settings.Global.getInt(resolver,
2003 Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
2004 int maxSamples = Settings.Global.getInt(resolver,
2005 Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
2006 if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) {
2007 Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples +
2008 "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
2009 DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
2010 minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
2011 maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
2014 final String[] domainStrs = domains == null ? new String[0] : domains.split(" ");
2015 final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples };
2017 mNetdService.setResolverConfiguration(netId, servers, domainStrs, params);
2018 } catch (RemoteException e) {
2019 throw new RuntimeException(e);
2024 public void setDnsServersForNetwork(int netId, String[] servers, String domains) {
2025 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2028 if (servers.length > 0) {
2029 cmd = new Command("resolver", "setnetdns", netId,
2030 (domains == null ? "" : domains));
2031 for (String s : servers) {
2032 InetAddress a = NetworkUtils.numericToInetAddress(s);
2033 if (a.isAnyLocalAddress() == false) {
2034 cmd.appendArg(a.getHostAddress());
2038 cmd = new Command("resolver", "clearnetdns", netId);
2042 mConnector.execute(cmd);
2043 } catch (NativeDaemonConnectorException e) {
2044 throw e.rethrowAsParcelableException();
2049 public void addVpnUidRanges(int netId, UidRange[] ranges) {
2050 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2051 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2056 // Avoid overly long commands by limiting number of UID ranges per command.
2057 for (int i = 0; i < ranges.length; i++) {
2058 argv[argc++] = ranges[i].toString();
2059 if (i == (ranges.length - 1) || argc == argv.length) {
2061 mConnector.execute("network", Arrays.copyOf(argv, argc));
2062 } catch (NativeDaemonConnectorException e) {
2063 throw e.rethrowAsParcelableException();
2071 public void removeVpnUidRanges(int netId, UidRange[] ranges) {
2072 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2073 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2078 // Avoid overly long commands by limiting number of UID ranges per command.
2079 for (int i = 0; i < ranges.length; i++) {
2080 argv[argc++] = ranges[i].toString();
2081 if (i == (ranges.length - 1) || argc == argv.length) {
2083 mConnector.execute("network", Arrays.copyOf(argv, argc));
2084 } catch (NativeDaemonConnectorException e) {
2085 throw e.rethrowAsParcelableException();
2093 public void setFirewallEnabled(boolean enabled) {
2096 mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist");
2097 mFirewallEnabled = enabled;
2098 } catch (NativeDaemonConnectorException e) {
2099 throw e.rethrowAsParcelableException();
2104 public boolean isFirewallEnabled() {
2106 return mFirewallEnabled;
2110 public void setFirewallInterfaceRule(String iface, boolean allow) {
2112 Preconditions.checkState(mFirewallEnabled);
2113 final String rule = allow ? "allow" : "deny";
2115 mConnector.execute("firewall", "set_interface_rule", iface, rule);
2116 } catch (NativeDaemonConnectorException e) {
2117 throw e.rethrowAsParcelableException();
2122 public void setFirewallEgressSourceRule(String addr, boolean allow) {
2124 Preconditions.checkState(mFirewallEnabled);
2125 final String rule = allow ? "allow" : "deny";
2127 mConnector.execute("firewall", "set_egress_source_rule", addr, rule);
2128 } catch (NativeDaemonConnectorException e) {
2129 throw e.rethrowAsParcelableException();
2134 public void setFirewallEgressDestRule(String addr, int port, boolean allow) {
2136 Preconditions.checkState(mFirewallEnabled);
2137 final String rule = allow ? "allow" : "deny";
2139 mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule);
2140 } catch (NativeDaemonConnectorException e) {
2141 throw e.rethrowAsParcelableException();
2145 private void closeSocketsForFirewallChainLocked(int chain, String chainName) {
2146 // UID ranges to close sockets on.
2148 // UID ranges whose sockets we won't touch.
2151 final SparseIntArray rules = getUidFirewallRules(chain);
2154 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
2155 // Close all sockets on all non-system UIDs...
2156 ranges = new UidRange[] {
2157 // TODO: is there a better way of finding all existing users? If so, we could
2158 // specify their ranges here.
2159 new UidRange(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
2161 // ... except for the UIDs that have allow rules.
2162 exemptUids = new int[rules.size()];
2163 for (int i = 0; i < exemptUids.length; i++) {
2164 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
2165 exemptUids[numUids] = rules.keyAt(i);
2169 // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
2170 // But the code does not guarantee this in any way, and at least in one case - if we add
2171 // a UID rule to the firewall, and then disable the firewall - the chains can contain
2172 // the wrong type of rule. In this case, don't close connections that we shouldn't.
2174 // TODO: tighten up this code by ensuring we never set the wrong type of rule, and
2175 // fix setFirewallEnabled to grab mQuotaLock and clear rules.
2176 if (numUids != exemptUids.length) {
2177 exemptUids = Arrays.copyOf(exemptUids, numUids);
2180 // Close sockets for every UID that has a deny rule...
2181 ranges = new UidRange[rules.size()];
2182 for (int i = 0; i < ranges.length; i++) {
2183 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_DENY) {
2184 int uid = rules.keyAt(i);
2185 ranges[numUids] = new UidRange(uid, uid);
2189 // As above; usually numUids == ranges.length, but not always.
2190 if (numUids != ranges.length) {
2191 ranges = Arrays.copyOf(ranges, numUids);
2193 // ... with no exceptions.
2194 exemptUids = new int[0];
2198 mNetdService.socketDestroy(ranges, exemptUids);
2199 } catch(RemoteException | ServiceSpecificException e) {
2200 Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e);
2205 public void setFirewallChainEnabled(int chain, boolean enable) {
2207 synchronized (mQuotaLock) {
2208 if (mFirewallChainStates.get(chain) == enable) {
2209 // All is the same, nothing to do. This relies on the fact that netd has child
2210 // chains default detached.
2213 mFirewallChainStates.put(chain, enable);
2215 final String operation = enable ? "enable_chain" : "disable_chain";
2216 final String chainName;
2218 case FIREWALL_CHAIN_STANDBY:
2219 chainName = FIREWALL_CHAIN_NAME_STANDBY;
2221 case FIREWALL_CHAIN_DOZABLE:
2222 chainName = FIREWALL_CHAIN_NAME_DOZABLE;
2224 case FIREWALL_CHAIN_POWERSAVE:
2225 chainName = FIREWALL_CHAIN_NAME_POWERSAVE;
2228 throw new IllegalArgumentException("Bad child chain: " + chain);
2232 mConnector.execute("firewall", operation, chainName);
2233 } catch (NativeDaemonConnectorException e) {
2234 throw e.rethrowAsParcelableException();
2237 // Close any sockets that were opened by the affected UIDs. This has to be done after
2238 // disabling network connectivity, in case they react to the socket close by reopening
2239 // the connection and race with the iptables commands that enable the firewall. All
2240 // whitelist and blacklist chains allow RSTs through.
2242 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
2243 closeSocketsForFirewallChainLocked(chain, chainName);
2248 private int getFirewallType(int chain) {
2250 case FIREWALL_CHAIN_STANDBY:
2251 return FIREWALL_TYPE_BLACKLIST;
2252 case FIREWALL_CHAIN_DOZABLE:
2253 return FIREWALL_TYPE_WHITELIST;
2254 case FIREWALL_CHAIN_POWERSAVE:
2255 return FIREWALL_TYPE_WHITELIST;
2257 return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
2262 public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
2264 synchronized (mQuotaLock) {
2265 SparseIntArray uidFirewallRules = getUidFirewallRules(chain);
2266 SparseIntArray newRules = new SparseIntArray();
2267 // apply new set of rules
2268 for (int index = uids.length - 1; index >= 0; --index) {
2269 int uid = uids[index];
2270 int rule = rules[index];
2271 updateFirewallUidRuleLocked(chain, uid, rule);
2272 newRules.put(uid, rule);
2274 // collect the rules to remove.
2275 SparseIntArray rulesToRemove = new SparseIntArray();
2276 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
2277 int uid = uidFirewallRules.keyAt(index);
2278 if (newRules.indexOfKey(uid) < 0) {
2279 rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
2282 // remove dead rules
2283 for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
2284 int uid = rulesToRemove.keyAt(index);
2285 updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
2289 case FIREWALL_CHAIN_DOZABLE:
2290 mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
2292 case FIREWALL_CHAIN_STANDBY:
2293 mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
2295 case FIREWALL_CHAIN_POWERSAVE:
2296 mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
2298 case FIREWALL_CHAIN_NONE:
2300 Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
2302 } catch (RemoteException e) {
2303 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
2309 public void setFirewallUidRule(int chain, int uid, int rule) {
2311 synchronized (mQuotaLock) {
2312 setFirewallUidRuleLocked(chain, uid, rule);
2316 private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
2317 if (updateFirewallUidRuleLocked(chain, uid, rule)) {
2319 mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
2320 getFirewallRuleName(chain, rule));
2321 } catch (NativeDaemonConnectorException e) {
2322 throw e.rethrowAsParcelableException();
2327 // TODO: now that netd supports batching, NMS should not keep these data structures anymore...
2328 private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) {
2329 SparseIntArray uidFirewallRules = getUidFirewallRules(chain);
2331 final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
2333 Slog.d(TAG, "oldRule = " + oldUidFirewallRule
2334 + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain);
2336 if (oldUidFirewallRule == rule) {
2337 if (DBG) Slog.d(TAG, "!!!!! Skipping change");
2338 // TODO: eventually consider throwing
2342 String ruleName = getFirewallRuleName(chain, rule);
2343 String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
2345 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
2346 uidFirewallRules.delete(uid);
2348 uidFirewallRules.put(uid, rule);
2350 return !ruleName.equals(oldRuleName);
2353 private @NonNull String getFirewallRuleName(int chain, int rule) {
2355 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
2356 if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
2361 } else { // Blacklist mode
2362 if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
2371 private @NonNull SparseIntArray getUidFirewallRules(int chain) {
2373 case FIREWALL_CHAIN_STANDBY:
2374 return mUidFirewallStandbyRules;
2375 case FIREWALL_CHAIN_DOZABLE:
2376 return mUidFirewallDozableRules;
2377 case FIREWALL_CHAIN_POWERSAVE:
2378 return mUidFirewallPowerSaveRules;
2379 case FIREWALL_CHAIN_NONE:
2380 return mUidFirewallRules;
2382 throw new IllegalArgumentException("Unknown chain:" + chain);
2386 public @NonNull String getFirewallChainName(int chain) {
2388 case FIREWALL_CHAIN_STANDBY:
2389 return FIREWALL_CHAIN_NAME_STANDBY;
2390 case FIREWALL_CHAIN_DOZABLE:
2391 return FIREWALL_CHAIN_NAME_DOZABLE;
2392 case FIREWALL_CHAIN_POWERSAVE:
2393 return FIREWALL_CHAIN_NAME_POWERSAVE;
2394 case FIREWALL_CHAIN_NONE:
2395 return FIREWALL_CHAIN_NAME_NONE;
2397 throw new IllegalArgumentException("Unknown chain:" + chain);
2401 private static void enforceSystemUid() {
2402 final int uid = Binder.getCallingUid();
2403 if (uid != Process.SYSTEM_UID) {
2404 throw new SecurityException("Only available to AID_SYSTEM");
2409 public void startClatd(String interfaceName) throws IllegalStateException {
2410 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2413 mConnector.execute("clatd", "start", interfaceName);
2414 } catch (NativeDaemonConnectorException e) {
2415 throw e.rethrowAsParcelableException();
2420 public void stopClatd(String interfaceName) throws IllegalStateException {
2421 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2424 mConnector.execute("clatd", "stop", interfaceName);
2425 } catch (NativeDaemonConnectorException e) {
2426 throw e.rethrowAsParcelableException();
2431 public boolean isClatdStarted(String interfaceName) {
2432 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2434 final NativeDaemonEvent event;
2436 event = mConnector.execute("clatd", "status", interfaceName);
2437 } catch (NativeDaemonConnectorException e) {
2438 throw e.rethrowAsParcelableException();
2441 event.checkCode(ClatdStatusResult);
2442 return event.getMessage().endsWith("started");
2446 public void registerNetworkActivityListener(INetworkActivityListener listener) {
2447 mNetworkActivityListeners.register(listener);
2451 public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
2452 mNetworkActivityListeners.unregister(listener);
2456 public boolean isNetworkActive() {
2457 synchronized (mNetworkActivityListeners) {
2458 return mNetworkActive || mActiveIdleTimers.isEmpty();
2462 private void reportNetworkActive() {
2463 final int length = mNetworkActivityListeners.beginBroadcast();
2465 for (int i = 0; i < length; i++) {
2467 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
2468 } catch (RemoteException | RuntimeException e) {
2472 mNetworkActivityListeners.finishBroadcast();
2476 /** {@inheritDoc} */
2478 public void monitor() {
2479 if (mConnector != null) {
2480 mConnector.monitor();
2485 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2486 mContext.enforceCallingOrSelfPermission(DUMP, TAG);
2488 pw.println("NetworkManagementService NativeDaemonConnector Log:");
2489 mConnector.dump(fd, pw, args);
2492 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
2493 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
2494 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
2495 pw.print("mNetworkActive="); pw.println(mNetworkActive);
2497 synchronized (mQuotaLock) {
2498 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
2499 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
2500 pw.print("Data saver mode: "); pw.println(mDataSaverMode);
2501 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
2502 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
2505 synchronized (mUidFirewallRules) {
2506 dumpUidFirewallRule(pw, "", mUidFirewallRules);
2509 pw.print("UID firewall standby chain enabled: "); pw.println(
2510 mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY));
2511 synchronized (mUidFirewallStandbyRules) {
2512 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
2515 pw.print("UID firewall dozable chain enabled: "); pw.println(
2516 mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE));
2517 synchronized (mUidFirewallDozableRules) {
2518 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
2521 pw.println("UID firewall powersave chain enabled: " +
2522 mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE));
2523 synchronized (mUidFirewallPowerSaveRules) {
2524 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
2527 synchronized (mIdleTimerLock) {
2528 pw.println("Idle timers:");
2529 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
2530 pw.print(" "); pw.print(ent.getKey()); pw.println(":");
2531 IdleTimerParams params = ent.getValue();
2532 pw.print(" timeout="); pw.print(params.timeout);
2533 pw.print(" type="); pw.print(params.type);
2534 pw.print(" networkCount="); pw.println(params.networkCount);
2538 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
2539 pw.print("Netd service status: " );
2540 if (mNetdService == null) {
2541 pw.println("disconnected");
2544 final boolean alive = mNetdService.isAlive();
2545 pw.println(alive ? "alive": "dead");
2546 } catch (RemoteException e) {
2547 pw.println("unreachable");
2552 private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
2553 pw.print("UID bandwith control ");
2555 pw.print(" rule: [");
2556 final int size = list.size();
2557 for (int i = 0; i < size; i++) {
2558 pw.print(list.keyAt(i));
2559 if (i < size - 1) pw.print(",");
2564 private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
2565 pw.print("UID firewall ");
2567 pw.print(" rule: [");
2568 final int size = rules.size();
2569 for (int i = 0; i < size; i++) {
2570 pw.print(rules.keyAt(i));
2572 pw.print(rules.valueAt(i));
2573 if (i < size - 1) pw.print(",");
2579 public void createPhysicalNetwork(int netId, String permission) {
2580 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2583 if (permission != null) {
2584 mConnector.execute("network", "create", netId, permission);
2586 mConnector.execute("network", "create", netId);
2588 } catch (NativeDaemonConnectorException e) {
2589 throw e.rethrowAsParcelableException();
2594 public void createVirtualNetwork(int netId, boolean hasDNS, boolean secure) {
2595 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2598 mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0",
2599 secure ? "1" : "0");
2600 } catch (NativeDaemonConnectorException e) {
2601 throw e.rethrowAsParcelableException();
2606 public void removeNetwork(int netId) {
2607 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2610 mConnector.execute("network", "destroy", netId);
2611 } catch (NativeDaemonConnectorException e) {
2612 throw e.rethrowAsParcelableException();
2617 public void addInterfaceToNetwork(String iface, int netId) {
2618 modifyInterfaceInNetwork("add", "" + netId, iface);
2622 public void removeInterfaceFromNetwork(String iface, int netId) {
2623 modifyInterfaceInNetwork("remove", "" + netId, iface);
2626 private void modifyInterfaceInNetwork(String action, String netId, String iface) {
2627 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2629 mConnector.execute("network", "interface", action, netId, iface);
2630 } catch (NativeDaemonConnectorException e) {
2631 throw e.rethrowAsParcelableException();
2636 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
2637 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2639 final Command cmd = new Command("network", "route", "legacy", uid, "add", netId);
2641 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
2642 final LinkAddress la = routeInfo.getDestinationLinkAddress();
2643 cmd.appendArg(routeInfo.getInterface());
2644 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength());
2645 if (routeInfo.hasGateway()) {
2646 cmd.appendArg(routeInfo.getGateway().getHostAddress());
2650 mConnector.execute(cmd);
2651 } catch (NativeDaemonConnectorException e) {
2652 throw e.rethrowAsParcelableException();
2657 public void setDefaultNetId(int netId) {
2658 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2661 mConnector.execute("network", "default", "set", netId);
2662 } catch (NativeDaemonConnectorException e) {
2663 throw e.rethrowAsParcelableException();
2668 public void clearDefaultNetId() {
2669 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2672 mConnector.execute("network", "default", "clear");
2673 } catch (NativeDaemonConnectorException e) {
2674 throw e.rethrowAsParcelableException();
2679 public void setNetworkPermission(int netId, String permission) {
2680 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2683 if (permission != null) {
2684 mConnector.execute("network", "permission", "network", "set", permission, netId);
2686 mConnector.execute("network", "permission", "network", "clear", netId);
2688 } catch (NativeDaemonConnectorException e) {
2689 throw e.rethrowAsParcelableException();
2695 public void setPermission(String permission, int[] uids) {
2696 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2698 Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND];
2699 argv[0] = "permission";
2702 argv[3] = permission;
2704 // Avoid overly long commands by limiting number of UIDs per command.
2705 for (int i = 0; i < uids.length; ++i) {
2706 argv[argc++] = uids[i];
2707 if (i == uids.length - 1 || argc == argv.length) {
2709 mConnector.execute("network", Arrays.copyOf(argv, argc));
2710 } catch (NativeDaemonConnectorException e) {
2711 throw e.rethrowAsParcelableException();
2719 public void clearPermission(int[] uids) {
2720 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2722 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2723 argv[0] = "permission";
2727 // Avoid overly long commands by limiting number of UIDs per command.
2728 for (int i = 0; i < uids.length; ++i) {
2729 argv[argc++] = uids[i];
2730 if (i == uids.length - 1 || argc == argv.length) {
2732 mConnector.execute("network", Arrays.copyOf(argv, argc));
2733 } catch (NativeDaemonConnectorException e) {
2734 throw e.rethrowAsParcelableException();
2742 public void allowProtect(int uid) {
2743 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2746 mConnector.execute("network", "protect", "allow", uid);
2747 } catch (NativeDaemonConnectorException e) {
2748 throw e.rethrowAsParcelableException();
2753 public void denyProtect(int uid) {
2754 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2757 mConnector.execute("network", "protect", "deny", uid);
2758 } catch (NativeDaemonConnectorException e) {
2759 throw e.rethrowAsParcelableException();
2764 public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
2765 modifyInterfaceInNetwork("add", "local", iface);
2767 for (RouteInfo route : routes) {
2768 if (!route.isDefaultRoute()) {
2769 modifyRoute("add", "local", route);
2775 public void removeInterfaceFromLocalNetwork(String iface) {
2776 modifyInterfaceInNetwork("remove", "local", iface);
2780 public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
2783 for (RouteInfo route : routes) {
2785 modifyRoute("remove", "local", route);
2786 } catch (IllegalStateException e) {