1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import static android.Manifest.permission.CONNECTIVITY_INTERNAL; 20 import static android.Manifest.permission.DUMP; 21 import static android.Manifest.permission.SHUTDOWN; 22 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE; 23 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE; 24 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE; 25 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE; 26 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY; 27 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE; 28 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE; 29 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY; 30 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; 31 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST; 32 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST; 33 import static android.net.NetworkStats.SET_DEFAULT; 34 import static android.net.NetworkStats.TAG_ALL; 35 import static android.net.NetworkStats.TAG_NONE; 36 import static android.net.NetworkStats.UID_ALL; 37 import static android.net.TrafficStats.UID_TETHERING; 38 import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult; 39 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult; 40 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult; 41 import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult; 42 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult; 43 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult; 44 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult; 45 import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult; 46 import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult; 47 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; 48 import android.annotation.NonNull; 49 import android.app.ActivityManagerNative; 50 import android.content.ContentResolver; 51 import android.content.Context; 52 import android.net.ConnectivityManager; 53 import android.net.INetd; 54 import android.net.INetworkManagementEventObserver; 55 import android.net.InterfaceConfiguration; 56 import android.net.IpPrefix; 57 import android.net.LinkAddress; 58 import android.net.Network; 59 import android.net.NetworkPolicyManager; 60 import android.net.NetworkStats; 61 import android.net.NetworkUtils; 62 import android.net.RouteInfo; 63 import android.net.UidRange; 64 import android.net.wifi.WifiConfiguration; 65 import android.net.wifi.WifiConfiguration.KeyMgmt; 66 import android.os.BatteryStats; 67 import android.os.Binder; 68 import android.os.Handler; 69 import android.os.INetworkActivityListener; 70 import android.os.INetworkManagementService; 71 import android.os.PowerManager; 72 import android.os.Process; 73 import android.os.RemoteCallbackList; 74 import android.os.RemoteException; 75 import android.os.ServiceManager; 76 import android.os.ServiceSpecificException; 77 import android.os.StrictMode; 78 import android.os.SystemClock; 79 import android.os.SystemProperties; 80 import android.provider.Settings; 81 import android.telephony.DataConnectionRealTimeInfo; 82 import android.telephony.PhoneStateListener; 83 import android.telephony.SubscriptionManager; 84 import android.telephony.TelephonyManager; 85 import android.util.Log; 86 import android.util.Slog; 87 import android.util.SparseBooleanArray; 88 import android.util.SparseIntArray; 89 90 import com.android.internal.annotations.GuardedBy; 91 import com.android.internal.app.IBatteryStats; 92 import com.android.internal.net.NetworkStatsFactory; 93 import com.android.internal.util.HexDump; 94 import com.android.internal.util.Preconditions; 95 import com.android.server.NativeDaemonConnector.Command; 96 import com.android.server.NativeDaemonConnector.SensitiveArg; 97 import com.android.server.net.LockdownVpnTracker; 98 import com.google.android.collect.Maps; 99 100 import java.io.BufferedReader; 101 import java.io.DataInputStream; 102 import java.io.File; 103 import java.io.FileDescriptor; 104 import java.io.FileInputStream; 105 import java.io.IOException; 106 import java.io.InputStreamReader; 107 import java.io.PrintWriter; 108 import java.net.InetAddress; 109 import java.net.InterfaceAddress; 110 import java.net.NetworkInterface; 111 import java.net.SocketException; 112 import java.util.ArrayList; 113 import java.util.Arrays; 114 import java.util.HashMap; 115 import java.util.List; 116 import java.util.Map; 117 import java.util.NoSuchElementException; 118 import java.util.StringTokenizer; 119 import java.util.concurrent.CountDownLatch; 120 121 /** 122 * @hide 123 */ 124 public class NetworkManagementService extends INetworkManagementService.Stub 125 implements Watchdog.Monitor { 126 private static final String TAG = "NetworkManagement"; 127 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); 128 private static final String NETD_TAG = "NetdConnector"; 129 private static final String NETD_SERVICE_NAME = "netd"; 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 setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges) 1854 throws ServiceSpecificException { 1855 try { 1856 mNetdService.networkRejectNonSecureVpn(add, uidRanges); 1857 } catch (ServiceSpecificException e) { 1858 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")" 1859 + ": netd command failed", e); 1860 throw e; 1861 } catch (RemoteException e) { 1862 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")" 1863 + ": netd command failed", e); 1864 throw e.rethrowAsRuntimeException(); 1865 } 1866 } 1867 1868 @Override 1869 public void setUidCleartextNetworkPolicy(int uid, int policy) { 1870 if (Binder.getCallingUid() != uid) { 1871 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1872 } 1873 1874 synchronized (mQuotaLock) { 1875 final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT); 1876 if (oldPolicy == policy) { 1877 return; 1878 } 1879 1880 if (!mStrictEnabled) { 1881 // Module isn't enabled yet; stash the requested policy away to 1882 // apply later once the daemon is connected. 1883 mUidCleartextPolicy.put(uid, policy); 1884 return; 1885 } 1886 1887 final String policyString; 1888 switch (policy) { 1889 case StrictMode.NETWORK_POLICY_ACCEPT: 1890 policyString = "accept"; 1891 break; 1892 case StrictMode.NETWORK_POLICY_LOG: 1893 policyString = "log"; 1894 break; 1895 case StrictMode.NETWORK_POLICY_REJECT: 1896 policyString = "reject"; 1897 break; 1898 default: 1899 throw new IllegalArgumentException("Unknown policy " + policy); 1900 } 1901 1902 try { 1903 mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString); 1904 mUidCleartextPolicy.put(uid, policy); 1905 } catch (NativeDaemonConnectorException e) { 1906 throw e.rethrowAsParcelableException(); 1907 } 1908 } 1909 } 1910 1911 @Override 1912 public boolean isBandwidthControlEnabled() { 1913 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1914 return mBandwidthControlEnabled; 1915 } 1916 1917 @Override 1918 public NetworkStats getNetworkStatsUidDetail(int uid) { 1919 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1920 try { 1921 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null); 1922 } catch (IOException e) { 1923 throw new IllegalStateException(e); 1924 } 1925 } 1926 1927 @Override 1928 public NetworkStats getNetworkStatsTethering() { 1929 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1930 1931 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1932 try { 1933 final NativeDaemonEvent[] events = mConnector.executeForList( 1934 "bandwidth", "gettetherstats"); 1935 for (NativeDaemonEvent event : events) { 1936 if (event.getCode() != TetheringStatsListResult) continue; 1937 1938 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets 1939 final StringTokenizer tok = new StringTokenizer(event.getMessage()); 1940 try { 1941 final String ifaceIn = tok.nextToken(); 1942 final String ifaceOut = tok.nextToken(); 1943 1944 final NetworkStats.Entry entry = new NetworkStats.Entry(); 1945 entry.iface = ifaceOut; 1946 entry.uid = UID_TETHERING; 1947 entry.set = SET_DEFAULT; 1948 entry.tag = TAG_NONE; 1949 entry.rxBytes = Long.parseLong(tok.nextToken()); 1950 entry.rxPackets = Long.parseLong(tok.nextToken()); 1951 entry.txBytes = Long.parseLong(tok.nextToken()); 1952 entry.txPackets = Long.parseLong(tok.nextToken()); 1953 stats.combineValues(entry); 1954 } catch (NoSuchElementException e) { 1955 throw new IllegalStateException("problem parsing tethering stats: " + event); 1956 } catch (NumberFormatException e) { 1957 throw new IllegalStateException("problem parsing tethering stats: " + event); 1958 } 1959 } 1960 } catch (NativeDaemonConnectorException e) { 1961 throw e.rethrowAsParcelableException(); 1962 } 1963 return stats; 1964 } 1965 1966 @Override 1967 public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) { 1968 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1969 1970 ContentResolver resolver = mContext.getContentResolver(); 1971 1972 int sampleValidity = Settings.Global.getInt(resolver, 1973 Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS, 1974 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS); 1975 if (sampleValidity < 0 || sampleValidity > 65535) { 1976 Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" + 1977 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS); 1978 sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS; 1979 } 1980 1981 int successThreshold = Settings.Global.getInt(resolver, 1982 Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT, 1983 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT); 1984 if (successThreshold < 0 || successThreshold > 100) { 1985 Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" + 1986 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT); 1987 successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT; 1988 } 1989 1990 int minSamples = Settings.Global.getInt(resolver, 1991 Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES); 1992 int maxSamples = Settings.Global.getInt(resolver, 1993 Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES); 1994 if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) { 1995 Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples + 1996 "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " + 1997 DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")"); 1998 minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES; 1999 maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES; 2000 } 2001 2002 final String[] domainStrs = domains == null ? new String[0] : domains.split(" "); 2003 final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples }; 2004 try { 2005 mNetdService.setResolverConfiguration(netId, servers, domainStrs, params); 2006 } catch (RemoteException e) { 2007 throw new RuntimeException(e); 2008 } 2009 } 2010 2011 @Override 2012 public void setDnsServersForNetwork(int netId, String[] servers, String domains) { 2013 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2014 2015 Command cmd; 2016 if (servers.length > 0) { 2017 cmd = new Command("resolver", "setnetdns", netId, 2018 (domains == null ? "" : domains)); 2019 for (String s : servers) { 2020 InetAddress a = NetworkUtils.numericToInetAddress(s); 2021 if (a.isAnyLocalAddress() == false) { 2022 cmd.appendArg(a.getHostAddress()); 2023 } 2024 } 2025 } else { 2026 cmd = new Command("resolver", "clearnetdns", netId); 2027 } 2028 2029 try { 2030 mConnector.execute(cmd); 2031 } catch (NativeDaemonConnectorException e) { 2032 throw e.rethrowAsParcelableException(); 2033 } 2034 } 2035 2036 @Override 2037 public void addVpnUidRanges(int netId, UidRange[] ranges) { 2038 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2039 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 2040 argv[0] = "users"; 2041 argv[1] = "add"; 2042 argv[2] = netId; 2043 int argc = 3; 2044 // Avoid overly long commands by limiting number of UID ranges per command. 2045 for (int i = 0; i < ranges.length; i++) { 2046 argv[argc++] = ranges[i].toString(); 2047 if (i == (ranges.length - 1) || argc == argv.length) { 2048 try { 2049 mConnector.execute("network", Arrays.copyOf(argv, argc)); 2050 } catch (NativeDaemonConnectorException e) { 2051 throw e.rethrowAsParcelableException(); 2052 } 2053 argc = 3; 2054 } 2055 } 2056 } 2057 2058 @Override 2059 public void removeVpnUidRanges(int netId, UidRange[] ranges) { 2060 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2061 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 2062 argv[0] = "users"; 2063 argv[1] = "remove"; 2064 argv[2] = netId; 2065 int argc = 3; 2066 // Avoid overly long commands by limiting number of UID ranges per command. 2067 for (int i = 0; i < ranges.length; i++) { 2068 argv[argc++] = ranges[i].toString(); 2069 if (i == (ranges.length - 1) || argc == argv.length) { 2070 try { 2071 mConnector.execute("network", Arrays.copyOf(argv, argc)); 2072 } catch (NativeDaemonConnectorException e) { 2073 throw e.rethrowAsParcelableException(); 2074 } 2075 argc = 3; 2076 } 2077 } 2078 } 2079 2080 @Override 2081 public void setFirewallEnabled(boolean enabled) { 2082 enforceSystemUid(); 2083 try { 2084 mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist"); 2085 mFirewallEnabled = enabled; 2086 } catch (NativeDaemonConnectorException e) { 2087 throw e.rethrowAsParcelableException(); 2088 } 2089 } 2090 2091 @Override 2092 public boolean isFirewallEnabled() { 2093 enforceSystemUid(); 2094 return mFirewallEnabled; 2095 } 2096 2097 @Override 2098 public void setFirewallInterfaceRule(String iface, boolean allow) { 2099 enforceSystemUid(); 2100 Preconditions.checkState(mFirewallEnabled); 2101 final String rule = allow ? "allow" : "deny"; 2102 try { 2103 mConnector.execute("firewall", "set_interface_rule", iface, rule); 2104 } catch (NativeDaemonConnectorException e) { 2105 throw e.rethrowAsParcelableException(); 2106 } 2107 } 2108 2109 @Override 2110 public void setFirewallEgressSourceRule(String addr, boolean allow) { 2111 enforceSystemUid(); 2112 Preconditions.checkState(mFirewallEnabled); 2113 final String rule = allow ? "allow" : "deny"; 2114 try { 2115 mConnector.execute("firewall", "set_egress_source_rule", addr, rule); 2116 } catch (NativeDaemonConnectorException e) { 2117 throw e.rethrowAsParcelableException(); 2118 } 2119 } 2120 2121 @Override 2122 public void setFirewallEgressDestRule(String addr, int port, boolean allow) { 2123 enforceSystemUid(); 2124 Preconditions.checkState(mFirewallEnabled); 2125 final String rule = allow ? "allow" : "deny"; 2126 try { 2127 mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule); 2128 } catch (NativeDaemonConnectorException e) { 2129 throw e.rethrowAsParcelableException(); 2130 } 2131 } 2132 2133 private void closeSocketsForFirewallChainLocked(int chain, String chainName) { 2134 // UID ranges to close sockets on. 2135 UidRange[] ranges; 2136 // UID ranges whose sockets we won't touch. 2137 int[] exemptUids; 2138 2139 final SparseIntArray rules = getUidFirewallRules(chain); 2140 int numUids = 0; 2141 2142 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) { 2143 // Close all sockets on all non-system UIDs... 2144 ranges = new UidRange[] { 2145 // TODO: is there a better way of finding all existing users? If so, we could 2146 // specify their ranges here. 2147 new UidRange(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE), 2148 }; 2149 // ... except for the UIDs that have allow rules. 2150 exemptUids = new int[rules.size()]; 2151 for (int i = 0; i < exemptUids.length; i++) { 2152 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { 2153 exemptUids[numUids] = rules.keyAt(i); 2154 numUids++; 2155 } 2156 } 2157 // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length. 2158 // But the code does not guarantee this in any way, and at least in one case - if we add 2159 // a UID rule to the firewall, and then disable the firewall - the chains can contain 2160 // the wrong type of rule. In this case, don't close connections that we shouldn't. 2161 // 2162 // TODO: tighten up this code by ensuring we never set the wrong type of rule, and 2163 // fix setFirewallEnabled to grab mQuotaLock and clear rules. 2164 if (numUids != exemptUids.length) { 2165 exemptUids = Arrays.copyOf(exemptUids, numUids); 2166 } 2167 } else { 2168 // Close sockets for every UID that has a deny rule... 2169 ranges = new UidRange[rules.size()]; 2170 for (int i = 0; i < ranges.length; i++) { 2171 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_DENY) { 2172 int uid = rules.keyAt(i); 2173 ranges[numUids] = new UidRange(uid, uid); 2174 numUids++; 2175 } 2176 } 2177 // As above; usually numUids == ranges.length, but not always. 2178 if (numUids != ranges.length) { 2179 ranges = Arrays.copyOf(ranges, numUids); 2180 } 2181 // ... with no exceptions. 2182 exemptUids = new int[0]; 2183 } 2184 2185 try { 2186 mNetdService.socketDestroy(ranges, exemptUids); 2187 } catch(RemoteException | ServiceSpecificException e) { 2188 Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e); 2189 } 2190 } 2191 2192 @Override 2193 public void setFirewallChainEnabled(int chain, boolean enable) { 2194 enforceSystemUid(); 2195 synchronized (mQuotaLock) { 2196 if (mFirewallChainStates.get(chain) == enable) { 2197 // All is the same, nothing to do. This relies on the fact that netd has child 2198 // chains default detached. 2199 return; 2200 } 2201 mFirewallChainStates.put(chain, enable); 2202 2203 final String operation = enable ? "enable_chain" : "disable_chain"; 2204 final String chainName; 2205 switch(chain) { 2206 case FIREWALL_CHAIN_STANDBY: 2207 chainName = FIREWALL_CHAIN_NAME_STANDBY; 2208 break; 2209 case FIREWALL_CHAIN_DOZABLE: 2210 chainName = FIREWALL_CHAIN_NAME_DOZABLE; 2211 break; 2212 case FIREWALL_CHAIN_POWERSAVE: 2213 chainName = FIREWALL_CHAIN_NAME_POWERSAVE; 2214 break; 2215 default: 2216 throw new IllegalArgumentException("Bad child chain: " + chain); 2217 } 2218 2219 try { 2220 mConnector.execute("firewall", operation, chainName); 2221 } catch (NativeDaemonConnectorException e) { 2222 throw e.rethrowAsParcelableException(); 2223 } 2224 2225 // Close any sockets that were opened by the affected UIDs. This has to be done after 2226 // disabling network connectivity, in case they react to the socket close by reopening 2227 // the connection and race with the iptables commands that enable the firewall. All 2228 // whitelist and blacklist chains allow RSTs through. 2229 if (enable) { 2230 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName); 2231 closeSocketsForFirewallChainLocked(chain, chainName); 2232 } 2233 } 2234 } 2235 2236 private int getFirewallType(int chain) { 2237 switch (chain) { 2238 case FIREWALL_CHAIN_STANDBY: 2239 return FIREWALL_TYPE_BLACKLIST; 2240 case FIREWALL_CHAIN_DOZABLE: 2241 return FIREWALL_TYPE_WHITELIST; 2242 case FIREWALL_CHAIN_POWERSAVE: 2243 return FIREWALL_TYPE_WHITELIST; 2244 default: 2245 return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST; 2246 } 2247 } 2248 2249 @Override 2250 public void setFirewallUidRules(int chain, int[] uids, int[] rules) { 2251 enforceSystemUid(); 2252 synchronized (mQuotaLock) { 2253 SparseIntArray uidFirewallRules = getUidFirewallRules(chain); 2254 SparseIntArray newRules = new SparseIntArray(); 2255 // apply new set of rules 2256 for (int index = uids.length - 1; index >= 0; --index) { 2257 int uid = uids[index]; 2258 int rule = rules[index]; 2259 updateFirewallUidRuleLocked(chain, uid, rule); 2260 newRules.put(uid, rule); 2261 } 2262 // collect the rules to remove. 2263 SparseIntArray rulesToRemove = new SparseIntArray(); 2264 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) { 2265 int uid = uidFirewallRules.keyAt(index); 2266 if (newRules.indexOfKey(uid) < 0) { 2267 rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT); 2268 } 2269 } 2270 // remove dead rules 2271 for (int index = rulesToRemove.size() - 1; index >= 0; --index) { 2272 int uid = rulesToRemove.keyAt(index); 2273 updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT); 2274 } 2275 try { 2276 switch (chain) { 2277 case FIREWALL_CHAIN_DOZABLE: 2278 mNetdService.firewallReplaceUidChain("fw_dozable", true, uids); 2279 break; 2280 case FIREWALL_CHAIN_STANDBY: 2281 mNetdService.firewallReplaceUidChain("fw_standby", false, uids); 2282 break; 2283 case FIREWALL_CHAIN_POWERSAVE: 2284 mNetdService.firewallReplaceUidChain("fw_powersave", true, uids); 2285 break; 2286 case FIREWALL_CHAIN_NONE: 2287 default: 2288 Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain); 2289 } 2290 } catch (RemoteException e) { 2291 Slog.w(TAG, "Error flushing firewall chain " + chain, e); 2292 } 2293 } 2294 } 2295 2296 @Override 2297 public void setFirewallUidRule(int chain, int uid, int rule) { 2298 enforceSystemUid(); 2299 synchronized (mQuotaLock) { 2300 setFirewallUidRuleLocked(chain, uid, rule); 2301 } 2302 } 2303 2304 private void setFirewallUidRuleLocked(int chain, int uid, int rule) { 2305 if (updateFirewallUidRuleLocked(chain, uid, rule)) { 2306 try { 2307 mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid, 2308 getFirewallRuleName(chain, rule)); 2309 } catch (NativeDaemonConnectorException e) { 2310 throw e.rethrowAsParcelableException(); 2311 } 2312 } 2313 } 2314 2315 // TODO: now that netd supports batching, NMS should not keep these data structures anymore... 2316 private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) { 2317 SparseIntArray uidFirewallRules = getUidFirewallRules(chain); 2318 2319 final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT); 2320 if (DBG) { 2321 Slog.d(TAG, "oldRule = " + oldUidFirewallRule 2322 + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain); 2323 } 2324 if (oldUidFirewallRule == rule) { 2325 if (DBG) Slog.d(TAG, "!!!!! Skipping change"); 2326 // TODO: eventually consider throwing 2327 return false; 2328 } 2329 2330 String ruleName = getFirewallRuleName(chain, rule); 2331 String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule); 2332 2333 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { 2334 uidFirewallRules.delete(uid); 2335 } else { 2336 uidFirewallRules.put(uid, rule); 2337 } 2338 return !ruleName.equals(oldRuleName); 2339 } 2340 2341 private @NonNull String getFirewallRuleName(int chain, int rule) { 2342 String ruleName; 2343 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) { 2344 if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { 2345 ruleName = "allow"; 2346 } else { 2347 ruleName = "deny"; 2348 } 2349 } else { // Blacklist mode 2350 if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) { 2351 ruleName = "deny"; 2352 } else { 2353 ruleName = "allow"; 2354 } 2355 } 2356 return ruleName; 2357 } 2358 2359 private @NonNull SparseIntArray getUidFirewallRules(int chain) { 2360 switch (chain) { 2361 case FIREWALL_CHAIN_STANDBY: 2362 return mUidFirewallStandbyRules; 2363 case FIREWALL_CHAIN_DOZABLE: 2364 return mUidFirewallDozableRules; 2365 case FIREWALL_CHAIN_POWERSAVE: 2366 return mUidFirewallPowerSaveRules; 2367 case FIREWALL_CHAIN_NONE: 2368 return mUidFirewallRules; 2369 default: 2370 throw new IllegalArgumentException("Unknown chain:" + chain); 2371 } 2372 } 2373 2374 public @NonNull String getFirewallChainName(int chain) { 2375 switch (chain) { 2376 case FIREWALL_CHAIN_STANDBY: 2377 return FIREWALL_CHAIN_NAME_STANDBY; 2378 case FIREWALL_CHAIN_DOZABLE: 2379 return FIREWALL_CHAIN_NAME_DOZABLE; 2380 case FIREWALL_CHAIN_POWERSAVE: 2381 return FIREWALL_CHAIN_NAME_POWERSAVE; 2382 case FIREWALL_CHAIN_NONE: 2383 return FIREWALL_CHAIN_NAME_NONE; 2384 default: 2385 throw new IllegalArgumentException("Unknown chain:" + chain); 2386 } 2387 } 2388 2389 private static void enforceSystemUid() { 2390 final int uid = Binder.getCallingUid(); 2391 if (uid != Process.SYSTEM_UID) { 2392 throw new SecurityException("Only available to AID_SYSTEM"); 2393 } 2394 } 2395 2396 @Override 2397 public void startClatd(String interfaceName) throws IllegalStateException { 2398 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2399 2400 try { 2401 mConnector.execute("clatd", "start", interfaceName); 2402 } catch (NativeDaemonConnectorException e) { 2403 throw e.rethrowAsParcelableException(); 2404 } 2405 } 2406 2407 @Override 2408 public void stopClatd(String interfaceName) throws IllegalStateException { 2409 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2410 2411 try { 2412 mConnector.execute("clatd", "stop", interfaceName); 2413 } catch (NativeDaemonConnectorException e) { 2414 throw e.rethrowAsParcelableException(); 2415 } 2416 } 2417 2418 @Override 2419 public boolean isClatdStarted(String interfaceName) { 2420 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2421 2422 final NativeDaemonEvent event; 2423 try { 2424 event = mConnector.execute("clatd", "status", interfaceName); 2425 } catch (NativeDaemonConnectorException e) { 2426 throw e.rethrowAsParcelableException(); 2427 } 2428 2429 event.checkCode(ClatdStatusResult); 2430 return event.getMessage().endsWith("started"); 2431 } 2432 2433 @Override 2434 public void registerNetworkActivityListener(INetworkActivityListener listener) { 2435 mNetworkActivityListeners.register(listener); 2436 } 2437 2438 @Override 2439 public void unregisterNetworkActivityListener(INetworkActivityListener listener) { 2440 mNetworkActivityListeners.unregister(listener); 2441 } 2442 2443 @Override 2444 public boolean isNetworkActive() { 2445 synchronized (mNetworkActivityListeners) { 2446 return mNetworkActive || mActiveIdleTimers.isEmpty(); 2447 } 2448 } 2449 2450 private void reportNetworkActive() { 2451 final int length = mNetworkActivityListeners.beginBroadcast(); 2452 try { 2453 for (int i = 0; i < length; i++) { 2454 try { 2455 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); 2456 } catch (RemoteException | RuntimeException e) { 2457 } 2458 } 2459 } finally { 2460 mNetworkActivityListeners.finishBroadcast(); 2461 } 2462 } 2463 2464 /** {@inheritDoc} */ 2465 @Override 2466 public void monitor() { 2467 if (mConnector != null) { 2468 mConnector.monitor(); 2469 } 2470 } 2471 2472 @Override 2473 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2474 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 2475 2476 pw.println("NetworkManagementService NativeDaemonConnector Log:"); 2477 mConnector.dump(fd, pw, args); 2478 pw.println(); 2479 2480 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 2481 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio); 2482 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio); 2483 pw.print("mNetworkActive="); pw.println(mNetworkActive); 2484 2485 synchronized (mQuotaLock) { 2486 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 2487 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 2488 pw.print("Data saver mode: "); pw.println(mDataSaverMode); 2489 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered); 2490 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered); 2491 } 2492 2493 synchronized (mUidFirewallRules) { 2494 dumpUidFirewallRule(pw, "", mUidFirewallRules); 2495 } 2496 2497 pw.print("UID firewall standby chain enabled: "); pw.println( 2498 mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)); 2499 synchronized (mUidFirewallStandbyRules) { 2500 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules); 2501 } 2502 2503 pw.print("UID firewall dozable chain enabled: "); pw.println( 2504 mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)); 2505 synchronized (mUidFirewallDozableRules) { 2506 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules); 2507 } 2508 2509 pw.println("UID firewall powersave chain enabled: " + 2510 mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)); 2511 synchronized (mUidFirewallPowerSaveRules) { 2512 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules); 2513 } 2514 2515 synchronized (mIdleTimerLock) { 2516 pw.println("Idle timers:"); 2517 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { 2518 pw.print(" "); pw.print(ent.getKey()); pw.println(":"); 2519 IdleTimerParams params = ent.getValue(); 2520 pw.print(" timeout="); pw.print(params.timeout); 2521 pw.print(" type="); pw.print(params.type); 2522 pw.print(" networkCount="); pw.println(params.networkCount); 2523 } 2524 } 2525 2526 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 2527 pw.print("Netd service status: " ); 2528 if (mNetdService == null) { 2529 pw.println("disconnected"); 2530 } else { 2531 try { 2532 final boolean alive = mNetdService.isAlive(); 2533 pw.println(alive ? "alive": "dead"); 2534 } catch (RemoteException e) { 2535 pw.println("unreachable"); 2536 } 2537 } 2538 } 2539 2540 private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) { 2541 pw.print("UID bandwith control "); 2542 pw.print(name); 2543 pw.print(" rule: ["); 2544 final int size = list.size(); 2545 for (int i = 0; i < size; i++) { 2546 pw.print(list.keyAt(i)); 2547 if (i < size - 1) pw.print(","); 2548 } 2549 pw.println("]"); 2550 } 2551 2552 private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) { 2553 pw.print("UID firewall "); 2554 pw.print(name); 2555 pw.print(" rule: ["); 2556 final int size = rules.size(); 2557 for (int i = 0; i < size; i++) { 2558 pw.print(rules.keyAt(i)); 2559 pw.print(":"); 2560 pw.print(rules.valueAt(i)); 2561 if (i < size - 1) pw.print(","); 2562 } 2563 pw.println("]"); 2564 } 2565 2566 @Override 2567 public void createPhysicalNetwork(int netId, String permission) { 2568 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2569 2570 try { 2571 if (permission != null) { 2572 mConnector.execute("network", "create", netId, permission); 2573 } else { 2574 mConnector.execute("network", "create", netId); 2575 } 2576 } catch (NativeDaemonConnectorException e) { 2577 throw e.rethrowAsParcelableException(); 2578 } 2579 } 2580 2581 @Override 2582 public void createVirtualNetwork(int netId, boolean hasDNS, boolean secure) { 2583 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2584 2585 try { 2586 mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0", 2587 secure ? "1" : "0"); 2588 } catch (NativeDaemonConnectorException e) { 2589 throw e.rethrowAsParcelableException(); 2590 } 2591 } 2592 2593 @Override 2594 public void removeNetwork(int netId) { 2595 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2596 2597 try { 2598 mConnector.execute("network", "destroy", netId); 2599 } catch (NativeDaemonConnectorException e) { 2600 throw e.rethrowAsParcelableException(); 2601 } 2602 } 2603 2604 @Override 2605 public void addInterfaceToNetwork(String iface, int netId) { 2606 modifyInterfaceInNetwork("add", "" + netId, iface); 2607 } 2608 2609 @Override 2610 public void removeInterfaceFromNetwork(String iface, int netId) { 2611 modifyInterfaceInNetwork("remove", "" + netId, iface); 2612 } 2613 2614 private void modifyInterfaceInNetwork(String action, String netId, String iface) { 2615 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2616 try { 2617 mConnector.execute("network", "interface", action, netId, iface); 2618 } catch (NativeDaemonConnectorException e) { 2619 throw e.rethrowAsParcelableException(); 2620 } 2621 } 2622 2623 @Override 2624 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) { 2625 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2626 2627 final Command cmd = new Command("network", "route", "legacy", uid, "add", netId); 2628 2629 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr 2630 final LinkAddress la = routeInfo.getDestinationLinkAddress(); 2631 cmd.appendArg(routeInfo.getInterface()); 2632 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength()); 2633 if (routeInfo.hasGateway()) { 2634 cmd.appendArg(routeInfo.getGateway().getHostAddress()); 2635 } 2636 2637 try { 2638 mConnector.execute(cmd); 2639 } catch (NativeDaemonConnectorException e) { 2640 throw e.rethrowAsParcelableException(); 2641 } 2642 } 2643 2644 @Override 2645 public void setDefaultNetId(int netId) { 2646 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2647 2648 try { 2649 mConnector.execute("network", "default", "set", netId); 2650 } catch (NativeDaemonConnectorException e) { 2651 throw e.rethrowAsParcelableException(); 2652 } 2653 } 2654 2655 @Override 2656 public void clearDefaultNetId() { 2657 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2658 2659 try { 2660 mConnector.execute("network", "default", "clear"); 2661 } catch (NativeDaemonConnectorException e) { 2662 throw e.rethrowAsParcelableException(); 2663 } 2664 } 2665 2666 @Override 2667 public void setNetworkPermission(int netId, String permission) { 2668 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2669 2670 try { 2671 if (permission != null) { 2672 mConnector.execute("network", "permission", "network", "set", permission, netId); 2673 } else { 2674 mConnector.execute("network", "permission", "network", "clear", netId); 2675 } 2676 } catch (NativeDaemonConnectorException e) { 2677 throw e.rethrowAsParcelableException(); 2678 } 2679 } 2680 2681 2682 @Override 2683 public void setPermission(String permission, int[] uids) { 2684 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2685 2686 Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND]; 2687 argv[0] = "permission"; 2688 argv[1] = "user"; 2689 argv[2] = "set"; 2690 argv[3] = permission; 2691 int argc = 4; 2692 // Avoid overly long commands by limiting number of UIDs per command. 2693 for (int i = 0; i < uids.length; ++i) { 2694 argv[argc++] = uids[i]; 2695 if (i == uids.length - 1 || argc == argv.length) { 2696 try { 2697 mConnector.execute("network", Arrays.copyOf(argv, argc)); 2698 } catch (NativeDaemonConnectorException e) { 2699 throw e.rethrowAsParcelableException(); 2700 } 2701 argc = 4; 2702 } 2703 } 2704 } 2705 2706 @Override 2707 public void clearPermission(int[] uids) { 2708 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2709 2710 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 2711 argv[0] = "permission"; 2712 argv[1] = "user"; 2713 argv[2] = "clear"; 2714 int argc = 3; 2715 // Avoid overly long commands by limiting number of UIDs per command. 2716 for (int i = 0; i < uids.length; ++i) { 2717 argv[argc++] = uids[i]; 2718 if (i == uids.length - 1 || argc == argv.length) { 2719 try { 2720 mConnector.execute("network", Arrays.copyOf(argv, argc)); 2721 } catch (NativeDaemonConnectorException e) { 2722 throw e.rethrowAsParcelableException(); 2723 } 2724 argc = 3; 2725 } 2726 } 2727 } 2728 2729 @Override 2730 public void allowProtect(int uid) { 2731 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2732 2733 try { 2734 mConnector.execute("network", "protect", "allow", uid); 2735 } catch (NativeDaemonConnectorException e) { 2736 throw e.rethrowAsParcelableException(); 2737 } 2738 } 2739 2740 @Override 2741 public void denyProtect(int uid) { 2742 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2743 2744 try { 2745 mConnector.execute("network", "protect", "deny", uid); 2746 } catch (NativeDaemonConnectorException e) { 2747 throw e.rethrowAsParcelableException(); 2748 } 2749 } 2750 2751 @Override 2752 public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) { 2753 modifyInterfaceInNetwork("add", "local", iface); 2754 2755 for (RouteInfo route : routes) { 2756 if (!route.isDefaultRoute()) { 2757 modifyRoute("add", "local", route); 2758 } 2759 } 2760 } 2761 2762 @Override 2763 public void removeInterfaceFromLocalNetwork(String iface) { 2764 modifyInterfaceInNetwork("remove", "local", iface); 2765 } 2766 } 2767