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