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