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