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