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