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