NetworkManagementService.java revision 69ddab4575ff684c533c995e07ca15fe18543fc0
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_NONE; 24import static android.net.NetworkStats.UID_ALL; 25import static android.net.TrafficStats.UID_TETHERING; 26import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult; 27import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult; 28import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceRxThrottleResult; 29import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceTxThrottleResult; 30import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult; 31import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult; 32import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult; 33import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult; 34import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsResult; 35import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult; 36import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; 37 38import android.bluetooth.BluetoothTetheringDataTracker; 39import android.content.Context; 40import android.net.INetworkManagementEventObserver; 41import android.net.InterfaceConfiguration; 42import android.net.LinkAddress; 43import android.net.NetworkStats; 44import android.net.NetworkUtils; 45import android.net.RouteInfo; 46import android.net.wifi.WifiConfiguration; 47import android.net.wifi.WifiConfiguration.KeyMgmt; 48import android.os.Handler; 49import android.os.INetworkManagementService; 50import android.os.RemoteCallbackList; 51import android.os.RemoteException; 52import android.os.SystemClock; 53import android.os.SystemProperties; 54import android.util.Log; 55import android.util.Slog; 56import android.util.SparseBooleanArray; 57 58import com.android.internal.net.NetworkStatsFactory; 59import com.android.internal.util.Preconditions; 60import com.android.server.NativeDaemonConnector.Command; 61import com.android.server.net.LockdownVpnTracker; 62import com.google.android.collect.Maps; 63 64import java.io.BufferedReader; 65import java.io.DataInputStream; 66import java.io.File; 67import java.io.FileDescriptor; 68import java.io.FileInputStream; 69import java.io.IOException; 70import java.io.InputStreamReader; 71import java.io.PrintWriter; 72import java.net.Inet4Address; 73import java.net.InetAddress; 74import java.net.InterfaceAddress; 75import java.net.NetworkInterface; 76import java.net.SocketException; 77import java.util.ArrayList; 78import java.util.Collection; 79import java.util.HashMap; 80import java.util.Map; 81import java.util.NoSuchElementException; 82import java.util.StringTokenizer; 83import java.util.concurrent.CountDownLatch; 84 85/** 86 * @hide 87 */ 88public class NetworkManagementService extends INetworkManagementService.Stub 89 implements Watchdog.Monitor { 90 private static final String TAG = "NetworkManagementService"; 91 private static final boolean DBG = false; 92 private static final String NETD_TAG = "NetdConnector"; 93 94 private static final String ADD = "add"; 95 private static final String REMOVE = "remove"; 96 97 private static final String ALLOW = "allow"; 98 private static final String DENY = "deny"; 99 100 private static final String DEFAULT = "default"; 101 private static final String SECONDARY = "secondary"; 102 103 /** 104 * Name representing {@link #setGlobalAlert(long)} limit when delivered to 105 * {@link INetworkManagementEventObserver#limitReached(String, String)}. 106 */ 107 public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; 108 109 class NetdResponseCode { 110 /* Keep in sync with system/netd/ResponseCode.h */ 111 public static final int InterfaceListResult = 110; 112 public static final int TetherInterfaceListResult = 111; 113 public static final int TetherDnsFwdTgtListResult = 112; 114 public static final int TtyListResult = 113; 115 116 public static final int TetherStatusResult = 210; 117 public static final int IpFwdStatusResult = 211; 118 public static final int InterfaceGetCfgResult = 213; 119 public static final int SoftapStatusResult = 214; 120 public static final int InterfaceRxCounterResult = 216; 121 public static final int InterfaceTxCounterResult = 217; 122 public static final int InterfaceRxThrottleResult = 218; 123 public static final int InterfaceTxThrottleResult = 219; 124 public static final int QuotaCounterResult = 220; 125 public static final int TetheringStatsResult = 221; 126 public static final int DnsProxyQueryResult = 222; 127 128 public static final int InterfaceChange = 600; 129 public static final int BandwidthControl = 601; 130 public static final int InterfaceClassActivity = 613; 131 } 132 133 /** 134 * Binder context for this service 135 */ 136 private Context mContext; 137 138 /** 139 * connector object for communicating with netd 140 */ 141 private NativeDaemonConnector mConnector; 142 143 private final Handler mMainHandler = new Handler(); 144 145 private Thread mThread; 146 private CountDownLatch mConnectedSignal = new CountDownLatch(1); 147 148 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers = 149 new RemoteCallbackList<INetworkManagementEventObserver>(); 150 151 private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory(); 152 153 private Object mQuotaLock = new Object(); 154 /** Set of interfaces with active quotas. */ 155 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap(); 156 /** Set of interfaces with active alerts. */ 157 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap(); 158 /** Set of UIDs with active reject rules. */ 159 private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray(); 160 161 private Object mIdleTimerLock = new Object(); 162 /** Set of interfaces with active idle timers. */ 163 private static class IdleTimerParams { 164 public final int timeout; 165 public final String label; 166 public int networkCount; 167 168 IdleTimerParams(int timeout, String label) { 169 this.timeout = timeout; 170 this.label = label; 171 this.networkCount = 1; 172 } 173 } 174 private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap(); 175 176 private volatile boolean mBandwidthControlEnabled; 177 private volatile boolean mFirewallEnabled; 178 179 /** 180 * Constructs a new NetworkManagementService instance 181 * 182 * @param context Binder context for this service 183 */ 184 private NetworkManagementService(Context context) { 185 mContext = context; 186 187 if ("simulator".equals(SystemProperties.get("ro.product.device"))) { 188 return; 189 } 190 191 mConnector = new NativeDaemonConnector( 192 new NetdCallbackReceiver(), "netd", 10, NETD_TAG, 160); 193 mThread = new Thread(mConnector, NETD_TAG); 194 195 // Add ourself to the Watchdog monitors. 196 Watchdog.getInstance().addMonitor(this); 197 } 198 199 public static NetworkManagementService create(Context context) throws InterruptedException { 200 final NetworkManagementService service = new NetworkManagementService(context); 201 final CountDownLatch connectedSignal = service.mConnectedSignal; 202 if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); 203 service.mThread.start(); 204 if (DBG) Slog.d(TAG, "Awaiting socket connection"); 205 connectedSignal.await(); 206 if (DBG) Slog.d(TAG, "Connected"); 207 return service; 208 } 209 210 public void systemReady() { 211 prepareNativeDaemon(); 212 if (DBG) Slog.d(TAG, "Prepared"); 213 } 214 215 @Override 216 public void registerObserver(INetworkManagementEventObserver observer) { 217 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 218 mObservers.register(observer); 219 } 220 221 @Override 222 public void unregisterObserver(INetworkManagementEventObserver observer) { 223 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 224 mObservers.unregister(observer); 225 } 226 227 /** 228 * Notify our observers of an interface status change 229 */ 230 private void notifyInterfaceStatusChanged(String iface, boolean up) { 231 final int length = mObservers.beginBroadcast(); 232 for (int i = 0; i < length; i++) { 233 try { 234 mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up); 235 } catch (RemoteException e) { 236 } 237 } 238 mObservers.finishBroadcast(); 239 } 240 241 /** 242 * Notify our observers of an interface link state change 243 * (typically, an Ethernet cable has been plugged-in or unplugged). 244 */ 245 private void notifyInterfaceLinkStateChanged(String iface, boolean up) { 246 final int length = mObservers.beginBroadcast(); 247 for (int i = 0; i < length; i++) { 248 try { 249 mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up); 250 } catch (RemoteException e) { 251 } 252 } 253 mObservers.finishBroadcast(); 254 } 255 256 /** 257 * Notify our observers of an interface addition. 258 */ 259 private void notifyInterfaceAdded(String iface) { 260 final int length = mObservers.beginBroadcast(); 261 for (int i = 0; i < length; i++) { 262 try { 263 mObservers.getBroadcastItem(i).interfaceAdded(iface); 264 } catch (RemoteException e) { 265 } 266 } 267 mObservers.finishBroadcast(); 268 } 269 270 /** 271 * Notify our observers of an interface removal. 272 */ 273 private void notifyInterfaceRemoved(String iface) { 274 // netd already clears out quota and alerts for removed ifaces; update 275 // our sanity-checking state. 276 mActiveAlerts.remove(iface); 277 mActiveQuotas.remove(iface); 278 279 final int length = mObservers.beginBroadcast(); 280 for (int i = 0; i < length; i++) { 281 try { 282 mObservers.getBroadcastItem(i).interfaceRemoved(iface); 283 } catch (RemoteException e) { 284 } 285 } 286 mObservers.finishBroadcast(); 287 } 288 289 /** 290 * Notify our observers of a limit reached. 291 */ 292 private void notifyLimitReached(String limitName, String iface) { 293 final int length = mObservers.beginBroadcast(); 294 for (int i = 0; i < length; i++) { 295 try { 296 mObservers.getBroadcastItem(i).limitReached(limitName, iface); 297 } catch (RemoteException e) { 298 } 299 } 300 mObservers.finishBroadcast(); 301 } 302 303 /** 304 * Notify our observers of a change in the data activity state of the interface 305 */ 306 private void notifyInterfaceClassActivity(String label, boolean active) { 307 final int length = mObservers.beginBroadcast(); 308 for (int i = 0; i < length; i++) { 309 try { 310 mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(label, active); 311 } catch (RemoteException e) { 312 } 313 } 314 mObservers.finishBroadcast(); 315 } 316 317 /** 318 * Prepare native daemon once connected, enabling modules and pushing any 319 * existing in-memory rules. 320 */ 321 private void prepareNativeDaemon() { 322 mBandwidthControlEnabled = false; 323 324 // only enable bandwidth control when support exists 325 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists(); 326 if (hasKernelSupport) { 327 Slog.d(TAG, "enabling bandwidth control"); 328 try { 329 mConnector.execute("bandwidth", "enable"); 330 mBandwidthControlEnabled = true; 331 } catch (NativeDaemonConnectorException e) { 332 Log.wtf(TAG, "problem enabling bandwidth controls", e); 333 } 334 } else { 335 Slog.d(TAG, "not enabling bandwidth control"); 336 } 337 338 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); 339 340 // push any existing quota or UID rules 341 synchronized (mQuotaLock) { 342 int size = mActiveQuotas.size(); 343 if (size > 0) { 344 Slog.d(TAG, "pushing " + size + " active quota rules"); 345 final HashMap<String, Long> activeQuotas = mActiveQuotas; 346 mActiveQuotas = Maps.newHashMap(); 347 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) { 348 setInterfaceQuota(entry.getKey(), entry.getValue()); 349 } 350 } 351 352 size = mActiveAlerts.size(); 353 if (size > 0) { 354 Slog.d(TAG, "pushing " + size + " active alert rules"); 355 final HashMap<String, Long> activeAlerts = mActiveAlerts; 356 mActiveAlerts = Maps.newHashMap(); 357 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) { 358 setInterfaceAlert(entry.getKey(), entry.getValue()); 359 } 360 } 361 362 size = mUidRejectOnQuota.size(); 363 if (size > 0) { 364 Slog.d(TAG, "pushing " + size + " active uid rules"); 365 final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota; 366 mUidRejectOnQuota = new SparseBooleanArray(); 367 for (int i = 0; i < uidRejectOnQuota.size(); i++) { 368 setUidNetworkRules(uidRejectOnQuota.keyAt(i), uidRejectOnQuota.valueAt(i)); 369 } 370 } 371 } 372 373 // TODO: Push any existing firewall state 374 setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); 375 } 376 377 // 378 // Netd Callback handling 379 // 380 381 private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { 382 @Override 383 public void onDaemonConnected() { 384 // event is dispatched from internal NDC thread, so we prepare the 385 // daemon back on main thread. 386 if (mConnectedSignal != null) { 387 mConnectedSignal.countDown(); 388 mConnectedSignal = null; 389 } else { 390 mMainHandler.post(new Runnable() { 391 @Override 392 public void run() { 393 prepareNativeDaemon(); 394 } 395 }); 396 } 397 } 398 399 @Override 400 public boolean onEvent(int code, String raw, String[] cooked) { 401 switch (code) { 402 case NetdResponseCode.InterfaceChange: 403 /* 404 * a network interface change occured 405 * Format: "NNN Iface added <name>" 406 * "NNN Iface removed <name>" 407 * "NNN Iface changed <name> <up/down>" 408 * "NNN Iface linkstatus <name> <up/down>" 409 */ 410 if (cooked.length < 4 || !cooked[1].equals("Iface")) { 411 throw new IllegalStateException( 412 String.format("Invalid event from daemon (%s)", raw)); 413 } 414 if (cooked[2].equals("added")) { 415 notifyInterfaceAdded(cooked[3]); 416 return true; 417 } else if (cooked[2].equals("removed")) { 418 notifyInterfaceRemoved(cooked[3]); 419 return true; 420 } else if (cooked[2].equals("changed") && cooked.length == 5) { 421 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); 422 return true; 423 } else if (cooked[2].equals("linkstate") && cooked.length == 5) { 424 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); 425 return true; 426 } 427 throw new IllegalStateException( 428 String.format("Invalid event from daemon (%s)", raw)); 429 // break; 430 case NetdResponseCode.BandwidthControl: 431 /* 432 * Bandwidth control needs some attention 433 * Format: "NNN limit alert <alertName> <ifaceName>" 434 */ 435 if (cooked.length < 5 || !cooked[1].equals("limit")) { 436 throw new IllegalStateException( 437 String.format("Invalid event from daemon (%s)", raw)); 438 } 439 if (cooked[2].equals("alert")) { 440 notifyLimitReached(cooked[3], cooked[4]); 441 return true; 442 } 443 throw new IllegalStateException( 444 String.format("Invalid event from daemon (%s)", raw)); 445 // break; 446 case NetdResponseCode.InterfaceClassActivity: 447 /* 448 * An network interface class state changed (active/idle) 449 * Format: "NNN IfaceClass <active/idle> <label>" 450 */ 451 if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) { 452 throw new IllegalStateException( 453 String.format("Invalid event from daemon (%s)", raw)); 454 } 455 boolean isActive = cooked[2].equals("active"); 456 notifyInterfaceClassActivity(cooked[3], isActive); 457 return true; 458 // break; 459 default: break; 460 } 461 return false; 462 } 463 } 464 465 466 // 467 // INetworkManagementService members 468 // 469 470 @Override 471 public String[] listInterfaces() { 472 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 473 try { 474 return NativeDaemonEvent.filterMessageList( 475 mConnector.executeForList("interface", "list"), InterfaceListResult); 476 } catch (NativeDaemonConnectorException e) { 477 throw e.rethrowAsParcelableException(); 478 } 479 } 480 481 @Override 482 public InterfaceConfiguration getInterfaceConfig(String iface) { 483 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 484 485 final NativeDaemonEvent event; 486 try { 487 event = mConnector.execute("interface", "getcfg", iface); 488 } catch (NativeDaemonConnectorException e) { 489 throw e.rethrowAsParcelableException(); 490 } 491 492 event.checkCode(InterfaceGetCfgResult); 493 494 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3 495 final StringTokenizer st = new StringTokenizer(event.getMessage()); 496 497 InterfaceConfiguration cfg; 498 try { 499 cfg = new InterfaceConfiguration(); 500 cfg.setHardwareAddress(st.nextToken(" ")); 501 InetAddress addr = null; 502 int prefixLength = 0; 503 try { 504 addr = NetworkUtils.numericToInetAddress(st.nextToken()); 505 } catch (IllegalArgumentException iae) { 506 Slog.e(TAG, "Failed to parse ipaddr", iae); 507 } 508 509 try { 510 prefixLength = Integer.parseInt(st.nextToken()); 511 } catch (NumberFormatException nfe) { 512 Slog.e(TAG, "Failed to parse prefixLength", nfe); 513 } 514 515 cfg.setLinkAddress(new LinkAddress(addr, prefixLength)); 516 while (st.hasMoreTokens()) { 517 cfg.setFlag(st.nextToken()); 518 } 519 } catch (NoSuchElementException nsee) { 520 throw new IllegalStateException("Invalid response from daemon: " + event); 521 } 522 return cfg; 523 } 524 525 @Override 526 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { 527 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 528 LinkAddress linkAddr = cfg.getLinkAddress(); 529 if (linkAddr == null || linkAddr.getAddress() == null) { 530 throw new IllegalStateException("Null LinkAddress given"); 531 } 532 533 final Command cmd = new Command("interface", "setcfg", iface, 534 linkAddr.getAddress().getHostAddress(), 535 linkAddr.getNetworkPrefixLength()); 536 for (String flag : cfg.getFlags()) { 537 cmd.appendArg(flag); 538 } 539 540 try { 541 mConnector.execute(cmd); 542 } catch (NativeDaemonConnectorException e) { 543 throw e.rethrowAsParcelableException(); 544 } 545 } 546 547 @Override 548 public void setInterfaceDown(String iface) { 549 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 550 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 551 ifcg.setInterfaceDown(); 552 setInterfaceConfig(iface, ifcg); 553 } 554 555 @Override 556 public void setInterfaceUp(String iface) { 557 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 558 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 559 ifcg.setInterfaceUp(); 560 setInterfaceConfig(iface, ifcg); 561 } 562 563 @Override 564 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { 565 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 566 try { 567 mConnector.execute( 568 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable"); 569 } catch (NativeDaemonConnectorException e) { 570 throw e.rethrowAsParcelableException(); 571 } 572 } 573 574 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 575 IPv6 addresses on interface down, but we need to do full clean up here */ 576 @Override 577 public void clearInterfaceAddresses(String iface) { 578 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 579 try { 580 mConnector.execute("interface", "clearaddrs", iface); 581 } catch (NativeDaemonConnectorException e) { 582 throw e.rethrowAsParcelableException(); 583 } 584 } 585 586 @Override 587 public void enableIpv6(String iface) { 588 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 589 try { 590 mConnector.execute("interface", "ipv6", iface, "enable"); 591 } catch (NativeDaemonConnectorException e) { 592 throw e.rethrowAsParcelableException(); 593 } 594 } 595 596 @Override 597 public void disableIpv6(String iface) { 598 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 599 try { 600 mConnector.execute("interface", "ipv6", iface, "disable"); 601 } catch (NativeDaemonConnectorException e) { 602 throw e.rethrowAsParcelableException(); 603 } 604 } 605 606 @Override 607 public void addRoute(String interfaceName, RouteInfo route) { 608 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 609 modifyRoute(interfaceName, ADD, route, DEFAULT); 610 } 611 612 @Override 613 public void removeRoute(String interfaceName, RouteInfo route) { 614 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 615 modifyRoute(interfaceName, REMOVE, route, DEFAULT); 616 } 617 618 @Override 619 public void addSecondaryRoute(String interfaceName, RouteInfo route) { 620 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 621 modifyRoute(interfaceName, ADD, route, SECONDARY); 622 } 623 624 @Override 625 public void removeSecondaryRoute(String interfaceName, RouteInfo route) { 626 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 627 modifyRoute(interfaceName, REMOVE, route, SECONDARY); 628 } 629 630 private void modifyRoute(String interfaceName, String action, RouteInfo route, String type) { 631 final Command cmd = new Command("interface", "route", action, interfaceName, type); 632 633 // create triplet: dest-ip-addr prefixlength gateway-ip-addr 634 final LinkAddress la = route.getDestination(); 635 cmd.appendArg(la.getAddress().getHostAddress()); 636 cmd.appendArg(la.getNetworkPrefixLength()); 637 638 if (route.getGateway() == null) { 639 if (la.getAddress() instanceof Inet4Address) { 640 cmd.appendArg("0.0.0.0"); 641 } else { 642 cmd.appendArg("::0"); 643 } 644 } else { 645 cmd.appendArg(route.getGateway().getHostAddress()); 646 } 647 648 try { 649 mConnector.execute(cmd); 650 } catch (NativeDaemonConnectorException e) { 651 throw e.rethrowAsParcelableException(); 652 } 653 } 654 655 private ArrayList<String> readRouteList(String filename) { 656 FileInputStream fstream = null; 657 ArrayList<String> list = new ArrayList<String>(); 658 659 try { 660 fstream = new FileInputStream(filename); 661 DataInputStream in = new DataInputStream(fstream); 662 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 663 String s; 664 665 // throw away the title line 666 667 while (((s = br.readLine()) != null) && (s.length() != 0)) { 668 list.add(s); 669 } 670 } catch (IOException ex) { 671 // return current list, possibly empty 672 } finally { 673 if (fstream != null) { 674 try { 675 fstream.close(); 676 } catch (IOException ex) {} 677 } 678 } 679 680 return list; 681 } 682 683 @Override 684 public RouteInfo[] getRoutes(String interfaceName) { 685 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 686 ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>(); 687 688 // v4 routes listed as: 689 // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT 690 for (String s : readRouteList("/proc/net/route")) { 691 String[] fields = s.split("\t"); 692 693 if (fields.length > 7) { 694 String iface = fields[0]; 695 696 if (interfaceName.equals(iface)) { 697 String dest = fields[1]; 698 String gate = fields[2]; 699 String flags = fields[3]; // future use? 700 String mask = fields[7]; 701 try { 702 // address stored as a hex string, ex: 0014A8C0 703 InetAddress destAddr = 704 NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16)); 705 int prefixLength = 706 NetworkUtils.netmaskIntToPrefixLength( 707 (int)Long.parseLong(mask, 16)); 708 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 709 710 // address stored as a hex string, ex 0014A8C0 711 InetAddress gatewayAddr = 712 NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16)); 713 714 RouteInfo route = new RouteInfo(linkAddress, gatewayAddr); 715 routes.add(route); 716 } catch (Exception e) { 717 Log.e(TAG, "Error parsing route " + s + " : " + e); 718 continue; 719 } 720 } 721 } 722 } 723 724 // v6 routes listed as: 725 // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface 726 for (String s : readRouteList("/proc/net/ipv6_route")) { 727 String[]fields = s.split("\\s+"); 728 if (fields.length > 9) { 729 String iface = fields[9].trim(); 730 if (interfaceName.equals(iface)) { 731 String dest = fields[0]; 732 String prefix = fields[1]; 733 String gate = fields[4]; 734 735 try { 736 // prefix length stored as a hex string, ex 40 737 int prefixLength = Integer.parseInt(prefix, 16); 738 739 // address stored as a 32 char hex string 740 // ex fe800000000000000000000000000000 741 InetAddress destAddr = NetworkUtils.hexToInet6Address(dest); 742 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 743 744 InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate); 745 746 RouteInfo route = new RouteInfo(linkAddress, gateAddr); 747 routes.add(route); 748 } catch (Exception e) { 749 Log.e(TAG, "Error parsing route " + s + " : " + e); 750 continue; 751 } 752 } 753 } 754 } 755 return routes.toArray(new RouteInfo[routes.size()]); 756 } 757 758 @Override 759 public void shutdown() { 760 // TODO: remove from aidl if nobody calls externally 761 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG); 762 763 Slog.d(TAG, "Shutting down"); 764 } 765 766 @Override 767 public boolean getIpForwardingEnabled() throws IllegalStateException{ 768 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 769 770 final NativeDaemonEvent event; 771 try { 772 event = mConnector.execute("ipfwd", "status"); 773 } catch (NativeDaemonConnectorException e) { 774 throw e.rethrowAsParcelableException(); 775 } 776 777 // 211 Forwarding enabled 778 event.checkCode(IpFwdStatusResult); 779 return event.getMessage().endsWith("enabled"); 780 } 781 782 @Override 783 public void setIpForwardingEnabled(boolean enable) { 784 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 785 try { 786 mConnector.execute("ipfwd", enable ? "enable" : "disable"); 787 } catch (NativeDaemonConnectorException e) { 788 throw e.rethrowAsParcelableException(); 789 } 790 } 791 792 @Override 793 public void startTethering(String[] dhcpRange) { 794 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 795 // cmd is "tether start first_start first_stop second_start second_stop ..." 796 // an odd number of addrs will fail 797 798 final Command cmd = new Command("tether", "start"); 799 for (String d : dhcpRange) { 800 cmd.appendArg(d); 801 } 802 803 try { 804 mConnector.execute(cmd); 805 } catch (NativeDaemonConnectorException e) { 806 throw e.rethrowAsParcelableException(); 807 } 808 } 809 810 @Override 811 public void stopTethering() { 812 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 813 try { 814 mConnector.execute("tether", "stop"); 815 } catch (NativeDaemonConnectorException e) { 816 throw e.rethrowAsParcelableException(); 817 } 818 } 819 820 @Override 821 public boolean isTetheringStarted() { 822 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 823 824 final NativeDaemonEvent event; 825 try { 826 event = mConnector.execute("tether", "status"); 827 } catch (NativeDaemonConnectorException e) { 828 throw e.rethrowAsParcelableException(); 829 } 830 831 // 210 Tethering services started 832 event.checkCode(TetherStatusResult); 833 return event.getMessage().endsWith("started"); 834 } 835 836 // TODO(BT) Remove 837 public void startReverseTethering(String iface) 838 throws IllegalStateException { 839 if (DBG) Slog.d(TAG, "startReverseTethering in"); 840 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 841 // cmd is "tether start first_start first_stop second_start second_stop ..." 842 // an odd number of addrs will fail 843 String cmd = "tether start-reverse"; 844 cmd += " " + iface; 845 if (DBG) Slog.d(TAG, "startReverseTethering cmd: " + cmd); 846 try { 847 mConnector.doCommand(cmd); 848 } catch (NativeDaemonConnectorException e) { 849 throw new IllegalStateException("Unable to communicate to native daemon"); 850 } 851 BluetoothTetheringDataTracker.getInstance().startReverseTether(iface); 852 853 } 854 855 // TODO(BT) Remove 856 public void stopReverseTethering() throws IllegalStateException { 857 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 858 try { 859 mConnector.doCommand("tether stop-reverse"); 860 } catch (NativeDaemonConnectorException e) { 861 throw new IllegalStateException("Unable to communicate to native daemon to stop tether"); 862 } 863 BluetoothTetheringDataTracker.getInstance().stopReverseTether(); 864 } 865 866 @Override 867 public void tetherInterface(String iface) { 868 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 869 try { 870 mConnector.execute("tether", "interface", "add", iface); 871 } catch (NativeDaemonConnectorException e) { 872 throw e.rethrowAsParcelableException(); 873 } 874 } 875 876 @Override 877 public void untetherInterface(String iface) { 878 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 879 try { 880 mConnector.execute("tether", "interface", "remove", iface); 881 } catch (NativeDaemonConnectorException e) { 882 throw e.rethrowAsParcelableException(); 883 } 884 } 885 886 @Override 887 public String[] listTetheredInterfaces() { 888 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 889 try { 890 return NativeDaemonEvent.filterMessageList( 891 mConnector.executeForList("tether", "interface", "list"), 892 TetherInterfaceListResult); 893 } catch (NativeDaemonConnectorException e) { 894 throw e.rethrowAsParcelableException(); 895 } 896 } 897 898 @Override 899 public void setDnsForwarders(String[] dns) { 900 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 901 902 final Command cmd = new Command("tether", "dns", "set"); 903 for (String s : dns) { 904 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress()); 905 } 906 907 try { 908 mConnector.execute(cmd); 909 } catch (NativeDaemonConnectorException e) { 910 throw e.rethrowAsParcelableException(); 911 } 912 } 913 914 @Override 915 public String[] getDnsForwarders() { 916 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 917 try { 918 return NativeDaemonEvent.filterMessageList( 919 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult); 920 } catch (NativeDaemonConnectorException e) { 921 throw e.rethrowAsParcelableException(); 922 } 923 } 924 925 private void modifyNat(String action, String internalInterface, String externalInterface) 926 throws SocketException { 927 final Command cmd = new Command("nat", action, internalInterface, externalInterface); 928 929 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName( 930 internalInterface); 931 if (internalNetworkInterface == null) { 932 cmd.appendArg("0"); 933 } else { 934 Collection<InterfaceAddress> interfaceAddresses = internalNetworkInterface 935 .getInterfaceAddresses(); 936 cmd.appendArg(interfaceAddresses.size()); 937 for (InterfaceAddress ia : interfaceAddresses) { 938 InetAddress addr = NetworkUtils.getNetworkPart( 939 ia.getAddress(), ia.getNetworkPrefixLength()); 940 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength()); 941 } 942 } 943 944 try { 945 mConnector.execute(cmd); 946 } catch (NativeDaemonConnectorException e) { 947 throw e.rethrowAsParcelableException(); 948 } 949 } 950 951 @Override 952 public void enableNat(String internalInterface, String externalInterface) { 953 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 954 try { 955 modifyNat("enable", internalInterface, externalInterface); 956 } catch (SocketException e) { 957 throw new IllegalStateException(e); 958 } 959 } 960 961 @Override 962 public void disableNat(String internalInterface, String externalInterface) { 963 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 964 try { 965 modifyNat("disable", internalInterface, externalInterface); 966 } catch (SocketException e) { 967 throw new IllegalStateException(e); 968 } 969 } 970 971 @Override 972 public String[] listTtys() { 973 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 974 try { 975 return NativeDaemonEvent.filterMessageList( 976 mConnector.executeForList("list_ttys"), TtyListResult); 977 } catch (NativeDaemonConnectorException e) { 978 throw e.rethrowAsParcelableException(); 979 } 980 } 981 982 @Override 983 public void attachPppd( 984 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) { 985 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 986 try { 987 mConnector.execute("pppd", "attach", tty, 988 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 989 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 990 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 991 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()); 992 } catch (NativeDaemonConnectorException e) { 993 throw e.rethrowAsParcelableException(); 994 } 995 } 996 997 @Override 998 public void detachPppd(String tty) { 999 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1000 try { 1001 mConnector.execute("pppd", "detach", tty); 1002 } catch (NativeDaemonConnectorException e) { 1003 throw e.rethrowAsParcelableException(); 1004 } 1005 } 1006 1007 @Override 1008 public void startAccessPoint( 1009 WifiConfiguration wifiConfig, String wlanIface) { 1010 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1011 try { 1012 wifiFirmwareReload(wlanIface, "AP"); 1013 if (wifiConfig == null) { 1014 mConnector.execute("softap", "set", wlanIface); 1015 } else { 1016 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1017 getSecurityType(wifiConfig), wifiConfig.preSharedKey); 1018 } 1019 mConnector.execute("softap", "startap"); 1020 } catch (NativeDaemonConnectorException e) { 1021 throw e.rethrowAsParcelableException(); 1022 } 1023 } 1024 1025 private static String getSecurityType(WifiConfiguration wifiConfig) { 1026 switch (wifiConfig.getAuthType()) { 1027 case KeyMgmt.WPA_PSK: 1028 return "wpa-psk"; 1029 case KeyMgmt.WPA2_PSK: 1030 return "wpa2-psk"; 1031 default: 1032 return "open"; 1033 } 1034 } 1035 1036 /* @param mode can be "AP", "STA" or "P2P" */ 1037 @Override 1038 public void wifiFirmwareReload(String wlanIface, String mode) { 1039 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1040 try { 1041 mConnector.execute("softap", "fwreload", wlanIface, mode); 1042 } catch (NativeDaemonConnectorException e) { 1043 throw e.rethrowAsParcelableException(); 1044 } 1045 } 1046 1047 @Override 1048 public void stopAccessPoint(String wlanIface) { 1049 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1050 try { 1051 mConnector.execute("softap", "stopap"); 1052 wifiFirmwareReload(wlanIface, "STA"); 1053 } catch (NativeDaemonConnectorException e) { 1054 throw e.rethrowAsParcelableException(); 1055 } 1056 } 1057 1058 @Override 1059 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { 1060 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1061 try { 1062 if (wifiConfig == null) { 1063 mConnector.execute("softap", "set", wlanIface); 1064 } else { 1065 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1066 getSecurityType(wifiConfig), wifiConfig.preSharedKey); 1067 } 1068 } catch (NativeDaemonConnectorException e) { 1069 throw e.rethrowAsParcelableException(); 1070 } 1071 } 1072 1073 @Override 1074 public void addIdleTimer(String iface, int timeout, String label) { 1075 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1076 1077 if (DBG) Slog.d(TAG, "Adding idletimer"); 1078 1079 synchronized (mIdleTimerLock) { 1080 IdleTimerParams params = mActiveIdleTimers.get(iface); 1081 if (params != null) { 1082 // the interface already has idletimer, update network count 1083 params.networkCount++; 1084 return; 1085 } 1086 1087 try { 1088 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout), label); 1089 } catch (NativeDaemonConnectorException e) { 1090 throw e.rethrowAsParcelableException(); 1091 } 1092 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, label)); 1093 } 1094 } 1095 1096 @Override 1097 public void removeIdleTimer(String iface) { 1098 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1099 1100 if (DBG) Slog.d(TAG, "Removing idletimer"); 1101 1102 synchronized (mIdleTimerLock) { 1103 IdleTimerParams params = mActiveIdleTimers.get(iface); 1104 if (params == null || --(params.networkCount) > 0) { 1105 return; 1106 } 1107 1108 try { 1109 mConnector.execute("idletimer", "remove", iface, 1110 Integer.toString(params.timeout), params.label); 1111 } catch (NativeDaemonConnectorException e) { 1112 throw e.rethrowAsParcelableException(); 1113 } 1114 mActiveIdleTimers.remove(iface); 1115 } 1116 } 1117 1118 @Override 1119 public NetworkStats getNetworkStatsSummaryDev() { 1120 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1121 return mStatsFactory.readNetworkStatsSummaryDev(); 1122 } 1123 1124 @Override 1125 public NetworkStats getNetworkStatsSummaryXt() { 1126 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1127 return mStatsFactory.readNetworkStatsSummaryXt(); 1128 } 1129 1130 @Override 1131 public NetworkStats getNetworkStatsDetail() { 1132 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1133 return mStatsFactory.readNetworkStatsDetail(UID_ALL); 1134 } 1135 1136 @Override 1137 public void setInterfaceQuota(String iface, long quotaBytes) { 1138 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1139 1140 // silently discard when control disabled 1141 // TODO: eventually migrate to be always enabled 1142 if (!mBandwidthControlEnabled) return; 1143 1144 synchronized (mQuotaLock) { 1145 if (mActiveQuotas.containsKey(iface)) { 1146 throw new IllegalStateException("iface " + iface + " already has quota"); 1147 } 1148 1149 try { 1150 // TODO: support quota shared across interfaces 1151 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes); 1152 mActiveQuotas.put(iface, quotaBytes); 1153 } catch (NativeDaemonConnectorException e) { 1154 throw e.rethrowAsParcelableException(); 1155 } 1156 } 1157 } 1158 1159 @Override 1160 public void removeInterfaceQuota(String iface) { 1161 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1162 1163 // silently discard when control disabled 1164 // TODO: eventually migrate to be always enabled 1165 if (!mBandwidthControlEnabled) return; 1166 1167 synchronized (mQuotaLock) { 1168 if (!mActiveQuotas.containsKey(iface)) { 1169 // TODO: eventually consider throwing 1170 return; 1171 } 1172 1173 mActiveQuotas.remove(iface); 1174 mActiveAlerts.remove(iface); 1175 1176 try { 1177 // TODO: support quota shared across interfaces 1178 mConnector.execute("bandwidth", "removeiquota", iface); 1179 } catch (NativeDaemonConnectorException e) { 1180 throw e.rethrowAsParcelableException(); 1181 } 1182 } 1183 } 1184 1185 @Override 1186 public void setInterfaceAlert(String iface, long alertBytes) { 1187 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1188 1189 // silently discard when control disabled 1190 // TODO: eventually migrate to be always enabled 1191 if (!mBandwidthControlEnabled) return; 1192 1193 // quick sanity check 1194 if (!mActiveQuotas.containsKey(iface)) { 1195 throw new IllegalStateException("setting alert requires existing quota on iface"); 1196 } 1197 1198 synchronized (mQuotaLock) { 1199 if (mActiveAlerts.containsKey(iface)) { 1200 throw new IllegalStateException("iface " + iface + " already has alert"); 1201 } 1202 1203 try { 1204 // TODO: support alert shared across interfaces 1205 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes); 1206 mActiveAlerts.put(iface, alertBytes); 1207 } catch (NativeDaemonConnectorException e) { 1208 throw e.rethrowAsParcelableException(); 1209 } 1210 } 1211 } 1212 1213 @Override 1214 public void removeInterfaceAlert(String iface) { 1215 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1216 1217 // silently discard when control disabled 1218 // TODO: eventually migrate to be always enabled 1219 if (!mBandwidthControlEnabled) return; 1220 1221 synchronized (mQuotaLock) { 1222 if (!mActiveAlerts.containsKey(iface)) { 1223 // TODO: eventually consider throwing 1224 return; 1225 } 1226 1227 try { 1228 // TODO: support alert shared across interfaces 1229 mConnector.execute("bandwidth", "removeinterfacealert", iface); 1230 mActiveAlerts.remove(iface); 1231 } catch (NativeDaemonConnectorException e) { 1232 throw e.rethrowAsParcelableException(); 1233 } 1234 } 1235 } 1236 1237 @Override 1238 public void setGlobalAlert(long alertBytes) { 1239 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1240 1241 // silently discard when control disabled 1242 // TODO: eventually migrate to be always enabled 1243 if (!mBandwidthControlEnabled) return; 1244 1245 try { 1246 mConnector.execute("bandwidth", "setglobalalert", alertBytes); 1247 } catch (NativeDaemonConnectorException e) { 1248 throw e.rethrowAsParcelableException(); 1249 } 1250 } 1251 1252 @Override 1253 public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1254 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1255 1256 // silently discard when control disabled 1257 // TODO: eventually migrate to be always enabled 1258 if (!mBandwidthControlEnabled) return; 1259 1260 synchronized (mQuotaLock) { 1261 final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false); 1262 if (oldRejectOnQuota == rejectOnQuotaInterfaces) { 1263 // TODO: eventually consider throwing 1264 return; 1265 } 1266 1267 try { 1268 mConnector.execute("bandwidth", 1269 rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid); 1270 if (rejectOnQuotaInterfaces) { 1271 mUidRejectOnQuota.put(uid, true); 1272 } else { 1273 mUidRejectOnQuota.delete(uid); 1274 } 1275 } catch (NativeDaemonConnectorException e) { 1276 throw e.rethrowAsParcelableException(); 1277 } 1278 } 1279 } 1280 1281 @Override 1282 public boolean isBandwidthControlEnabled() { 1283 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1284 return mBandwidthControlEnabled; 1285 } 1286 1287 @Override 1288 public NetworkStats getNetworkStatsUidDetail(int uid) { 1289 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1290 return mStatsFactory.readNetworkStatsDetail(uid); 1291 } 1292 1293 @Override 1294 public NetworkStats getNetworkStatsTethering(String[] ifacePairs) { 1295 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1296 1297 if (ifacePairs.length % 2 != 0) { 1298 throw new IllegalArgumentException( 1299 "unexpected ifacePairs; length=" + ifacePairs.length); 1300 } 1301 1302 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1303 for (int i = 0; i < ifacePairs.length; i += 2) { 1304 final String ifaceIn = ifacePairs[i]; 1305 final String ifaceOut = ifacePairs[i + 1]; 1306 if (ifaceIn != null && ifaceOut != null) { 1307 stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut)); 1308 } 1309 } 1310 return stats; 1311 } 1312 1313 private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) { 1314 final NativeDaemonEvent event; 1315 try { 1316 event = mConnector.execute("bandwidth", "gettetherstats", ifaceIn, ifaceOut); 1317 } catch (NativeDaemonConnectorException e) { 1318 throw e.rethrowAsParcelableException(); 1319 } 1320 1321 event.checkCode(TetheringStatsResult); 1322 1323 // 221 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets 1324 final StringTokenizer tok = new StringTokenizer(event.getMessage()); 1325 tok.nextToken(); 1326 tok.nextToken(); 1327 1328 try { 1329 final NetworkStats.Entry entry = new NetworkStats.Entry(); 1330 entry.iface = ifaceIn; 1331 entry.uid = UID_TETHERING; 1332 entry.set = SET_DEFAULT; 1333 entry.tag = TAG_NONE; 1334 entry.rxBytes = Long.parseLong(tok.nextToken()); 1335 entry.rxPackets = Long.parseLong(tok.nextToken()); 1336 entry.txBytes = Long.parseLong(tok.nextToken()); 1337 entry.txPackets = Long.parseLong(tok.nextToken()); 1338 return entry; 1339 } catch (NumberFormatException e) { 1340 throw new IllegalStateException( 1341 "problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e); 1342 } 1343 } 1344 1345 @Override 1346 public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) { 1347 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1348 try { 1349 mConnector.execute("interface", "setthrottle", iface, rxKbps, txKbps); 1350 } catch (NativeDaemonConnectorException e) { 1351 throw e.rethrowAsParcelableException(); 1352 } 1353 } 1354 1355 private int getInterfaceThrottle(String iface, boolean rx) { 1356 final NativeDaemonEvent event; 1357 try { 1358 event = mConnector.execute("interface", "getthrottle", iface, rx ? "rx" : "tx"); 1359 } catch (NativeDaemonConnectorException e) { 1360 throw e.rethrowAsParcelableException(); 1361 } 1362 1363 if (rx) { 1364 event.checkCode(InterfaceRxThrottleResult); 1365 } else { 1366 event.checkCode(InterfaceTxThrottleResult); 1367 } 1368 1369 try { 1370 return Integer.parseInt(event.getMessage()); 1371 } catch (NumberFormatException e) { 1372 throw new IllegalStateException("unexpected response:" + event); 1373 } 1374 } 1375 1376 @Override 1377 public int getInterfaceRxThrottle(String iface) { 1378 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1379 return getInterfaceThrottle(iface, true); 1380 } 1381 1382 @Override 1383 public int getInterfaceTxThrottle(String iface) { 1384 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1385 return getInterfaceThrottle(iface, false); 1386 } 1387 1388 @Override 1389 public void setDefaultInterfaceForDns(String iface) { 1390 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1391 try { 1392 mConnector.execute("resolver", "setdefaultif", iface); 1393 } catch (NativeDaemonConnectorException e) { 1394 throw e.rethrowAsParcelableException(); 1395 } 1396 } 1397 1398 @Override 1399 public void setDnsServersForInterface(String iface, String[] servers) { 1400 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1401 1402 final Command cmd = new Command("resolver", "setifdns", iface); 1403 for (String s : servers) { 1404 InetAddress a = NetworkUtils.numericToInetAddress(s); 1405 if (a.isAnyLocalAddress() == false) { 1406 cmd.appendArg(a.getHostAddress()); 1407 } 1408 } 1409 1410 try { 1411 mConnector.execute(cmd); 1412 } catch (NativeDaemonConnectorException e) { 1413 throw e.rethrowAsParcelableException(); 1414 } 1415 } 1416 1417 @Override 1418 public void flushDefaultDnsCache() { 1419 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1420 try { 1421 mConnector.execute("resolver", "flushdefaultif"); 1422 } catch (NativeDaemonConnectorException e) { 1423 throw e.rethrowAsParcelableException(); 1424 } 1425 } 1426 1427 @Override 1428 public void flushInterfaceDnsCache(String iface) { 1429 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1430 try { 1431 mConnector.execute("resolver", "flushif", iface); 1432 } catch (NativeDaemonConnectorException e) { 1433 throw e.rethrowAsParcelableException(); 1434 } 1435 } 1436 1437 @Override 1438 public void setFirewallEnabled(boolean enabled) { 1439 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1440 try { 1441 mConnector.execute("firewall", enabled ? "enable" : "disable"); 1442 mFirewallEnabled = enabled; 1443 } catch (NativeDaemonConnectorException e) { 1444 throw e.rethrowAsParcelableException(); 1445 } 1446 } 1447 1448 @Override 1449 public boolean isFirewallEnabled() { 1450 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1451 return mFirewallEnabled; 1452 } 1453 1454 @Override 1455 public void setFirewallInterfaceRule(String iface, boolean allow) { 1456 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1457 Preconditions.checkState(mFirewallEnabled); 1458 final String rule = allow ? ALLOW : DENY; 1459 try { 1460 mConnector.execute("firewall", "set_interface_rule", iface, rule); 1461 } catch (NativeDaemonConnectorException e) { 1462 throw e.rethrowAsParcelableException(); 1463 } 1464 } 1465 1466 @Override 1467 public void setFirewallEgressSourceRule(String addr, boolean allow) { 1468 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1469 Preconditions.checkState(mFirewallEnabled); 1470 final String rule = allow ? ALLOW : DENY; 1471 try { 1472 mConnector.execute("firewall", "set_egress_source_rule", addr, rule); 1473 } catch (NativeDaemonConnectorException e) { 1474 throw e.rethrowAsParcelableException(); 1475 } 1476 } 1477 1478 @Override 1479 public void setFirewallEgressDestRule(String addr, int port, boolean allow) { 1480 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1481 Preconditions.checkState(mFirewallEnabled); 1482 final String rule = allow ? ALLOW : DENY; 1483 try { 1484 mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule); 1485 } catch (NativeDaemonConnectorException e) { 1486 throw e.rethrowAsParcelableException(); 1487 } 1488 } 1489 1490 @Override 1491 public void setFirewallUidRule(int uid, boolean allow) { 1492 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1493 Preconditions.checkState(mFirewallEnabled); 1494 final String rule = allow ? ALLOW : DENY; 1495 try { 1496 mConnector.execute("firewall", "set_uid_rule", uid, rule); 1497 } catch (NativeDaemonConnectorException e) { 1498 throw e.rethrowAsParcelableException(); 1499 } 1500 } 1501 1502 @Override 1503 public void monitor() { 1504 if (mConnector != null) { 1505 mConnector.monitor(); 1506 } 1507 } 1508 1509 @Override 1510 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1511 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 1512 1513 pw.println("NetworkManagementService NativeDaemonConnector Log:"); 1514 mConnector.dump(fd, pw, args); 1515 pw.println(); 1516 1517 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 1518 1519 synchronized (mQuotaLock) { 1520 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 1521 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 1522 } 1523 1524 synchronized (mUidRejectOnQuota) { 1525 pw.print("UID reject on quota ifaces: ["); 1526 final int size = mUidRejectOnQuota.size(); 1527 for (int i = 0; i < size; i++) { 1528 pw.print(mUidRejectOnQuota.keyAt(i)); 1529 if (i < size - 1) pw.print(","); 1530 } 1531 pw.println("]"); 1532 } 1533 1534 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 1535 } 1536} 1537