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