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