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