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