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