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