NetworkManagementService.java revision a701cad320a0a2715cac1c31b269ced2ccbc8ac2
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 int uid, 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, uid); 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 setFirewallUidRuleLocked(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 int processUid = -1; 849 if (cooked.length >= 5) { 850 try { 851 timestampNanos = Long.parseLong(cooked[4]); 852 if (cooked.length == 6) { 853 processUid = Integer.parseInt(cooked[5]); 854 } 855 } catch(NumberFormatException ne) {} 856 } else { 857 timestampNanos = SystemClock.elapsedRealtimeNanos(); 858 } 859 boolean isActive = cooked[2].equals("active"); 860 notifyInterfaceClassActivity(Integer.parseInt(cooked[3]), 861 isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH 862 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, 863 timestampNanos, processUid, false); 864 return true; 865 // break; 866 case NetdResponseCode.InterfaceAddressChange: 867 /* 868 * A network address change occurred 869 * Format: "NNN Address updated <addr> <iface> <flags> <scope>" 870 * "NNN Address removed <addr> <iface> <flags> <scope>" 871 */ 872 if (cooked.length < 7 || !cooked[1].equals("Address")) { 873 throw new IllegalStateException(errorMessage); 874 } 875 876 String iface = cooked[4]; 877 LinkAddress address; 878 try { 879 int flags = Integer.parseInt(cooked[5]); 880 int scope = Integer.parseInt(cooked[6]); 881 address = new LinkAddress(cooked[3], flags, scope); 882 } catch(NumberFormatException e) { // Non-numeric lifetime or scope. 883 throw new IllegalStateException(errorMessage, e); 884 } catch(IllegalArgumentException e) { // Malformed/invalid IP address. 885 throw new IllegalStateException(errorMessage, e); 886 } 887 888 if (cooked[2].equals("updated")) { 889 notifyAddressUpdated(iface, address); 890 } else { 891 notifyAddressRemoved(iface, address); 892 } 893 return true; 894 // break; 895 case NetdResponseCode.InterfaceDnsServerInfo: 896 /* 897 * Information about available DNS servers has been received. 898 * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>" 899 */ 900 long lifetime; // Actually a 32-bit unsigned integer. 901 902 if (cooked.length == 6 && 903 cooked[1].equals("DnsInfo") && 904 cooked[2].equals("servers")) { 905 try { 906 lifetime = Long.parseLong(cooked[4]); 907 } catch (NumberFormatException e) { 908 throw new IllegalStateException(errorMessage); 909 } 910 String[] servers = cooked[5].split(","); 911 notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers); 912 } 913 return true; 914 // break; 915 case NetdResponseCode.RouteChange: 916 /* 917 * A route has been updated or removed. 918 * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]" 919 */ 920 if (!cooked[1].equals("Route") || cooked.length < 6) { 921 throw new IllegalStateException(errorMessage); 922 } 923 924 String via = null; 925 String dev = null; 926 boolean valid = true; 927 for (int i = 4; (i + 1) < cooked.length && valid; i += 2) { 928 if (cooked[i].equals("dev")) { 929 if (dev == null) { 930 dev = cooked[i+1]; 931 } else { 932 valid = false; // Duplicate interface. 933 } 934 } else if (cooked[i].equals("via")) { 935 if (via == null) { 936 via = cooked[i+1]; 937 } else { 938 valid = false; // Duplicate gateway. 939 } 940 } else { 941 valid = false; // Unknown syntax. 942 } 943 } 944 if (valid) { 945 try { 946 // InetAddress.parseNumericAddress(null) inexplicably returns ::1. 947 InetAddress gateway = null; 948 if (via != null) gateway = InetAddress.parseNumericAddress(via); 949 RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev); 950 notifyRouteChange(cooked[2], route); 951 return true; 952 } catch (IllegalArgumentException e) {} 953 } 954 throw new IllegalStateException(errorMessage); 955 // break; 956 case NetdResponseCode.StrictCleartext: 957 final int uid = Integer.parseInt(cooked[1]); 958 final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]); 959 try { 960 ActivityManagerNative.getDefault().notifyCleartextNetwork(uid, firstPacket); 961 } catch (RemoteException ignored) { 962 } 963 break; 964 default: break; 965 } 966 return false; 967 } 968 } 969 970 971 // 972 // INetworkManagementService members 973 // 974 975 @Override 976 public String[] listInterfaces() { 977 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 978 try { 979 return NativeDaemonEvent.filterMessageList( 980 mConnector.executeForList("interface", "list"), InterfaceListResult); 981 } catch (NativeDaemonConnectorException e) { 982 throw e.rethrowAsParcelableException(); 983 } 984 } 985 986 @Override 987 public InterfaceConfiguration getInterfaceConfig(String iface) { 988 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 989 990 final NativeDaemonEvent event; 991 try { 992 event = mConnector.execute("interface", "getcfg", iface); 993 } catch (NativeDaemonConnectorException e) { 994 throw e.rethrowAsParcelableException(); 995 } 996 997 event.checkCode(InterfaceGetCfgResult); 998 999 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3 1000 final StringTokenizer st = new StringTokenizer(event.getMessage()); 1001 1002 InterfaceConfiguration cfg; 1003 try { 1004 cfg = new InterfaceConfiguration(); 1005 cfg.setHardwareAddress(st.nextToken(" ")); 1006 InetAddress addr = null; 1007 int prefixLength = 0; 1008 try { 1009 addr = NetworkUtils.numericToInetAddress(st.nextToken()); 1010 } catch (IllegalArgumentException iae) { 1011 Slog.e(TAG, "Failed to parse ipaddr", iae); 1012 } 1013 1014 try { 1015 prefixLength = Integer.parseInt(st.nextToken()); 1016 } catch (NumberFormatException nfe) { 1017 Slog.e(TAG, "Failed to parse prefixLength", nfe); 1018 } 1019 1020 cfg.setLinkAddress(new LinkAddress(addr, prefixLength)); 1021 while (st.hasMoreTokens()) { 1022 cfg.setFlag(st.nextToken()); 1023 } 1024 } catch (NoSuchElementException nsee) { 1025 throw new IllegalStateException("Invalid response from daemon: " + event); 1026 } 1027 return cfg; 1028 } 1029 1030 @Override 1031 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { 1032 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1033 LinkAddress linkAddr = cfg.getLinkAddress(); 1034 if (linkAddr == null || linkAddr.getAddress() == null) { 1035 throw new IllegalStateException("Null LinkAddress given"); 1036 } 1037 1038 final Command cmd = new Command("interface", "setcfg", iface, 1039 linkAddr.getAddress().getHostAddress(), 1040 linkAddr.getPrefixLength()); 1041 for (String flag : cfg.getFlags()) { 1042 cmd.appendArg(flag); 1043 } 1044 1045 try { 1046 mConnector.execute(cmd); 1047 } catch (NativeDaemonConnectorException e) { 1048 throw e.rethrowAsParcelableException(); 1049 } 1050 } 1051 1052 @Override 1053 public void setInterfaceDown(String iface) { 1054 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1055 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 1056 ifcg.setInterfaceDown(); 1057 setInterfaceConfig(iface, ifcg); 1058 } 1059 1060 @Override 1061 public void setInterfaceUp(String iface) { 1062 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1063 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 1064 ifcg.setInterfaceUp(); 1065 setInterfaceConfig(iface, ifcg); 1066 } 1067 1068 @Override 1069 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { 1070 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1071 try { 1072 mConnector.execute( 1073 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable"); 1074 } catch (NativeDaemonConnectorException e) { 1075 throw e.rethrowAsParcelableException(); 1076 } 1077 } 1078 1079 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 1080 IPv6 addresses on interface down, but we need to do full clean up here */ 1081 @Override 1082 public void clearInterfaceAddresses(String iface) { 1083 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1084 try { 1085 mConnector.execute("interface", "clearaddrs", iface); 1086 } catch (NativeDaemonConnectorException e) { 1087 throw e.rethrowAsParcelableException(); 1088 } 1089 } 1090 1091 @Override 1092 public void enableIpv6(String iface) { 1093 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1094 try { 1095 mConnector.execute("interface", "ipv6", iface, "enable"); 1096 } catch (NativeDaemonConnectorException e) { 1097 throw e.rethrowAsParcelableException(); 1098 } 1099 } 1100 1101 @Override 1102 public void disableIpv6(String iface) { 1103 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1104 try { 1105 mConnector.execute("interface", "ipv6", iface, "disable"); 1106 } catch (NativeDaemonConnectorException e) { 1107 throw e.rethrowAsParcelableException(); 1108 } 1109 } 1110 1111 @Override 1112 public void setInterfaceIpv6NdOffload(String iface, boolean enable) { 1113 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1114 try { 1115 mConnector.execute( 1116 "interface", "ipv6ndoffload", iface, (enable ? "enable" : "disable")); 1117 } catch (NativeDaemonConnectorException e) { 1118 throw e.rethrowAsParcelableException(); 1119 } 1120 } 1121 1122 @Override 1123 public void addRoute(int netId, RouteInfo route) { 1124 modifyRoute("add", "" + netId, route); 1125 } 1126 1127 @Override 1128 public void removeRoute(int netId, RouteInfo route) { 1129 modifyRoute("remove", "" + netId, route); 1130 } 1131 1132 private void modifyRoute(String action, String netId, RouteInfo route) { 1133 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1134 1135 final Command cmd = new Command("network", "route", action, netId); 1136 1137 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr 1138 cmd.appendArg(route.getInterface()); 1139 cmd.appendArg(route.getDestination().toString()); 1140 1141 switch (route.getType()) { 1142 case RouteInfo.RTN_UNICAST: 1143 if (route.hasGateway()) { 1144 cmd.appendArg(route.getGateway().getHostAddress()); 1145 } 1146 break; 1147 case RouteInfo.RTN_UNREACHABLE: 1148 cmd.appendArg("unreachable"); 1149 break; 1150 case RouteInfo.RTN_THROW: 1151 cmd.appendArg("throw"); 1152 break; 1153 } 1154 1155 try { 1156 mConnector.execute(cmd); 1157 } catch (NativeDaemonConnectorException e) { 1158 throw e.rethrowAsParcelableException(); 1159 } 1160 } 1161 1162 private ArrayList<String> readRouteList(String filename) { 1163 FileInputStream fstream = null; 1164 ArrayList<String> list = new ArrayList<String>(); 1165 1166 try { 1167 fstream = new FileInputStream(filename); 1168 DataInputStream in = new DataInputStream(fstream); 1169 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 1170 String s; 1171 1172 // throw away the title line 1173 1174 while (((s = br.readLine()) != null) && (s.length() != 0)) { 1175 list.add(s); 1176 } 1177 } catch (IOException ex) { 1178 // return current list, possibly empty 1179 } finally { 1180 if (fstream != null) { 1181 try { 1182 fstream.close(); 1183 } catch (IOException ex) {} 1184 } 1185 } 1186 1187 return list; 1188 } 1189 1190 @Override 1191 public void setMtu(String iface, int mtu) { 1192 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1193 1194 final NativeDaemonEvent event; 1195 try { 1196 event = mConnector.execute("interface", "setmtu", iface, mtu); 1197 } catch (NativeDaemonConnectorException e) { 1198 throw e.rethrowAsParcelableException(); 1199 } 1200 } 1201 1202 @Override 1203 public void shutdown() { 1204 // TODO: remove from aidl if nobody calls externally 1205 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG); 1206 1207 Slog.i(TAG, "Shutting down"); 1208 } 1209 1210 @Override 1211 public boolean getIpForwardingEnabled() throws IllegalStateException{ 1212 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1213 1214 final NativeDaemonEvent event; 1215 try { 1216 event = mConnector.execute("ipfwd", "status"); 1217 } catch (NativeDaemonConnectorException e) { 1218 throw e.rethrowAsParcelableException(); 1219 } 1220 1221 // 211 Forwarding enabled 1222 event.checkCode(IpFwdStatusResult); 1223 return event.getMessage().endsWith("enabled"); 1224 } 1225 1226 @Override 1227 public void setIpForwardingEnabled(boolean enable) { 1228 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1229 try { 1230 mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering"); 1231 } catch (NativeDaemonConnectorException e) { 1232 throw e.rethrowAsParcelableException(); 1233 } 1234 } 1235 1236 @Override 1237 public void startTethering(String[] dhcpRange) { 1238 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1239 // cmd is "tether start first_start first_stop second_start second_stop ..." 1240 // an odd number of addrs will fail 1241 1242 final Command cmd = new Command("tether", "start"); 1243 for (String d : dhcpRange) { 1244 cmd.appendArg(d); 1245 } 1246 1247 try { 1248 mConnector.execute(cmd); 1249 } catch (NativeDaemonConnectorException e) { 1250 throw e.rethrowAsParcelableException(); 1251 } 1252 } 1253 1254 @Override 1255 public void stopTethering() { 1256 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1257 try { 1258 mConnector.execute("tether", "stop"); 1259 } catch (NativeDaemonConnectorException e) { 1260 throw e.rethrowAsParcelableException(); 1261 } 1262 } 1263 1264 @Override 1265 public boolean isTetheringStarted() { 1266 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1267 1268 final NativeDaemonEvent event; 1269 try { 1270 event = mConnector.execute("tether", "status"); 1271 } catch (NativeDaemonConnectorException e) { 1272 throw e.rethrowAsParcelableException(); 1273 } 1274 1275 // 210 Tethering services started 1276 event.checkCode(TetherStatusResult); 1277 return event.getMessage().endsWith("started"); 1278 } 1279 1280 @Override 1281 public void tetherInterface(String iface) { 1282 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1283 try { 1284 mConnector.execute("tether", "interface", "add", iface); 1285 } catch (NativeDaemonConnectorException e) { 1286 throw e.rethrowAsParcelableException(); 1287 } 1288 List<RouteInfo> routes = new ArrayList<RouteInfo>(); 1289 // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it 1290 // suitable to use as a route destination. 1291 routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface)); 1292 addInterfaceToLocalNetwork(iface, routes); 1293 } 1294 1295 @Override 1296 public void untetherInterface(String iface) { 1297 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1298 try { 1299 mConnector.execute("tether", "interface", "remove", iface); 1300 } catch (NativeDaemonConnectorException e) { 1301 throw e.rethrowAsParcelableException(); 1302 } 1303 removeInterfaceFromLocalNetwork(iface); 1304 } 1305 1306 @Override 1307 public String[] listTetheredInterfaces() { 1308 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1309 try { 1310 return NativeDaemonEvent.filterMessageList( 1311 mConnector.executeForList("tether", "interface", "list"), 1312 TetherInterfaceListResult); 1313 } catch (NativeDaemonConnectorException e) { 1314 throw e.rethrowAsParcelableException(); 1315 } 1316 } 1317 1318 @Override 1319 public void setDnsForwarders(Network network, String[] dns) { 1320 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1321 1322 int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET; 1323 final Command cmd = new Command("tether", "dns", "set", netId); 1324 1325 for (String s : dns) { 1326 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress()); 1327 } 1328 1329 try { 1330 mConnector.execute(cmd); 1331 } catch (NativeDaemonConnectorException e) { 1332 throw e.rethrowAsParcelableException(); 1333 } 1334 } 1335 1336 @Override 1337 public String[] getDnsForwarders() { 1338 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1339 try { 1340 return NativeDaemonEvent.filterMessageList( 1341 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult); 1342 } catch (NativeDaemonConnectorException e) { 1343 throw e.rethrowAsParcelableException(); 1344 } 1345 } 1346 1347 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) { 1348 ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size()); 1349 for (InterfaceAddress ia : addresses) { 1350 if (!ia.getAddress().isLinkLocalAddress()) 1351 filtered.add(ia); 1352 } 1353 return filtered; 1354 } 1355 1356 private void modifyInterfaceForward(boolean add, String fromIface, String toIface) { 1357 final Command cmd = new Command("ipfwd", add ? "add" : "remove", fromIface, toIface); 1358 try { 1359 mConnector.execute(cmd); 1360 } catch (NativeDaemonConnectorException e) { 1361 throw e.rethrowAsParcelableException(); 1362 } 1363 } 1364 1365 @Override 1366 public void startInterfaceForwarding(String fromIface, String toIface) { 1367 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1368 modifyInterfaceForward(true, fromIface, toIface); 1369 } 1370 1371 @Override 1372 public void stopInterfaceForwarding(String fromIface, String toIface) { 1373 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1374 modifyInterfaceForward(false, fromIface, toIface); 1375 } 1376 1377 private void modifyNat(String action, String internalInterface, String externalInterface) 1378 throws SocketException { 1379 final Command cmd = new Command("nat", action, internalInterface, externalInterface); 1380 1381 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName( 1382 internalInterface); 1383 if (internalNetworkInterface == null) { 1384 cmd.appendArg("0"); 1385 } else { 1386 // Don't touch link-local routes, as link-local addresses aren't routable, 1387 // kernel creates link-local routes on all interfaces automatically 1388 List<InterfaceAddress> interfaceAddresses = excludeLinkLocal( 1389 internalNetworkInterface.getInterfaceAddresses()); 1390 cmd.appendArg(interfaceAddresses.size()); 1391 for (InterfaceAddress ia : interfaceAddresses) { 1392 InetAddress addr = NetworkUtils.getNetworkPart( 1393 ia.getAddress(), ia.getNetworkPrefixLength()); 1394 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength()); 1395 } 1396 } 1397 1398 try { 1399 mConnector.execute(cmd); 1400 } catch (NativeDaemonConnectorException e) { 1401 throw e.rethrowAsParcelableException(); 1402 } 1403 } 1404 1405 @Override 1406 public void enableNat(String internalInterface, String externalInterface) { 1407 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1408 try { 1409 modifyNat("enable", internalInterface, externalInterface); 1410 } catch (SocketException e) { 1411 throw new IllegalStateException(e); 1412 } 1413 } 1414 1415 @Override 1416 public void disableNat(String internalInterface, String externalInterface) { 1417 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1418 try { 1419 modifyNat("disable", internalInterface, externalInterface); 1420 } catch (SocketException e) { 1421 throw new IllegalStateException(e); 1422 } 1423 } 1424 1425 @Override 1426 public String[] listTtys() { 1427 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1428 try { 1429 return NativeDaemonEvent.filterMessageList( 1430 mConnector.executeForList("list_ttys"), TtyListResult); 1431 } catch (NativeDaemonConnectorException e) { 1432 throw e.rethrowAsParcelableException(); 1433 } 1434 } 1435 1436 @Override 1437 public void attachPppd( 1438 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) { 1439 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1440 try { 1441 mConnector.execute("pppd", "attach", tty, 1442 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 1443 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 1444 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 1445 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()); 1446 } catch (NativeDaemonConnectorException e) { 1447 throw e.rethrowAsParcelableException(); 1448 } 1449 } 1450 1451 @Override 1452 public void detachPppd(String tty) { 1453 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1454 try { 1455 mConnector.execute("pppd", "detach", tty); 1456 } catch (NativeDaemonConnectorException e) { 1457 throw e.rethrowAsParcelableException(); 1458 } 1459 } 1460 1461 /** 1462 * Private method used to call execute for a command given the provided arguments. 1463 * 1464 * This function checks the returned NativeDaemonEvent for the provided expected response code 1465 * and message. If either of these is not correct, an error is logged. 1466 * 1467 * @param String command The command to execute. 1468 * @param Object[] args If needed, arguments for the command to execute. 1469 * @param int expectedResponseCode The code expected to be returned in the corresponding event. 1470 * @param String expectedResponseMessage The message expected in the returned event. 1471 * @param String logMsg The message to log as an error (TAG will be applied). 1472 */ 1473 private void executeOrLogWithMessage(String command, Object[] args, 1474 int expectedResponseCode, String expectedResponseMessage, String logMsg) 1475 throws NativeDaemonConnectorException { 1476 NativeDaemonEvent event = mConnector.execute(command, args); 1477 if (event.getCode() != expectedResponseCode 1478 || !event.getMessage().equals(expectedResponseMessage)) { 1479 Log.e(TAG, logMsg + ": event = " + event); 1480 } 1481 } 1482 1483 @Override 1484 public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { 1485 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1486 Object[] args; 1487 String logMsg = "startAccessPoint Error setting up softap"; 1488 try { 1489 if (wifiConfig == null) { 1490 args = new Object[] {"set", wlanIface}; 1491 } else { 1492 args = new Object[] {"set", wlanIface, wifiConfig.SSID, 1493 "broadcast", Integer.toString(wifiConfig.apChannel), 1494 getSecurityType(wifiConfig), new SensitiveArg(wifiConfig.preSharedKey)}; 1495 } 1496 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult, 1497 SOFT_AP_COMMAND_SUCCESS, logMsg); 1498 1499 logMsg = "startAccessPoint Error starting softap"; 1500 args = new Object[] {"startap"}; 1501 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult, 1502 SOFT_AP_COMMAND_SUCCESS, logMsg); 1503 } catch (NativeDaemonConnectorException e) { 1504 throw e.rethrowAsParcelableException(); 1505 } 1506 } 1507 1508 private static String getSecurityType(WifiConfiguration wifiConfig) { 1509 switch (wifiConfig.getAuthType()) { 1510 case KeyMgmt.WPA_PSK: 1511 return "wpa-psk"; 1512 case KeyMgmt.WPA2_PSK: 1513 return "wpa2-psk"; 1514 default: 1515 return "open"; 1516 } 1517 } 1518 1519 /* @param mode can be "AP", "STA" or "P2P" */ 1520 @Override 1521 public void wifiFirmwareReload(String wlanIface, String mode) { 1522 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1523 Object[] args = {"fwreload", wlanIface, mode}; 1524 String logMsg = "wifiFirmwareReload Error reloading " 1525 + wlanIface + " fw in " + mode + " mode"; 1526 try { 1527 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult, 1528 SOFT_AP_COMMAND_SUCCESS, logMsg); 1529 } catch (NativeDaemonConnectorException e) { 1530 throw e.rethrowAsParcelableException(); 1531 } 1532 1533 // Ensure that before we return from this command, any asynchronous 1534 // notifications generated before the command completed have been 1535 // processed by all NetworkManagementEventObservers. 1536 mConnector.waitForCallbacks(); 1537 } 1538 1539 @Override 1540 public void stopAccessPoint(String wlanIface) { 1541 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1542 Object[] args = {"stopap"}; 1543 String logMsg = "stopAccessPoint Error stopping softap"; 1544 1545 try { 1546 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult, 1547 SOFT_AP_COMMAND_SUCCESS, logMsg); 1548 wifiFirmwareReload(wlanIface, "STA"); 1549 } catch (NativeDaemonConnectorException e) { 1550 throw e.rethrowAsParcelableException(); 1551 } 1552 } 1553 1554 @Override 1555 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { 1556 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1557 Object[] args; 1558 String logMsg = "startAccessPoint Error setting up softap"; 1559 try { 1560 if (wifiConfig == null) { 1561 args = new Object[] {"set", wlanIface}; 1562 } else { 1563 // TODO: understand why this is set to "6" instead of 1564 // Integer.toString(wifiConfig.apChannel) as in startAccessPoint 1565 // TODO: should startAccessPoint call this instead of repeating code? 1566 args = new Object[] {"set", wlanIface, wifiConfig.SSID, 1567 "broadcast", "6", 1568 getSecurityType(wifiConfig), new SensitiveArg(wifiConfig.preSharedKey)}; 1569 } 1570 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult, 1571 SOFT_AP_COMMAND_SUCCESS, logMsg); 1572 } catch (NativeDaemonConnectorException e) { 1573 throw e.rethrowAsParcelableException(); 1574 } 1575 } 1576 1577 @Override 1578 public void addIdleTimer(String iface, int timeout, final int type) { 1579 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1580 1581 if (DBG) Slog.d(TAG, "Adding idletimer"); 1582 1583 synchronized (mIdleTimerLock) { 1584 IdleTimerParams params = mActiveIdleTimers.get(iface); 1585 if (params != null) { 1586 // the interface already has idletimer, update network count 1587 params.networkCount++; 1588 return; 1589 } 1590 1591 try { 1592 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout), 1593 Integer.toString(type)); 1594 } catch (NativeDaemonConnectorException e) { 1595 throw e.rethrowAsParcelableException(); 1596 } 1597 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type)); 1598 1599 // Networks start up. 1600 if (ConnectivityManager.isNetworkTypeMobile(type)) { 1601 mNetworkActive = false; 1602 } 1603 mDaemonHandler.post(new Runnable() { 1604 @Override public void run() { 1605 notifyInterfaceClassActivity(type, 1606 DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 1607 SystemClock.elapsedRealtimeNanos(), -1, false); 1608 } 1609 }); 1610 } 1611 } 1612 1613 @Override 1614 public void removeIdleTimer(String iface) { 1615 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1616 1617 if (DBG) Slog.d(TAG, "Removing idletimer"); 1618 1619 synchronized (mIdleTimerLock) { 1620 final IdleTimerParams params = mActiveIdleTimers.get(iface); 1621 if (params == null || --(params.networkCount) > 0) { 1622 return; 1623 } 1624 1625 try { 1626 mConnector.execute("idletimer", "remove", iface, 1627 Integer.toString(params.timeout), Integer.toString(params.type)); 1628 } catch (NativeDaemonConnectorException e) { 1629 throw e.rethrowAsParcelableException(); 1630 } 1631 mActiveIdleTimers.remove(iface); 1632 mDaemonHandler.post(new Runnable() { 1633 @Override public void run() { 1634 notifyInterfaceClassActivity(params.type, 1635 DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, 1636 SystemClock.elapsedRealtimeNanos(), -1, false); 1637 } 1638 }); 1639 } 1640 } 1641 1642 @Override 1643 public NetworkStats getNetworkStatsSummaryDev() { 1644 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1645 try { 1646 return mStatsFactory.readNetworkStatsSummaryDev(); 1647 } catch (IOException e) { 1648 throw new IllegalStateException(e); 1649 } 1650 } 1651 1652 @Override 1653 public NetworkStats getNetworkStatsSummaryXt() { 1654 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1655 try { 1656 return mStatsFactory.readNetworkStatsSummaryXt(); 1657 } catch (IOException e) { 1658 throw new IllegalStateException(e); 1659 } 1660 } 1661 1662 @Override 1663 public NetworkStats getNetworkStatsDetail() { 1664 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1665 try { 1666 return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); 1667 } catch (IOException e) { 1668 throw new IllegalStateException(e); 1669 } 1670 } 1671 1672 @Override 1673 public void setInterfaceQuota(String iface, long quotaBytes) { 1674 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1675 1676 // silently discard when control disabled 1677 // TODO: eventually migrate to be always enabled 1678 if (!mBandwidthControlEnabled) return; 1679 1680 synchronized (mQuotaLock) { 1681 if (mActiveQuotas.containsKey(iface)) { 1682 throw new IllegalStateException("iface " + iface + " already has quota"); 1683 } 1684 1685 try { 1686 // TODO: support quota shared across interfaces 1687 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes); 1688 mActiveQuotas.put(iface, quotaBytes); 1689 } catch (NativeDaemonConnectorException e) { 1690 throw e.rethrowAsParcelableException(); 1691 } 1692 } 1693 } 1694 1695 @Override 1696 public void removeInterfaceQuota(String iface) { 1697 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1698 1699 // silently discard when control disabled 1700 // TODO: eventually migrate to be always enabled 1701 if (!mBandwidthControlEnabled) return; 1702 1703 synchronized (mQuotaLock) { 1704 if (!mActiveQuotas.containsKey(iface)) { 1705 // TODO: eventually consider throwing 1706 return; 1707 } 1708 1709 mActiveQuotas.remove(iface); 1710 mActiveAlerts.remove(iface); 1711 1712 try { 1713 // TODO: support quota shared across interfaces 1714 mConnector.execute("bandwidth", "removeiquota", iface); 1715 } catch (NativeDaemonConnectorException e) { 1716 throw e.rethrowAsParcelableException(); 1717 } 1718 } 1719 } 1720 1721 @Override 1722 public void setInterfaceAlert(String iface, long alertBytes) { 1723 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1724 1725 // silently discard when control disabled 1726 // TODO: eventually migrate to be always enabled 1727 if (!mBandwidthControlEnabled) return; 1728 1729 // quick sanity check 1730 if (!mActiveQuotas.containsKey(iface)) { 1731 throw new IllegalStateException("setting alert requires existing quota on iface"); 1732 } 1733 1734 synchronized (mQuotaLock) { 1735 if (mActiveAlerts.containsKey(iface)) { 1736 throw new IllegalStateException("iface " + iface + " already has alert"); 1737 } 1738 1739 try { 1740 // TODO: support alert shared across interfaces 1741 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes); 1742 mActiveAlerts.put(iface, alertBytes); 1743 } catch (NativeDaemonConnectorException e) { 1744 throw e.rethrowAsParcelableException(); 1745 } 1746 } 1747 } 1748 1749 @Override 1750 public void removeInterfaceAlert(String iface) { 1751 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1752 1753 // silently discard when control disabled 1754 // TODO: eventually migrate to be always enabled 1755 if (!mBandwidthControlEnabled) return; 1756 1757 synchronized (mQuotaLock) { 1758 if (!mActiveAlerts.containsKey(iface)) { 1759 // TODO: eventually consider throwing 1760 return; 1761 } 1762 1763 try { 1764 // TODO: support alert shared across interfaces 1765 mConnector.execute("bandwidth", "removeinterfacealert", iface); 1766 mActiveAlerts.remove(iface); 1767 } catch (NativeDaemonConnectorException e) { 1768 throw e.rethrowAsParcelableException(); 1769 } 1770 } 1771 } 1772 1773 @Override 1774 public void setGlobalAlert(long alertBytes) { 1775 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1776 1777 // silently discard when control disabled 1778 // TODO: eventually migrate to be always enabled 1779 if (!mBandwidthControlEnabled) return; 1780 1781 try { 1782 mConnector.execute("bandwidth", "setglobalalert", alertBytes); 1783 } catch (NativeDaemonConnectorException e) { 1784 throw e.rethrowAsParcelableException(); 1785 } 1786 } 1787 1788 private void setUidOnMeteredNetworkList(SparseBooleanArray quotaList, int uid, 1789 boolean blacklist, boolean enable) { 1790 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1791 1792 // silently discard when control disabled 1793 // TODO: eventually migrate to be always enabled 1794 if (!mBandwidthControlEnabled) return; 1795 1796 final String chain = blacklist ? "naughtyapps" : "niceapps"; 1797 final String suffix = enable ? "add" : "remove"; 1798 1799 synchronized (mQuotaLock) { 1800 final boolean oldEnable = quotaList.get(uid, false); 1801 if (oldEnable == enable) { 1802 // TODO: eventually consider throwing 1803 return; 1804 } 1805 1806 try { 1807 mConnector.execute("bandwidth", suffix + chain, uid); 1808 if (enable) { 1809 quotaList.put(uid, true); 1810 } else { 1811 quotaList.delete(uid); 1812 } 1813 } catch (NativeDaemonConnectorException e) { 1814 throw e.rethrowAsParcelableException(); 1815 } 1816 } 1817 } 1818 1819 @Override 1820 public void setUidMeteredNetworkBlacklist(int uid, boolean enable) { 1821 setUidOnMeteredNetworkList(mUidRejectOnMetered, uid, true, enable); 1822 } 1823 1824 @Override 1825 public void setUidMeteredNetworkWhitelist(int uid, boolean enable) { 1826 setUidOnMeteredNetworkList(mUidAllowOnMetered, uid, false, enable); 1827 } 1828 1829 @Override 1830 public boolean setDataSaverModeEnabled(boolean enable) { 1831 if (DBG) Log.d(TAG, "setDataSaverMode: " + enable); 1832 synchronized (mQuotaLock) { 1833 if (mDataSaverMode == enable) { 1834 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode); 1835 return true; 1836 } 1837 try { 1838 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable); 1839 if (changed) { 1840 mDataSaverMode = enable; 1841 } else { 1842 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed"); 1843 } 1844 return changed; 1845 } catch (RemoteException e) { 1846 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e); 1847 return false; 1848 } 1849 } 1850 } 1851 1852 @Override 1853 public void setUidCleartextNetworkPolicy(int uid, int policy) { 1854 if (Binder.getCallingUid() != uid) { 1855 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1856 } 1857 1858 synchronized (mQuotaLock) { 1859 final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT); 1860 if (oldPolicy == policy) { 1861 return; 1862 } 1863 1864 if (!mStrictEnabled) { 1865 // Module isn't enabled yet; stash the requested policy away to 1866 // apply later once the daemon is connected. 1867 mUidCleartextPolicy.put(uid, policy); 1868 return; 1869 } 1870 1871 final String policyString; 1872 switch (policy) { 1873 case StrictMode.NETWORK_POLICY_ACCEPT: 1874 policyString = "accept"; 1875 break; 1876 case StrictMode.NETWORK_POLICY_LOG: 1877 policyString = "log"; 1878 break; 1879 case StrictMode.NETWORK_POLICY_REJECT: 1880 policyString = "reject"; 1881 break; 1882 default: 1883 throw new IllegalArgumentException("Unknown policy " + policy); 1884 } 1885 1886 try { 1887 mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString); 1888 mUidCleartextPolicy.put(uid, policy); 1889 } catch (NativeDaemonConnectorException e) { 1890 throw e.rethrowAsParcelableException(); 1891 } 1892 } 1893 } 1894 1895 @Override 1896 public boolean isBandwidthControlEnabled() { 1897 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1898 return mBandwidthControlEnabled; 1899 } 1900 1901 @Override 1902 public NetworkStats getNetworkStatsUidDetail(int uid) { 1903 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1904 try { 1905 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null); 1906 } catch (IOException e) { 1907 throw new IllegalStateException(e); 1908 } 1909 } 1910 1911 @Override 1912 public NetworkStats getNetworkStatsTethering() { 1913 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1914 1915 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1916 try { 1917 final NativeDaemonEvent[] events = mConnector.executeForList( 1918 "bandwidth", "gettetherstats"); 1919 for (NativeDaemonEvent event : events) { 1920 if (event.getCode() != TetheringStatsListResult) continue; 1921 1922 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets 1923 final StringTokenizer tok = new StringTokenizer(event.getMessage()); 1924 try { 1925 final String ifaceIn = tok.nextToken(); 1926 final String ifaceOut = tok.nextToken(); 1927 1928 final NetworkStats.Entry entry = new NetworkStats.Entry(); 1929 entry.iface = ifaceOut; 1930 entry.uid = UID_TETHERING; 1931 entry.set = SET_DEFAULT; 1932 entry.tag = TAG_NONE; 1933 entry.rxBytes = Long.parseLong(tok.nextToken()); 1934 entry.rxPackets = Long.parseLong(tok.nextToken()); 1935 entry.txBytes = Long.parseLong(tok.nextToken()); 1936 entry.txPackets = Long.parseLong(tok.nextToken()); 1937 stats.combineValues(entry); 1938 } catch (NoSuchElementException e) { 1939 throw new IllegalStateException("problem parsing tethering stats: " + event); 1940 } catch (NumberFormatException e) { 1941 throw new IllegalStateException("problem parsing tethering stats: " + event); 1942 } 1943 } 1944 } catch (NativeDaemonConnectorException e) { 1945 throw e.rethrowAsParcelableException(); 1946 } 1947 return stats; 1948 } 1949 1950 @Override 1951 public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) { 1952 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1953 1954 ContentResolver resolver = mContext.getContentResolver(); 1955 1956 int sampleValidity = Settings.Global.getInt(resolver, 1957 Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS, 1958 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS); 1959 if (sampleValidity < 0 || sampleValidity > 65535) { 1960 Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" + 1961 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS); 1962 sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS; 1963 } 1964 1965 int successThreshold = Settings.Global.getInt(resolver, 1966 Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT, 1967 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT); 1968 if (successThreshold < 0 || successThreshold > 100) { 1969 Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" + 1970 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT); 1971 successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT; 1972 } 1973 1974 int minSamples = Settings.Global.getInt(resolver, 1975 Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES); 1976 int maxSamples = Settings.Global.getInt(resolver, 1977 Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES); 1978 if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) { 1979 Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples + 1980 "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " + 1981 DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")"); 1982 minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES; 1983 maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES; 1984 } 1985 1986 final String[] domainStrs = domains == null ? new String[0] : domains.split(" "); 1987 final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples }; 1988 try { 1989 mNetdService.setResolverConfiguration(netId, servers, domainStrs, params); 1990 } catch (RemoteException e) { 1991 throw new RuntimeException(e); 1992 } 1993 } 1994 1995 @Override 1996 public void setDnsServersForNetwork(int netId, String[] servers, String domains) { 1997 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1998 1999 Command cmd; 2000 if (servers.length > 0) { 2001 cmd = new Command("resolver", "setnetdns", netId, 2002 (domains == null ? "" : domains)); 2003 for (String s : servers) { 2004 InetAddress a = NetworkUtils.numericToInetAddress(s); 2005 if (a.isAnyLocalAddress() == false) { 2006 cmd.appendArg(a.getHostAddress()); 2007 } 2008 } 2009 } else { 2010 cmd = new Command("resolver", "clearnetdns", netId); 2011 } 2012 2013 try { 2014 mConnector.execute(cmd); 2015 } catch (NativeDaemonConnectorException e) { 2016 throw e.rethrowAsParcelableException(); 2017 } 2018 } 2019 2020 @Override 2021 public void addVpnUidRanges(int netId, UidRange[] ranges) { 2022 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2023 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 2024 argv[0] = "users"; 2025 argv[1] = "add"; 2026 argv[2] = netId; 2027 int argc = 3; 2028 // Avoid overly long commands by limiting number of UID ranges per command. 2029 for (int i = 0; i < ranges.length; i++) { 2030 argv[argc++] = ranges[i].toString(); 2031 if (i == (ranges.length - 1) || argc == argv.length) { 2032 try { 2033 mConnector.execute("network", Arrays.copyOf(argv, argc)); 2034 } catch (NativeDaemonConnectorException e) { 2035 throw e.rethrowAsParcelableException(); 2036 } 2037 argc = 3; 2038 } 2039 } 2040 } 2041 2042 @Override 2043 public void removeVpnUidRanges(int netId, UidRange[] ranges) { 2044 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2045 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 2046 argv[0] = "users"; 2047 argv[1] = "remove"; 2048 argv[2] = netId; 2049 int argc = 3; 2050 // Avoid overly long commands by limiting number of UID ranges per command. 2051 for (int i = 0; i < ranges.length; i++) { 2052 argv[argc++] = ranges[i].toString(); 2053 if (i == (ranges.length - 1) || argc == argv.length) { 2054 try { 2055 mConnector.execute("network", Arrays.copyOf(argv, argc)); 2056 } catch (NativeDaemonConnectorException e) { 2057 throw e.rethrowAsParcelableException(); 2058 } 2059 argc = 3; 2060 } 2061 } 2062 } 2063 2064 @Override 2065 public void setFirewallEnabled(boolean enabled) { 2066 enforceSystemUid(); 2067 try { 2068 mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist"); 2069 mFirewallEnabled = enabled; 2070 } catch (NativeDaemonConnectorException e) { 2071 throw e.rethrowAsParcelableException(); 2072 } 2073 } 2074 2075 @Override 2076 public boolean isFirewallEnabled() { 2077 enforceSystemUid(); 2078 return mFirewallEnabled; 2079 } 2080 2081 @Override 2082 public void setFirewallInterfaceRule(String iface, boolean allow) { 2083 enforceSystemUid(); 2084 Preconditions.checkState(mFirewallEnabled); 2085 final String rule = allow ? "allow" : "deny"; 2086 try { 2087 mConnector.execute("firewall", "set_interface_rule", iface, rule); 2088 } catch (NativeDaemonConnectorException e) { 2089 throw e.rethrowAsParcelableException(); 2090 } 2091 } 2092 2093 @Override 2094 public void setFirewallEgressSourceRule(String addr, boolean allow) { 2095 enforceSystemUid(); 2096 Preconditions.checkState(mFirewallEnabled); 2097 final String rule = allow ? "allow" : "deny"; 2098 try { 2099 mConnector.execute("firewall", "set_egress_source_rule", addr, rule); 2100 } catch (NativeDaemonConnectorException e) { 2101 throw e.rethrowAsParcelableException(); 2102 } 2103 } 2104 2105 @Override 2106 public void setFirewallEgressDestRule(String addr, int port, boolean allow) { 2107 enforceSystemUid(); 2108 Preconditions.checkState(mFirewallEnabled); 2109 final String rule = allow ? "allow" : "deny"; 2110 try { 2111 mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule); 2112 } catch (NativeDaemonConnectorException e) { 2113 throw e.rethrowAsParcelableException(); 2114 } 2115 } 2116 2117 private void closeSocketsForFirewallChainLocked(int chain, String chainName) { 2118 // UID ranges to close sockets on. 2119 UidRange[] ranges; 2120 // UID ranges whose sockets we won't touch. 2121 int[] exemptUids; 2122 2123 final SparseIntArray rules = getUidFirewallRules(chain); 2124 int numUids = 0; 2125 2126 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) { 2127 // Close all sockets on all non-system UIDs... 2128 ranges = new UidRange[] { 2129 // TODO: is there a better way of finding all existing users? If so, we could 2130 // specify their ranges here. 2131 new UidRange(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE), 2132 }; 2133 // ... except for the UIDs that have allow rules. 2134 exemptUids = new int[rules.size()]; 2135 for (int i = 0; i < exemptUids.length; i++) { 2136 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { 2137 exemptUids[numUids] = rules.keyAt(i); 2138 numUids++; 2139 } 2140 } 2141 // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length. 2142 // But the code does not guarantee this in any way, and at least in one case - if we add 2143 // a UID rule to the firewall, and then disable the firewall - the chains can contain 2144 // the wrong type of rule. In this case, don't close connections that we shouldn't. 2145 // 2146 // TODO: tighten up this code by ensuring we never set the wrong type of rule, and 2147 // fix setFirewallEnabled to grab mQuotaLock and clear rules. 2148 if (numUids != exemptUids.length) { 2149 exemptUids = Arrays.copyOf(exemptUids, numUids); 2150 } 2151 } else { 2152 // Close sockets for every UID that has a deny rule... 2153 ranges = new UidRange[rules.size()]; 2154 for (int i = 0; i < ranges.length; i++) { 2155 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_DENY) { 2156 int uid = rules.keyAt(i); 2157 ranges[numUids] = new UidRange(uid, uid); 2158 numUids++; 2159 } 2160 } 2161 // As above; usually numUids == ranges.length, but not always. 2162 if (numUids != ranges.length) { 2163 ranges = Arrays.copyOf(ranges, numUids); 2164 } 2165 // ... with no exceptions. 2166 exemptUids = new int[0]; 2167 } 2168 2169 try { 2170 mNetdService.socketDestroy(ranges, exemptUids); 2171 } catch(RemoteException | ServiceSpecificException e) { 2172 Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e); 2173 } 2174 } 2175 2176 @Override 2177 public void setFirewallChainEnabled(int chain, boolean enable) { 2178 enforceSystemUid(); 2179 synchronized (mQuotaLock) { 2180 if (mFirewallChainStates.get(chain) == enable) { 2181 // All is the same, nothing to do. This relies on the fact that netd has child 2182 // chains default detached. 2183 return; 2184 } 2185 mFirewallChainStates.put(chain, enable); 2186 2187 final String operation = enable ? "enable_chain" : "disable_chain"; 2188 final String chainName; 2189 switch(chain) { 2190 case FIREWALL_CHAIN_STANDBY: 2191 chainName = FIREWALL_CHAIN_NAME_STANDBY; 2192 break; 2193 case FIREWALL_CHAIN_DOZABLE: 2194 chainName = FIREWALL_CHAIN_NAME_DOZABLE; 2195 break; 2196 case FIREWALL_CHAIN_POWERSAVE: 2197 chainName = FIREWALL_CHAIN_NAME_POWERSAVE; 2198 break; 2199 default: 2200 throw new IllegalArgumentException("Bad child chain: " + chain); 2201 } 2202 2203 try { 2204 mConnector.execute("firewall", operation, chainName); 2205 } catch (NativeDaemonConnectorException e) { 2206 throw e.rethrowAsParcelableException(); 2207 } 2208 2209 // Close any sockets that were opened by the affected UIDs. This has to be done after 2210 // disabling network connectivity, in case they react to the socket close by reopening 2211 // the connection and race with the iptables commands that enable the firewall. All 2212 // whitelist and blacklist chains allow RSTs through. 2213 if (enable) { 2214 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName); 2215 closeSocketsForFirewallChainLocked(chain, chainName); 2216 } 2217 } 2218 } 2219 2220 private int getFirewallType(int chain) { 2221 switch (chain) { 2222 case FIREWALL_CHAIN_STANDBY: 2223 return FIREWALL_TYPE_BLACKLIST; 2224 case FIREWALL_CHAIN_DOZABLE: 2225 return FIREWALL_TYPE_WHITELIST; 2226 case FIREWALL_CHAIN_POWERSAVE: 2227 return FIREWALL_TYPE_WHITELIST; 2228 default: 2229 return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST; 2230 } 2231 } 2232 2233 @Override 2234 public void setFirewallUidRules(int chain, int[] uids, int[] rules) { 2235 enforceSystemUid(); 2236 synchronized (mQuotaLock) { 2237 SparseIntArray uidFirewallRules = getUidFirewallRules(chain); 2238 SparseIntArray newRules = new SparseIntArray(); 2239 // apply new set of rules 2240 for (int index = uids.length - 1; index >= 0; --index) { 2241 int uid = uids[index]; 2242 int rule = rules[index]; 2243 updateFirewallUidRuleLocked(chain, uid, rule); 2244 newRules.put(uid, rule); 2245 } 2246 // collect the rules to remove. 2247 SparseIntArray rulesToRemove = new SparseIntArray(); 2248 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) { 2249 int uid = uidFirewallRules.keyAt(index); 2250 if (newRules.indexOfKey(uid) < 0) { 2251 rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT); 2252 } 2253 } 2254 // remove dead rules 2255 for (int index = rulesToRemove.size() - 1; index >= 0; --index) { 2256 int uid = rulesToRemove.keyAt(index); 2257 updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT); 2258 } 2259 try { 2260 switch (chain) { 2261 case FIREWALL_CHAIN_DOZABLE: 2262 mNetdService.firewallReplaceUidChain("fw_dozable", true, uids); 2263 break; 2264 case FIREWALL_CHAIN_STANDBY: 2265 mNetdService.firewallReplaceUidChain("fw_standby", false, uids); 2266 break; 2267 case FIREWALL_CHAIN_POWERSAVE: 2268 mNetdService.firewallReplaceUidChain("fw_powersave", true, uids); 2269 break; 2270 case FIREWALL_CHAIN_NONE: 2271 default: 2272 Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain); 2273 } 2274 } catch (RemoteException e) { 2275 Slog.w(TAG, "Error flushing firewall chain " + chain, e); 2276 } 2277 } 2278 } 2279 2280 @Override 2281 public void setFirewallUidRule(int chain, int uid, int rule) { 2282 enforceSystemUid(); 2283 synchronized (mQuotaLock) { 2284 setFirewallUidRuleLocked(chain, uid, rule); 2285 } 2286 } 2287 2288 private void setFirewallUidRuleLocked(int chain, int uid, int rule) { 2289 if (updateFirewallUidRuleLocked(chain, uid, rule)) { 2290 try { 2291 mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid, 2292 getFirewallRuleName(chain, rule)); 2293 } catch (NativeDaemonConnectorException e) { 2294 throw e.rethrowAsParcelableException(); 2295 } 2296 } 2297 } 2298 2299 // TODO: now that netd supports batching, NMS should not keep these data structures anymore... 2300 private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) { 2301 SparseIntArray uidFirewallRules = getUidFirewallRules(chain); 2302 2303 final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT); 2304 if (DBG) { 2305 Slog.d(TAG, "oldRule = " + oldUidFirewallRule 2306 + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain); 2307 } 2308 if (oldUidFirewallRule == rule) { 2309 if (DBG) Slog.d(TAG, "!!!!! Skipping change"); 2310 // TODO: eventually consider throwing 2311 return false; 2312 } 2313 2314 String ruleName = getFirewallRuleName(chain, rule); 2315 String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule); 2316 2317 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { 2318 uidFirewallRules.delete(uid); 2319 } else { 2320 uidFirewallRules.put(uid, rule); 2321 } 2322 return !ruleName.equals(oldRuleName); 2323 } 2324 2325 private @NonNull String getFirewallRuleName(int chain, int rule) { 2326 String ruleName; 2327 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) { 2328 if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { 2329 ruleName = "allow"; 2330 } else { 2331 ruleName = "deny"; 2332 } 2333 } else { // Blacklist mode 2334 if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) { 2335 ruleName = "deny"; 2336 } else { 2337 ruleName = "allow"; 2338 } 2339 } 2340 return ruleName; 2341 } 2342 2343 private @NonNull SparseIntArray getUidFirewallRules(int chain) { 2344 switch (chain) { 2345 case FIREWALL_CHAIN_STANDBY: 2346 return mUidFirewallStandbyRules; 2347 case FIREWALL_CHAIN_DOZABLE: 2348 return mUidFirewallDozableRules; 2349 case FIREWALL_CHAIN_POWERSAVE: 2350 return mUidFirewallPowerSaveRules; 2351 case FIREWALL_CHAIN_NONE: 2352 return mUidFirewallRules; 2353 default: 2354 throw new IllegalArgumentException("Unknown chain:" + chain); 2355 } 2356 } 2357 2358 public @NonNull String getFirewallChainName(int chain) { 2359 switch (chain) { 2360 case FIREWALL_CHAIN_STANDBY: 2361 return FIREWALL_CHAIN_NAME_STANDBY; 2362 case FIREWALL_CHAIN_DOZABLE: 2363 return FIREWALL_CHAIN_NAME_DOZABLE; 2364 case FIREWALL_CHAIN_POWERSAVE: 2365 return FIREWALL_CHAIN_NAME_POWERSAVE; 2366 case FIREWALL_CHAIN_NONE: 2367 return FIREWALL_CHAIN_NAME_NONE; 2368 default: 2369 throw new IllegalArgumentException("Unknown chain:" + chain); 2370 } 2371 } 2372 2373 private static void enforceSystemUid() { 2374 final int uid = Binder.getCallingUid(); 2375 if (uid != Process.SYSTEM_UID) { 2376 throw new SecurityException("Only available to AID_SYSTEM"); 2377 } 2378 } 2379 2380 @Override 2381 public void startClatd(String interfaceName) throws IllegalStateException { 2382 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2383 2384 try { 2385 mConnector.execute("clatd", "start", interfaceName); 2386 } catch (NativeDaemonConnectorException e) { 2387 throw e.rethrowAsParcelableException(); 2388 } 2389 } 2390 2391 @Override 2392 public void stopClatd(String interfaceName) throws IllegalStateException { 2393 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2394 2395 try { 2396 mConnector.execute("clatd", "stop", interfaceName); 2397 } catch (NativeDaemonConnectorException e) { 2398 throw e.rethrowAsParcelableException(); 2399 } 2400 } 2401 2402 @Override 2403 public boolean isClatdStarted(String interfaceName) { 2404 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2405 2406 final NativeDaemonEvent event; 2407 try { 2408 event = mConnector.execute("clatd", "status", interfaceName); 2409 } catch (NativeDaemonConnectorException e) { 2410 throw e.rethrowAsParcelableException(); 2411 } 2412 2413 event.checkCode(ClatdStatusResult); 2414 return event.getMessage().endsWith("started"); 2415 } 2416 2417 @Override 2418 public void registerNetworkActivityListener(INetworkActivityListener listener) { 2419 mNetworkActivityListeners.register(listener); 2420 } 2421 2422 @Override 2423 public void unregisterNetworkActivityListener(INetworkActivityListener listener) { 2424 mNetworkActivityListeners.unregister(listener); 2425 } 2426 2427 @Override 2428 public boolean isNetworkActive() { 2429 synchronized (mNetworkActivityListeners) { 2430 return mNetworkActive || mActiveIdleTimers.isEmpty(); 2431 } 2432 } 2433 2434 private void reportNetworkActive() { 2435 final int length = mNetworkActivityListeners.beginBroadcast(); 2436 try { 2437 for (int i = 0; i < length; i++) { 2438 try { 2439 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); 2440 } catch (RemoteException | RuntimeException e) { 2441 } 2442 } 2443 } finally { 2444 mNetworkActivityListeners.finishBroadcast(); 2445 } 2446 } 2447 2448 /** {@inheritDoc} */ 2449 @Override 2450 public void monitor() { 2451 if (mConnector != null) { 2452 mConnector.monitor(); 2453 } 2454 } 2455 2456 @Override 2457 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2458 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 2459 2460 pw.println("NetworkManagementService NativeDaemonConnector Log:"); 2461 mConnector.dump(fd, pw, args); 2462 pw.println(); 2463 2464 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 2465 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio); 2466 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio); 2467 pw.print("mNetworkActive="); pw.println(mNetworkActive); 2468 2469 synchronized (mQuotaLock) { 2470 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 2471 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 2472 pw.print("Data saver mode: "); pw.println(mDataSaverMode); 2473 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered); 2474 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered); 2475 } 2476 2477 synchronized (mUidFirewallRules) { 2478 dumpUidFirewallRule(pw, "", mUidFirewallRules); 2479 } 2480 2481 pw.print("UID firewall standby chain enabled: "); pw.println( 2482 mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)); 2483 synchronized (mUidFirewallStandbyRules) { 2484 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules); 2485 } 2486 2487 pw.print("UID firewall dozable chain enabled: "); pw.println( 2488 mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)); 2489 synchronized (mUidFirewallDozableRules) { 2490 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules); 2491 } 2492 2493 pw.println("UID firewall powersave chain enabled: " + 2494 mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)); 2495 synchronized (mUidFirewallPowerSaveRules) { 2496 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules); 2497 } 2498 2499 synchronized (mIdleTimerLock) { 2500 pw.println("Idle timers:"); 2501 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { 2502 pw.print(" "); pw.print(ent.getKey()); pw.println(":"); 2503 IdleTimerParams params = ent.getValue(); 2504 pw.print(" timeout="); pw.print(params.timeout); 2505 pw.print(" type="); pw.print(params.type); 2506 pw.print(" networkCount="); pw.println(params.networkCount); 2507 } 2508 } 2509 2510 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 2511 pw.print("Netd service status: " ); 2512 if (mNetdService == null) { 2513 pw.println("disconnected"); 2514 } else { 2515 try { 2516 final boolean alive = mNetdService.isAlive(); 2517 pw.println(alive ? "alive": "dead"); 2518 } catch (RemoteException e) { 2519 pw.println("unreachable"); 2520 } 2521 } 2522 } 2523 2524 private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) { 2525 pw.print("UID bandwith control "); 2526 pw.print(name); 2527 pw.print(" rule: ["); 2528 final int size = list.size(); 2529 for (int i = 0; i < size; i++) { 2530 pw.print(list.keyAt(i)); 2531 if (i < size - 1) pw.print(","); 2532 } 2533 pw.println("]"); 2534 } 2535 2536 private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) { 2537 pw.print("UID firewall "); 2538 pw.print(name); 2539 pw.print(" rule: ["); 2540 final int size = rules.size(); 2541 for (int i = 0; i < size; i++) { 2542 pw.print(rules.keyAt(i)); 2543 pw.print(":"); 2544 pw.print(rules.valueAt(i)); 2545 if (i < size - 1) pw.print(","); 2546 } 2547 pw.println("]"); 2548 } 2549 2550 @Override 2551 public void createPhysicalNetwork(int netId, String permission) { 2552 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2553 2554 try { 2555 if (permission != null) { 2556 mConnector.execute("network", "create", netId, permission); 2557 } else { 2558 mConnector.execute("network", "create", netId); 2559 } 2560 } catch (NativeDaemonConnectorException e) { 2561 throw e.rethrowAsParcelableException(); 2562 } 2563 } 2564 2565 @Override 2566 public void createVirtualNetwork(int netId, boolean hasDNS, boolean secure) { 2567 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2568 2569 try { 2570 mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0", 2571 secure ? "1" : "0"); 2572 } catch (NativeDaemonConnectorException e) { 2573 throw e.rethrowAsParcelableException(); 2574 } 2575 } 2576 2577 @Override 2578 public void removeNetwork(int netId) { 2579 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2580 2581 try { 2582 mConnector.execute("network", "destroy", netId); 2583 } catch (NativeDaemonConnectorException e) { 2584 throw e.rethrowAsParcelableException(); 2585 } 2586 } 2587 2588 @Override 2589 public void addInterfaceToNetwork(String iface, int netId) { 2590 modifyInterfaceInNetwork("add", "" + netId, iface); 2591 } 2592 2593 @Override 2594 public void removeInterfaceFromNetwork(String iface, int netId) { 2595 modifyInterfaceInNetwork("remove", "" + netId, iface); 2596 } 2597 2598 private void modifyInterfaceInNetwork(String action, String netId, String iface) { 2599 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2600 try { 2601 mConnector.execute("network", "interface", action, netId, iface); 2602 } catch (NativeDaemonConnectorException e) { 2603 throw e.rethrowAsParcelableException(); 2604 } 2605 } 2606 2607 @Override 2608 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) { 2609 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2610 2611 final Command cmd = new Command("network", "route", "legacy", uid, "add", netId); 2612 2613 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr 2614 final LinkAddress la = routeInfo.getDestinationLinkAddress(); 2615 cmd.appendArg(routeInfo.getInterface()); 2616 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength()); 2617 if (routeInfo.hasGateway()) { 2618 cmd.appendArg(routeInfo.getGateway().getHostAddress()); 2619 } 2620 2621 try { 2622 mConnector.execute(cmd); 2623 } catch (NativeDaemonConnectorException e) { 2624 throw e.rethrowAsParcelableException(); 2625 } 2626 } 2627 2628 @Override 2629 public void setDefaultNetId(int netId) { 2630 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2631 2632 try { 2633 mConnector.execute("network", "default", "set", netId); 2634 } catch (NativeDaemonConnectorException e) { 2635 throw e.rethrowAsParcelableException(); 2636 } 2637 } 2638 2639 @Override 2640 public void clearDefaultNetId() { 2641 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2642 2643 try { 2644 mConnector.execute("network", "default", "clear"); 2645 } catch (NativeDaemonConnectorException e) { 2646 throw e.rethrowAsParcelableException(); 2647 } 2648 } 2649 2650 @Override 2651 public void setNetworkPermission(int netId, String permission) { 2652 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2653 2654 try { 2655 if (permission != null) { 2656 mConnector.execute("network", "permission", "network", "set", permission, netId); 2657 } else { 2658 mConnector.execute("network", "permission", "network", "clear", netId); 2659 } 2660 } catch (NativeDaemonConnectorException e) { 2661 throw e.rethrowAsParcelableException(); 2662 } 2663 } 2664 2665 2666 @Override 2667 public void setPermission(String permission, int[] uids) { 2668 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2669 2670 Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND]; 2671 argv[0] = "permission"; 2672 argv[1] = "user"; 2673 argv[2] = "set"; 2674 argv[3] = permission; 2675 int argc = 4; 2676 // Avoid overly long commands by limiting number of UIDs per command. 2677 for (int i = 0; i < uids.length; ++i) { 2678 argv[argc++] = uids[i]; 2679 if (i == uids.length - 1 || argc == argv.length) { 2680 try { 2681 mConnector.execute("network", Arrays.copyOf(argv, argc)); 2682 } catch (NativeDaemonConnectorException e) { 2683 throw e.rethrowAsParcelableException(); 2684 } 2685 argc = 4; 2686 } 2687 } 2688 } 2689 2690 @Override 2691 public void clearPermission(int[] uids) { 2692 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2693 2694 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 2695 argv[0] = "permission"; 2696 argv[1] = "user"; 2697 argv[2] = "clear"; 2698 int argc = 3; 2699 // Avoid overly long commands by limiting number of UIDs per command. 2700 for (int i = 0; i < uids.length; ++i) { 2701 argv[argc++] = uids[i]; 2702 if (i == uids.length - 1 || argc == argv.length) { 2703 try { 2704 mConnector.execute("network", Arrays.copyOf(argv, argc)); 2705 } catch (NativeDaemonConnectorException e) { 2706 throw e.rethrowAsParcelableException(); 2707 } 2708 argc = 3; 2709 } 2710 } 2711 } 2712 2713 @Override 2714 public void allowProtect(int uid) { 2715 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2716 2717 try { 2718 mConnector.execute("network", "protect", "allow", uid); 2719 } catch (NativeDaemonConnectorException e) { 2720 throw e.rethrowAsParcelableException(); 2721 } 2722 } 2723 2724 @Override 2725 public void denyProtect(int uid) { 2726 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2727 2728 try { 2729 mConnector.execute("network", "protect", "deny", uid); 2730 } catch (NativeDaemonConnectorException e) { 2731 throw e.rethrowAsParcelableException(); 2732 } 2733 } 2734 2735 @Override 2736 public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) { 2737 modifyInterfaceInNetwork("add", "local", iface); 2738 2739 for (RouteInfo route : routes) { 2740 if (!route.isDefaultRoute()) { 2741 modifyRoute("add", "local", route); 2742 } 2743 } 2744 } 2745 2746 @Override 2747 public void removeInterfaceFromLocalNetwork(String iface) { 2748 modifyInterfaceInNetwork("remove", "local", iface); 2749 } 2750} 2751