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