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