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