NetworkManagementService.java revision a1bd79268be693f04f4adee90673d6ed400cc9fd
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, long tsNanos) { 350 try { 351 getBatteryStats().noteDataConnectionActive(type, active, tsNanos); 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, tsNanos); 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 long timestampNanos = 0; 575 if (cooked.length == 5) { 576 try { 577 timestampNanos = Long.parseLong(cooked[4]); 578 } catch(NumberFormatException ne) {} 579 } 580 boolean isActive = cooked[2].equals("active"); 581 notifyInterfaceClassActivity(Integer.parseInt(cooked[3]), 582 isActive, timestampNanos); 583 return true; 584 // break; 585 case NetdResponseCode.InterfaceAddressChange: 586 /* 587 * A network address change occurred 588 * Format: "NNN Address updated <addr> <iface> <flags> <scope>" 589 * "NNN Address removed <addr> <iface> <flags> <scope>" 590 */ 591 if (cooked.length < 7 || !cooked[1].equals("Address")) { 592 throw new IllegalStateException(errorMessage); 593 } 594 595 String iface = cooked[4]; 596 LinkAddress address; 597 try { 598 int flags = Integer.parseInt(cooked[5]); 599 int scope = Integer.parseInt(cooked[6]); 600 address = new LinkAddress(cooked[3], flags, scope); 601 } catch(NumberFormatException e) { // Non-numeric lifetime or scope. 602 throw new IllegalStateException(errorMessage, e); 603 } catch(IllegalArgumentException e) { // Malformed/invalid IP address. 604 throw new IllegalStateException(errorMessage, e); 605 } 606 607 if (cooked[2].equals("updated")) { 608 notifyAddressUpdated(iface, address); 609 } else { 610 notifyAddressRemoved(iface, address); 611 } 612 return true; 613 // break; 614 case NetdResponseCode.InterfaceDnsServerInfo: 615 /* 616 * Information about available DNS servers has been received. 617 * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>" 618 */ 619 long lifetime; // Actually a 32-bit unsigned integer. 620 621 if (cooked.length == 6 && 622 cooked[1].equals("DnsInfo") && 623 cooked[2].equals("servers")) { 624 try { 625 lifetime = Long.parseLong(cooked[4]); 626 } catch (NumberFormatException e) { 627 throw new IllegalStateException(errorMessage); 628 } 629 String[] servers = cooked[5].split(","); 630 notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers); 631 } 632 return true; 633 // break; 634 default: break; 635 } 636 return false; 637 } 638 } 639 640 641 // 642 // INetworkManagementService members 643 // 644 645 @Override 646 public String[] listInterfaces() { 647 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 648 try { 649 return NativeDaemonEvent.filterMessageList( 650 mConnector.executeForList("interface", "list"), InterfaceListResult); 651 } catch (NativeDaemonConnectorException e) { 652 throw e.rethrowAsParcelableException(); 653 } 654 } 655 656 @Override 657 public InterfaceConfiguration getInterfaceConfig(String iface) { 658 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 659 660 final NativeDaemonEvent event; 661 try { 662 event = mConnector.execute("interface", "getcfg", iface); 663 } catch (NativeDaemonConnectorException e) { 664 throw e.rethrowAsParcelableException(); 665 } 666 667 event.checkCode(InterfaceGetCfgResult); 668 669 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3 670 final StringTokenizer st = new StringTokenizer(event.getMessage()); 671 672 InterfaceConfiguration cfg; 673 try { 674 cfg = new InterfaceConfiguration(); 675 cfg.setHardwareAddress(st.nextToken(" ")); 676 InetAddress addr = null; 677 int prefixLength = 0; 678 try { 679 addr = NetworkUtils.numericToInetAddress(st.nextToken()); 680 } catch (IllegalArgumentException iae) { 681 Slog.e(TAG, "Failed to parse ipaddr", iae); 682 } 683 684 try { 685 prefixLength = Integer.parseInt(st.nextToken()); 686 } catch (NumberFormatException nfe) { 687 Slog.e(TAG, "Failed to parse prefixLength", nfe); 688 } 689 690 cfg.setLinkAddress(new LinkAddress(addr, prefixLength)); 691 while (st.hasMoreTokens()) { 692 cfg.setFlag(st.nextToken()); 693 } 694 } catch (NoSuchElementException nsee) { 695 throw new IllegalStateException("Invalid response from daemon: " + event); 696 } 697 return cfg; 698 } 699 700 @Override 701 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { 702 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 703 LinkAddress linkAddr = cfg.getLinkAddress(); 704 if (linkAddr == null || linkAddr.getAddress() == null) { 705 throw new IllegalStateException("Null LinkAddress given"); 706 } 707 708 final Command cmd = new Command("interface", "setcfg", iface, 709 linkAddr.getAddress().getHostAddress(), 710 linkAddr.getNetworkPrefixLength()); 711 for (String flag : cfg.getFlags()) { 712 cmd.appendArg(flag); 713 } 714 715 try { 716 mConnector.execute(cmd); 717 } catch (NativeDaemonConnectorException e) { 718 throw e.rethrowAsParcelableException(); 719 } 720 } 721 722 @Override 723 public void setInterfaceDown(String iface) { 724 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 725 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 726 ifcg.setInterfaceDown(); 727 setInterfaceConfig(iface, ifcg); 728 } 729 730 @Override 731 public void setInterfaceUp(String iface) { 732 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 733 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 734 ifcg.setInterfaceUp(); 735 setInterfaceConfig(iface, ifcg); 736 } 737 738 @Override 739 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { 740 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 741 try { 742 mConnector.execute( 743 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable"); 744 } catch (NativeDaemonConnectorException e) { 745 throw e.rethrowAsParcelableException(); 746 } 747 } 748 749 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 750 IPv6 addresses on interface down, but we need to do full clean up here */ 751 @Override 752 public void clearInterfaceAddresses(String iface) { 753 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 754 try { 755 mConnector.execute("interface", "clearaddrs", iface); 756 } catch (NativeDaemonConnectorException e) { 757 throw e.rethrowAsParcelableException(); 758 } 759 } 760 761 @Override 762 public void enableIpv6(String iface) { 763 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 764 try { 765 mConnector.execute("interface", "ipv6", iface, "enable"); 766 } catch (NativeDaemonConnectorException e) { 767 throw e.rethrowAsParcelableException(); 768 } 769 } 770 771 @Override 772 public void disableIpv6(String iface) { 773 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 774 try { 775 mConnector.execute("interface", "ipv6", iface, "disable"); 776 } catch (NativeDaemonConnectorException e) { 777 throw e.rethrowAsParcelableException(); 778 } 779 } 780 781 @Override 782 public void addRoute(String interfaceName, RouteInfo route) { 783 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 784 modifyRoute(interfaceName, ADD, route, DEFAULT); 785 } 786 787 @Override 788 public void removeRoute(String interfaceName, RouteInfo route) { 789 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 790 modifyRoute(interfaceName, REMOVE, route, DEFAULT); 791 } 792 793 @Override 794 public void addSecondaryRoute(String interfaceName, RouteInfo route) { 795 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 796 modifyRoute(interfaceName, ADD, route, SECONDARY); 797 } 798 799 @Override 800 public void removeSecondaryRoute(String interfaceName, RouteInfo route) { 801 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 802 modifyRoute(interfaceName, REMOVE, route, SECONDARY); 803 } 804 805 private void modifyRoute(String interfaceName, String action, RouteInfo route, String type) { 806 final Command cmd = new Command("interface", "route", action, interfaceName, type); 807 808 // create triplet: dest-ip-addr prefixlength gateway-ip-addr 809 final LinkAddress la = route.getDestination(); 810 cmd.appendArg(la.getAddress().getHostAddress()); 811 cmd.appendArg(la.getNetworkPrefixLength()); 812 813 if (route.getGateway() == null) { 814 if (la.getAddress() instanceof Inet4Address) { 815 cmd.appendArg("0.0.0.0"); 816 } else { 817 cmd.appendArg("::0"); 818 } 819 } else { 820 cmd.appendArg(route.getGateway().getHostAddress()); 821 } 822 823 try { 824 mConnector.execute(cmd); 825 } catch (NativeDaemonConnectorException e) { 826 throw e.rethrowAsParcelableException(); 827 } 828 } 829 830 private ArrayList<String> readRouteList(String filename) { 831 FileInputStream fstream = null; 832 ArrayList<String> list = new ArrayList<String>(); 833 834 try { 835 fstream = new FileInputStream(filename); 836 DataInputStream in = new DataInputStream(fstream); 837 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 838 String s; 839 840 // throw away the title line 841 842 while (((s = br.readLine()) != null) && (s.length() != 0)) { 843 list.add(s); 844 } 845 } catch (IOException ex) { 846 // return current list, possibly empty 847 } finally { 848 if (fstream != null) { 849 try { 850 fstream.close(); 851 } catch (IOException ex) {} 852 } 853 } 854 855 return list; 856 } 857 858 @Override 859 public RouteInfo[] getRoutes(String interfaceName) { 860 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 861 ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>(); 862 863 // v4 routes listed as: 864 // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT 865 for (String s : readRouteList("/proc/net/route")) { 866 String[] fields = s.split("\t"); 867 868 if (fields.length > 7) { 869 String iface = fields[0]; 870 871 if (interfaceName.equals(iface)) { 872 String dest = fields[1]; 873 String gate = fields[2]; 874 String flags = fields[3]; // future use? 875 String mask = fields[7]; 876 try { 877 // address stored as a hex string, ex: 0014A8C0 878 InetAddress destAddr = 879 NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16)); 880 int prefixLength = 881 NetworkUtils.netmaskIntToPrefixLength( 882 (int)Long.parseLong(mask, 16)); 883 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 884 885 // address stored as a hex string, ex 0014A8C0 886 InetAddress gatewayAddr = 887 NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16)); 888 889 RouteInfo route = new RouteInfo(linkAddress, gatewayAddr); 890 routes.add(route); 891 } catch (Exception e) { 892 Log.e(TAG, "Error parsing route " + s + " : " + e); 893 continue; 894 } 895 } 896 } 897 } 898 899 // v6 routes listed as: 900 // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface 901 for (String s : readRouteList("/proc/net/ipv6_route")) { 902 String[]fields = s.split("\\s+"); 903 if (fields.length > 9) { 904 String iface = fields[9].trim(); 905 if (interfaceName.equals(iface)) { 906 String dest = fields[0]; 907 String prefix = fields[1]; 908 String gate = fields[4]; 909 910 try { 911 // prefix length stored as a hex string, ex 40 912 int prefixLength = Integer.parseInt(prefix, 16); 913 914 // address stored as a 32 char hex string 915 // ex fe800000000000000000000000000000 916 InetAddress destAddr = NetworkUtils.hexToInet6Address(dest); 917 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 918 919 InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate); 920 921 RouteInfo route = new RouteInfo(linkAddress, gateAddr); 922 routes.add(route); 923 } catch (Exception e) { 924 Log.e(TAG, "Error parsing route " + s + " : " + e); 925 continue; 926 } 927 } 928 } 929 } 930 return routes.toArray(new RouteInfo[routes.size()]); 931 } 932 933 @Override 934 public void setMtu(String iface, int mtu) { 935 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 936 937 final NativeDaemonEvent event; 938 try { 939 event = mConnector.execute("interface", "setmtu", iface, mtu); 940 } catch (NativeDaemonConnectorException e) { 941 throw e.rethrowAsParcelableException(); 942 } 943 } 944 945 @Override 946 public void shutdown() { 947 // TODO: remove from aidl if nobody calls externally 948 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG); 949 950 Slog.d(TAG, "Shutting down"); 951 } 952 953 @Override 954 public boolean getIpForwardingEnabled() throws IllegalStateException{ 955 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 956 957 final NativeDaemonEvent event; 958 try { 959 event = mConnector.execute("ipfwd", "status"); 960 } catch (NativeDaemonConnectorException e) { 961 throw e.rethrowAsParcelableException(); 962 } 963 964 // 211 Forwarding enabled 965 event.checkCode(IpFwdStatusResult); 966 return event.getMessage().endsWith("enabled"); 967 } 968 969 @Override 970 public void setIpForwardingEnabled(boolean enable) { 971 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 972 try { 973 mConnector.execute("ipfwd", enable ? "enable" : "disable"); 974 } catch (NativeDaemonConnectorException e) { 975 throw e.rethrowAsParcelableException(); 976 } 977 } 978 979 @Override 980 public void startTethering(String[] dhcpRange) { 981 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 982 // cmd is "tether start first_start first_stop second_start second_stop ..." 983 // an odd number of addrs will fail 984 985 final Command cmd = new Command("tether", "start"); 986 for (String d : dhcpRange) { 987 cmd.appendArg(d); 988 } 989 990 try { 991 mConnector.execute(cmd); 992 } catch (NativeDaemonConnectorException e) { 993 throw e.rethrowAsParcelableException(); 994 } 995 } 996 997 @Override 998 public void stopTethering() { 999 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1000 try { 1001 mConnector.execute("tether", "stop"); 1002 } catch (NativeDaemonConnectorException e) { 1003 throw e.rethrowAsParcelableException(); 1004 } 1005 } 1006 1007 @Override 1008 public boolean isTetheringStarted() { 1009 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1010 1011 final NativeDaemonEvent event; 1012 try { 1013 event = mConnector.execute("tether", "status"); 1014 } catch (NativeDaemonConnectorException e) { 1015 throw e.rethrowAsParcelableException(); 1016 } 1017 1018 // 210 Tethering services started 1019 event.checkCode(TetherStatusResult); 1020 return event.getMessage().endsWith("started"); 1021 } 1022 1023 @Override 1024 public void tetherInterface(String iface) { 1025 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1026 try { 1027 mConnector.execute("tether", "interface", "add", iface); 1028 } catch (NativeDaemonConnectorException e) { 1029 throw e.rethrowAsParcelableException(); 1030 } 1031 } 1032 1033 @Override 1034 public void untetherInterface(String iface) { 1035 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1036 try { 1037 mConnector.execute("tether", "interface", "remove", iface); 1038 } catch (NativeDaemonConnectorException e) { 1039 throw e.rethrowAsParcelableException(); 1040 } 1041 } 1042 1043 @Override 1044 public String[] listTetheredInterfaces() { 1045 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1046 try { 1047 return NativeDaemonEvent.filterMessageList( 1048 mConnector.executeForList("tether", "interface", "list"), 1049 TetherInterfaceListResult); 1050 } catch (NativeDaemonConnectorException e) { 1051 throw e.rethrowAsParcelableException(); 1052 } 1053 } 1054 1055 @Override 1056 public void setDnsForwarders(String[] dns) { 1057 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1058 1059 final Command cmd = new Command("tether", "dns", "set"); 1060 for (String s : dns) { 1061 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress()); 1062 } 1063 1064 try { 1065 mConnector.execute(cmd); 1066 } catch (NativeDaemonConnectorException e) { 1067 throw e.rethrowAsParcelableException(); 1068 } 1069 } 1070 1071 @Override 1072 public String[] getDnsForwarders() { 1073 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1074 try { 1075 return NativeDaemonEvent.filterMessageList( 1076 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult); 1077 } catch (NativeDaemonConnectorException e) { 1078 throw e.rethrowAsParcelableException(); 1079 } 1080 } 1081 1082 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) { 1083 ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size()); 1084 for (InterfaceAddress ia : addresses) { 1085 if (!ia.getAddress().isLinkLocalAddress()) 1086 filtered.add(ia); 1087 } 1088 return filtered; 1089 } 1090 1091 private void modifyNat(String action, String internalInterface, String externalInterface) 1092 throws SocketException { 1093 final Command cmd = new Command("nat", action, internalInterface, externalInterface); 1094 1095 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName( 1096 internalInterface); 1097 if (internalNetworkInterface == null) { 1098 cmd.appendArg("0"); 1099 } else { 1100 // Don't touch link-local routes, as link-local addresses aren't routable, 1101 // kernel creates link-local routes on all interfaces automatically 1102 List<InterfaceAddress> interfaceAddresses = excludeLinkLocal( 1103 internalNetworkInterface.getInterfaceAddresses()); 1104 cmd.appendArg(interfaceAddresses.size()); 1105 for (InterfaceAddress ia : interfaceAddresses) { 1106 InetAddress addr = NetworkUtils.getNetworkPart( 1107 ia.getAddress(), ia.getNetworkPrefixLength()); 1108 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength()); 1109 } 1110 } 1111 1112 try { 1113 mConnector.execute(cmd); 1114 } catch (NativeDaemonConnectorException e) { 1115 throw e.rethrowAsParcelableException(); 1116 } 1117 } 1118 1119 @Override 1120 public void enableNat(String internalInterface, String externalInterface) { 1121 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1122 try { 1123 modifyNat("enable", internalInterface, externalInterface); 1124 } catch (SocketException e) { 1125 throw new IllegalStateException(e); 1126 } 1127 } 1128 1129 @Override 1130 public void disableNat(String internalInterface, String externalInterface) { 1131 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1132 try { 1133 modifyNat("disable", internalInterface, externalInterface); 1134 } catch (SocketException e) { 1135 throw new IllegalStateException(e); 1136 } 1137 } 1138 1139 @Override 1140 public String[] listTtys() { 1141 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1142 try { 1143 return NativeDaemonEvent.filterMessageList( 1144 mConnector.executeForList("list_ttys"), TtyListResult); 1145 } catch (NativeDaemonConnectorException e) { 1146 throw e.rethrowAsParcelableException(); 1147 } 1148 } 1149 1150 @Override 1151 public void attachPppd( 1152 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) { 1153 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1154 try { 1155 mConnector.execute("pppd", "attach", tty, 1156 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 1157 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 1158 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 1159 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()); 1160 } catch (NativeDaemonConnectorException e) { 1161 throw e.rethrowAsParcelableException(); 1162 } 1163 } 1164 1165 @Override 1166 public void detachPppd(String tty) { 1167 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1168 try { 1169 mConnector.execute("pppd", "detach", tty); 1170 } catch (NativeDaemonConnectorException e) { 1171 throw e.rethrowAsParcelableException(); 1172 } 1173 } 1174 1175 @Override 1176 public void startAccessPoint( 1177 WifiConfiguration wifiConfig, String wlanIface) { 1178 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1179 try { 1180 wifiFirmwareReload(wlanIface, "AP"); 1181 if (wifiConfig == null) { 1182 mConnector.execute("softap", "set", wlanIface); 1183 } else { 1184 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1185 "broadcast", "6", getSecurityType(wifiConfig), 1186 new SensitiveArg(wifiConfig.preSharedKey)); 1187 } 1188 mConnector.execute("softap", "startap"); 1189 } catch (NativeDaemonConnectorException e) { 1190 throw e.rethrowAsParcelableException(); 1191 } 1192 } 1193 1194 private static String getSecurityType(WifiConfiguration wifiConfig) { 1195 switch (wifiConfig.getAuthType()) { 1196 case KeyMgmt.WPA_PSK: 1197 return "wpa-psk"; 1198 case KeyMgmt.WPA2_PSK: 1199 return "wpa2-psk"; 1200 default: 1201 return "open"; 1202 } 1203 } 1204 1205 /* @param mode can be "AP", "STA" or "P2P" */ 1206 @Override 1207 public void wifiFirmwareReload(String wlanIface, String mode) { 1208 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1209 try { 1210 mConnector.execute("softap", "fwreload", wlanIface, mode); 1211 } catch (NativeDaemonConnectorException e) { 1212 throw e.rethrowAsParcelableException(); 1213 } 1214 } 1215 1216 @Override 1217 public void stopAccessPoint(String wlanIface) { 1218 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1219 try { 1220 mConnector.execute("softap", "stopap"); 1221 wifiFirmwareReload(wlanIface, "STA"); 1222 } catch (NativeDaemonConnectorException e) { 1223 throw e.rethrowAsParcelableException(); 1224 } 1225 } 1226 1227 @Override 1228 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { 1229 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1230 try { 1231 if (wifiConfig == null) { 1232 mConnector.execute("softap", "set", wlanIface); 1233 } else { 1234 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1235 "broadcast", "6", getSecurityType(wifiConfig), 1236 new SensitiveArg(wifiConfig.preSharedKey)); 1237 } 1238 } catch (NativeDaemonConnectorException e) { 1239 throw e.rethrowAsParcelableException(); 1240 } 1241 } 1242 1243 @Override 1244 public void addIdleTimer(String iface, int timeout, final int type) { 1245 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1246 1247 if (DBG) Slog.d(TAG, "Adding idletimer"); 1248 1249 synchronized (mIdleTimerLock) { 1250 IdleTimerParams params = mActiveIdleTimers.get(iface); 1251 if (params != null) { 1252 // the interface already has idletimer, update network count 1253 params.networkCount++; 1254 return; 1255 } 1256 1257 try { 1258 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout), 1259 Integer.toString(type)); 1260 } catch (NativeDaemonConnectorException e) { 1261 throw e.rethrowAsParcelableException(); 1262 } 1263 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type)); 1264 1265 // Networks start up. 1266 if (ConnectivityManager.isNetworkTypeMobile(type)) { 1267 mNetworkActive = false; 1268 } 1269 mMainHandler.post(new Runnable() { 1270 @Override public void run() { 1271 notifyInterfaceClassActivity(type, true, SystemClock.elapsedRealtimeNanos()); 1272 } 1273 }); 1274 } 1275 } 1276 1277 @Override 1278 public void removeIdleTimer(String iface) { 1279 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1280 1281 if (DBG) Slog.d(TAG, "Removing idletimer"); 1282 1283 synchronized (mIdleTimerLock) { 1284 final IdleTimerParams params = mActiveIdleTimers.get(iface); 1285 if (params == null || --(params.networkCount) > 0) { 1286 return; 1287 } 1288 1289 try { 1290 mConnector.execute("idletimer", "remove", iface, 1291 Integer.toString(params.timeout), Integer.toString(params.type)); 1292 } catch (NativeDaemonConnectorException e) { 1293 throw e.rethrowAsParcelableException(); 1294 } 1295 mActiveIdleTimers.remove(iface); 1296 mMainHandler.post(new Runnable() { 1297 @Override public void run() { 1298 notifyInterfaceClassActivity(params.type, false, 1299 SystemClock.elapsedRealtimeNanos()); 1300 } 1301 }); 1302 } 1303 } 1304 1305 @Override 1306 public NetworkStats getNetworkStatsSummaryDev() { 1307 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1308 try { 1309 return mStatsFactory.readNetworkStatsSummaryDev(); 1310 } catch (IOException e) { 1311 throw new IllegalStateException(e); 1312 } 1313 } 1314 1315 @Override 1316 public NetworkStats getNetworkStatsSummaryXt() { 1317 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1318 try { 1319 return mStatsFactory.readNetworkStatsSummaryXt(); 1320 } catch (IOException e) { 1321 throw new IllegalStateException(e); 1322 } 1323 } 1324 1325 @Override 1326 public NetworkStats getNetworkStatsDetail() { 1327 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1328 try { 1329 return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); 1330 } catch (IOException e) { 1331 throw new IllegalStateException(e); 1332 } 1333 } 1334 1335 @Override 1336 public void setInterfaceQuota(String iface, long quotaBytes) { 1337 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1338 1339 // silently discard when control disabled 1340 // TODO: eventually migrate to be always enabled 1341 if (!mBandwidthControlEnabled) return; 1342 1343 synchronized (mQuotaLock) { 1344 if (mActiveQuotas.containsKey(iface)) { 1345 throw new IllegalStateException("iface " + iface + " already has quota"); 1346 } 1347 1348 try { 1349 // TODO: support quota shared across interfaces 1350 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes); 1351 mActiveQuotas.put(iface, quotaBytes); 1352 } catch (NativeDaemonConnectorException e) { 1353 throw e.rethrowAsParcelableException(); 1354 } 1355 } 1356 } 1357 1358 @Override 1359 public void removeInterfaceQuota(String iface) { 1360 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1361 1362 // silently discard when control disabled 1363 // TODO: eventually migrate to be always enabled 1364 if (!mBandwidthControlEnabled) return; 1365 1366 synchronized (mQuotaLock) { 1367 if (!mActiveQuotas.containsKey(iface)) { 1368 // TODO: eventually consider throwing 1369 return; 1370 } 1371 1372 mActiveQuotas.remove(iface); 1373 mActiveAlerts.remove(iface); 1374 1375 try { 1376 // TODO: support quota shared across interfaces 1377 mConnector.execute("bandwidth", "removeiquota", iface); 1378 } catch (NativeDaemonConnectorException e) { 1379 throw e.rethrowAsParcelableException(); 1380 } 1381 } 1382 } 1383 1384 @Override 1385 public void setInterfaceAlert(String iface, long alertBytes) { 1386 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1387 1388 // silently discard when control disabled 1389 // TODO: eventually migrate to be always enabled 1390 if (!mBandwidthControlEnabled) return; 1391 1392 // quick sanity check 1393 if (!mActiveQuotas.containsKey(iface)) { 1394 throw new IllegalStateException("setting alert requires existing quota on iface"); 1395 } 1396 1397 synchronized (mQuotaLock) { 1398 if (mActiveAlerts.containsKey(iface)) { 1399 throw new IllegalStateException("iface " + iface + " already has alert"); 1400 } 1401 1402 try { 1403 // TODO: support alert shared across interfaces 1404 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes); 1405 mActiveAlerts.put(iface, alertBytes); 1406 } catch (NativeDaemonConnectorException e) { 1407 throw e.rethrowAsParcelableException(); 1408 } 1409 } 1410 } 1411 1412 @Override 1413 public void removeInterfaceAlert(String iface) { 1414 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1415 1416 // silently discard when control disabled 1417 // TODO: eventually migrate to be always enabled 1418 if (!mBandwidthControlEnabled) return; 1419 1420 synchronized (mQuotaLock) { 1421 if (!mActiveAlerts.containsKey(iface)) { 1422 // TODO: eventually consider throwing 1423 return; 1424 } 1425 1426 try { 1427 // TODO: support alert shared across interfaces 1428 mConnector.execute("bandwidth", "removeinterfacealert", iface); 1429 mActiveAlerts.remove(iface); 1430 } catch (NativeDaemonConnectorException e) { 1431 throw e.rethrowAsParcelableException(); 1432 } 1433 } 1434 } 1435 1436 @Override 1437 public void setGlobalAlert(long alertBytes) { 1438 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1439 1440 // silently discard when control disabled 1441 // TODO: eventually migrate to be always enabled 1442 if (!mBandwidthControlEnabled) return; 1443 1444 try { 1445 mConnector.execute("bandwidth", "setglobalalert", alertBytes); 1446 } catch (NativeDaemonConnectorException e) { 1447 throw e.rethrowAsParcelableException(); 1448 } 1449 } 1450 1451 @Override 1452 public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1453 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1454 1455 // silently discard when control disabled 1456 // TODO: eventually migrate to be always enabled 1457 if (!mBandwidthControlEnabled) return; 1458 1459 synchronized (mQuotaLock) { 1460 final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false); 1461 if (oldRejectOnQuota == rejectOnQuotaInterfaces) { 1462 // TODO: eventually consider throwing 1463 return; 1464 } 1465 1466 try { 1467 mConnector.execute("bandwidth", 1468 rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid); 1469 if (rejectOnQuotaInterfaces) { 1470 mUidRejectOnQuota.put(uid, true); 1471 } else { 1472 mUidRejectOnQuota.delete(uid); 1473 } 1474 } catch (NativeDaemonConnectorException e) { 1475 throw e.rethrowAsParcelableException(); 1476 } 1477 } 1478 } 1479 1480 @Override 1481 public boolean isBandwidthControlEnabled() { 1482 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1483 return mBandwidthControlEnabled; 1484 } 1485 1486 @Override 1487 public NetworkStats getNetworkStatsUidDetail(int uid) { 1488 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1489 try { 1490 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null); 1491 } catch (IOException e) { 1492 throw new IllegalStateException(e); 1493 } 1494 } 1495 1496 @Override 1497 public NetworkStats getNetworkStatsTethering() { 1498 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1499 1500 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1501 try { 1502 final NativeDaemonEvent[] events = mConnector.executeForList( 1503 "bandwidth", "gettetherstats"); 1504 for (NativeDaemonEvent event : events) { 1505 if (event.getCode() != TetheringStatsListResult) continue; 1506 1507 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets 1508 final StringTokenizer tok = new StringTokenizer(event.getMessage()); 1509 try { 1510 final String ifaceIn = tok.nextToken(); 1511 final String ifaceOut = tok.nextToken(); 1512 1513 final NetworkStats.Entry entry = new NetworkStats.Entry(); 1514 entry.iface = ifaceOut; 1515 entry.uid = UID_TETHERING; 1516 entry.set = SET_DEFAULT; 1517 entry.tag = TAG_NONE; 1518 entry.rxBytes = Long.parseLong(tok.nextToken()); 1519 entry.rxPackets = Long.parseLong(tok.nextToken()); 1520 entry.txBytes = Long.parseLong(tok.nextToken()); 1521 entry.txPackets = Long.parseLong(tok.nextToken()); 1522 stats.combineValues(entry); 1523 } catch (NoSuchElementException e) { 1524 throw new IllegalStateException("problem parsing tethering stats: " + event); 1525 } catch (NumberFormatException e) { 1526 throw new IllegalStateException("problem parsing tethering stats: " + event); 1527 } 1528 } 1529 } catch (NativeDaemonConnectorException e) { 1530 throw e.rethrowAsParcelableException(); 1531 } 1532 return stats; 1533 } 1534 1535 @Override 1536 public void setDefaultInterfaceForDns(String iface) { 1537 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1538 try { 1539 mConnector.execute("resolver", "setdefaultif", iface); 1540 } catch (NativeDaemonConnectorException e) { 1541 throw e.rethrowAsParcelableException(); 1542 } 1543 } 1544 1545 @Override 1546 public void setDnsServersForInterface(String iface, String[] servers, String domains) { 1547 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1548 1549 final Command cmd = new Command("resolver", "setifdns", iface, 1550 (domains == null ? "" : domains)); 1551 1552 for (String s : servers) { 1553 InetAddress a = NetworkUtils.numericToInetAddress(s); 1554 if (a.isAnyLocalAddress() == false) { 1555 cmd.appendArg(a.getHostAddress()); 1556 } 1557 } 1558 1559 try { 1560 mConnector.execute(cmd); 1561 } catch (NativeDaemonConnectorException e) { 1562 throw e.rethrowAsParcelableException(); 1563 } 1564 } 1565 1566 @Override 1567 public void setUidRangeRoute(String iface, int uid_start, int uid_end) { 1568 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1569 try { 1570 mConnector.execute("interface", "fwmark", 1571 "uid", "add", iface, uid_start, uid_end); 1572 } catch (NativeDaemonConnectorException e) { 1573 throw e.rethrowAsParcelableException(); 1574 } 1575 } 1576 1577 @Override 1578 public void clearUidRangeRoute(String iface, int uid_start, int uid_end) { 1579 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1580 try { 1581 mConnector.execute("interface", "fwmark", 1582 "uid", "remove", iface, uid_start, uid_end); 1583 } catch (NativeDaemonConnectorException e) { 1584 throw e.rethrowAsParcelableException(); 1585 } 1586 } 1587 1588 @Override 1589 public void setMarkedForwarding(String iface) { 1590 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1591 try { 1592 mConnector.execute("interface", "fwmark", "rule", "add", iface); 1593 } catch (NativeDaemonConnectorException e) { 1594 throw e.rethrowAsParcelableException(); 1595 } 1596 } 1597 1598 @Override 1599 public void clearMarkedForwarding(String iface) { 1600 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1601 try { 1602 mConnector.execute("interface", "fwmark", "rule", "remove", iface); 1603 } catch (NativeDaemonConnectorException e) { 1604 throw e.rethrowAsParcelableException(); 1605 } 1606 } 1607 1608 @Override 1609 public int getMarkForUid(int uid) { 1610 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1611 final NativeDaemonEvent event; 1612 try { 1613 event = mConnector.execute("interface", "fwmark", "get", "mark", uid); 1614 } catch (NativeDaemonConnectorException e) { 1615 throw e.rethrowAsParcelableException(); 1616 } 1617 event.checkCode(GetMarkResult); 1618 return Integer.parseInt(event.getMessage()); 1619 } 1620 1621 @Override 1622 public int getMarkForProtect() { 1623 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1624 final NativeDaemonEvent event; 1625 try { 1626 event = mConnector.execute("interface", "fwmark", "get", "protect"); 1627 } catch (NativeDaemonConnectorException e) { 1628 throw e.rethrowAsParcelableException(); 1629 } 1630 event.checkCode(GetMarkResult); 1631 return Integer.parseInt(event.getMessage()); 1632 } 1633 1634 @Override 1635 public void setMarkedForwardingRoute(String iface, RouteInfo route) { 1636 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1637 try { 1638 LinkAddress dest = route.getDestination(); 1639 mConnector.execute("interface", "fwmark", "route", "add", iface, 1640 dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength()); 1641 } catch (NativeDaemonConnectorException e) { 1642 throw e.rethrowAsParcelableException(); 1643 } 1644 } 1645 1646 @Override 1647 public void clearMarkedForwardingRoute(String iface, RouteInfo route) { 1648 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1649 try { 1650 LinkAddress dest = route.getDestination(); 1651 mConnector.execute("interface", "fwmark", "route", "remove", iface, 1652 dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength()); 1653 } catch (NativeDaemonConnectorException e) { 1654 throw e.rethrowAsParcelableException(); 1655 } 1656 } 1657 1658 @Override 1659 public void setHostExemption(LinkAddress host) { 1660 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1661 try { 1662 mConnector.execute("interface", "fwmark", "exempt", "add", host); 1663 } catch (NativeDaemonConnectorException e) { 1664 throw e.rethrowAsParcelableException(); 1665 } 1666 } 1667 1668 @Override 1669 public void clearHostExemption(LinkAddress host) { 1670 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1671 try { 1672 mConnector.execute("interface", "fwmark", "exempt", "remove", host); 1673 } catch (NativeDaemonConnectorException e) { 1674 throw e.rethrowAsParcelableException(); 1675 } 1676 } 1677 1678 @Override 1679 public void setDnsInterfaceForUidRange(String iface, int uid_start, int uid_end) { 1680 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1681 try { 1682 mConnector.execute("resolver", "setifaceforuidrange", iface, uid_start, uid_end); 1683 } catch (NativeDaemonConnectorException e) { 1684 throw e.rethrowAsParcelableException(); 1685 } 1686 } 1687 1688 @Override 1689 public void clearDnsInterfaceForUidRange(int uid_start, int uid_end) { 1690 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1691 try { 1692 mConnector.execute("resolver", "clearifaceforuidrange", uid_start, uid_end); 1693 } catch (NativeDaemonConnectorException e) { 1694 throw e.rethrowAsParcelableException(); 1695 } 1696 } 1697 1698 @Override 1699 public void clearDnsInterfaceMaps() { 1700 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1701 try { 1702 mConnector.execute("resolver", "clearifacemapping"); 1703 } catch (NativeDaemonConnectorException e) { 1704 throw e.rethrowAsParcelableException(); 1705 } 1706 } 1707 1708 1709 @Override 1710 public void flushDefaultDnsCache() { 1711 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1712 try { 1713 mConnector.execute("resolver", "flushdefaultif"); 1714 } catch (NativeDaemonConnectorException e) { 1715 throw e.rethrowAsParcelableException(); 1716 } 1717 } 1718 1719 @Override 1720 public void flushInterfaceDnsCache(String iface) { 1721 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1722 try { 1723 mConnector.execute("resolver", "flushif", iface); 1724 } catch (NativeDaemonConnectorException e) { 1725 throw e.rethrowAsParcelableException(); 1726 } 1727 } 1728 1729 @Override 1730 public void setFirewallEnabled(boolean enabled) { 1731 enforceSystemUid(); 1732 try { 1733 mConnector.execute("firewall", enabled ? "enable" : "disable"); 1734 mFirewallEnabled = enabled; 1735 } catch (NativeDaemonConnectorException e) { 1736 throw e.rethrowAsParcelableException(); 1737 } 1738 } 1739 1740 @Override 1741 public boolean isFirewallEnabled() { 1742 enforceSystemUid(); 1743 return mFirewallEnabled; 1744 } 1745 1746 @Override 1747 public void setFirewallInterfaceRule(String iface, boolean allow) { 1748 enforceSystemUid(); 1749 Preconditions.checkState(mFirewallEnabled); 1750 final String rule = allow ? ALLOW : DENY; 1751 try { 1752 mConnector.execute("firewall", "set_interface_rule", iface, rule); 1753 } catch (NativeDaemonConnectorException e) { 1754 throw e.rethrowAsParcelableException(); 1755 } 1756 } 1757 1758 @Override 1759 public void setFirewallEgressSourceRule(String addr, boolean allow) { 1760 enforceSystemUid(); 1761 Preconditions.checkState(mFirewallEnabled); 1762 final String rule = allow ? ALLOW : DENY; 1763 try { 1764 mConnector.execute("firewall", "set_egress_source_rule", addr, rule); 1765 } catch (NativeDaemonConnectorException e) { 1766 throw e.rethrowAsParcelableException(); 1767 } 1768 } 1769 1770 @Override 1771 public void setFirewallEgressDestRule(String addr, int port, boolean allow) { 1772 enforceSystemUid(); 1773 Preconditions.checkState(mFirewallEnabled); 1774 final String rule = allow ? ALLOW : DENY; 1775 try { 1776 mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule); 1777 } catch (NativeDaemonConnectorException e) { 1778 throw e.rethrowAsParcelableException(); 1779 } 1780 } 1781 1782 @Override 1783 public void setFirewallUidRule(int uid, boolean allow) { 1784 enforceSystemUid(); 1785 Preconditions.checkState(mFirewallEnabled); 1786 final String rule = allow ? ALLOW : DENY; 1787 try { 1788 mConnector.execute("firewall", "set_uid_rule", uid, rule); 1789 } catch (NativeDaemonConnectorException e) { 1790 throw e.rethrowAsParcelableException(); 1791 } 1792 } 1793 1794 private static void enforceSystemUid() { 1795 final int uid = Binder.getCallingUid(); 1796 if (uid != Process.SYSTEM_UID) { 1797 throw new SecurityException("Only available to AID_SYSTEM"); 1798 } 1799 } 1800 1801 @Override 1802 public void setDnsInterfaceForPid(String iface, int pid) throws IllegalStateException { 1803 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1804 try { 1805 mConnector.execute("resolver", "setifaceforpid", iface, pid); 1806 } catch (NativeDaemonConnectorException e) { 1807 throw new IllegalStateException( 1808 "Error communicating with native deamon to set interface for pid" + iface, e); 1809 } 1810 } 1811 1812 @Override 1813 public void clearDnsInterfaceForPid(int pid) throws IllegalStateException { 1814 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1815 try { 1816 mConnector.execute("resolver", "clearifaceforpid", pid); 1817 } catch (NativeDaemonConnectorException e) { 1818 throw new IllegalStateException( 1819 "Error communicating with native deamon to clear interface for pid " + pid, e); 1820 } 1821 } 1822 1823 @Override 1824 public void startClatd(String interfaceName) throws IllegalStateException { 1825 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1826 1827 try { 1828 mConnector.execute("clatd", "start", interfaceName); 1829 } catch (NativeDaemonConnectorException e) { 1830 throw e.rethrowAsParcelableException(); 1831 } 1832 } 1833 1834 @Override 1835 public void stopClatd() throws IllegalStateException { 1836 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1837 1838 try { 1839 mConnector.execute("clatd", "stop"); 1840 } catch (NativeDaemonConnectorException e) { 1841 throw e.rethrowAsParcelableException(); 1842 } 1843 } 1844 1845 @Override 1846 public boolean isClatdStarted() { 1847 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1848 1849 final NativeDaemonEvent event; 1850 try { 1851 event = mConnector.execute("clatd", "status"); 1852 } catch (NativeDaemonConnectorException e) { 1853 throw e.rethrowAsParcelableException(); 1854 } 1855 1856 event.checkCode(ClatdStatusResult); 1857 return event.getMessage().endsWith("started"); 1858 } 1859 1860 @Override 1861 public void registerNetworkActivityListener(INetworkActivityListener listener) { 1862 mNetworkActivityListeners.register(listener); 1863 } 1864 1865 @Override 1866 public void unregisterNetworkActivityListener(INetworkActivityListener listener) { 1867 mNetworkActivityListeners.unregister(listener); 1868 } 1869 1870 @Override 1871 public boolean isNetworkActive() { 1872 synchronized (mNetworkActivityListeners) { 1873 return mNetworkActive || mActiveIdleTimers.isEmpty(); 1874 } 1875 } 1876 1877 private void reportNetworkActive() { 1878 final int length = mNetworkActivityListeners.beginBroadcast(); 1879 for (int i = 0; i < length; i++) { 1880 try { 1881 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); 1882 } catch (RemoteException e) { 1883 } catch (RuntimeException e) { 1884 } 1885 } 1886 mNetworkActivityListeners.finishBroadcast(); 1887 } 1888 1889 /** {@inheritDoc} */ 1890 @Override 1891 public void monitor() { 1892 if (mConnector != null) { 1893 mConnector.monitor(); 1894 } 1895 } 1896 1897 @Override 1898 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1899 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 1900 1901 pw.println("NetworkManagementService NativeDaemonConnector Log:"); 1902 mConnector.dump(fd, pw, args); 1903 pw.println(); 1904 1905 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 1906 1907 synchronized (mQuotaLock) { 1908 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 1909 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 1910 } 1911 1912 synchronized (mUidRejectOnQuota) { 1913 pw.print("UID reject on quota ifaces: ["); 1914 final int size = mUidRejectOnQuota.size(); 1915 for (int i = 0; i < size; i++) { 1916 pw.print(mUidRejectOnQuota.keyAt(i)); 1917 if (i < size - 1) pw.print(","); 1918 } 1919 pw.println("]"); 1920 } 1921 1922 synchronized (mIdleTimerLock) { 1923 pw.println("Idle timers:"); 1924 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { 1925 pw.print(" "); pw.print(ent.getKey()); pw.println(":"); 1926 IdleTimerParams params = ent.getValue(); 1927 pw.print(" timeout="); pw.print(params.timeout); 1928 pw.print(" type="); pw.print(params.type); 1929 pw.print(" networkCount="); pw.println(params.networkCount); 1930 } 1931 } 1932 1933 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 1934 } 1935} 1936