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