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