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