NetworkManagementService.java revision 3fef7230d2d4c9e8bd49e52e7f319303f2867177
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.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE; 23import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE; 24import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE; 25import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE; 26import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY; 27import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE; 28import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE; 29import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY; 30import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; 31import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST; 32import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST; 33import static android.net.NetworkStats.SET_DEFAULT; 34import static android.net.NetworkStats.TAG_ALL; 35import static android.net.NetworkStats.TAG_NONE; 36import static android.net.NetworkStats.UID_ALL; 37import static android.net.TrafficStats.UID_TETHERING; 38import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult; 39import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult; 40import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult; 41import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult; 42import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult; 43import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult; 44import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult; 45import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult; 46import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult; 47import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; 48import android.annotation.NonNull; 49import android.app.ActivityManagerNative; 50import android.content.Context; 51import android.net.ConnectivityManager; 52import android.net.INetd; 53import android.net.INetworkManagementEventObserver; 54import android.net.InterfaceConfiguration; 55import android.net.IpPrefix; 56import android.net.LinkAddress; 57import android.net.Network; 58import android.net.NetworkPolicyManager; 59import android.net.NetworkStats; 60import android.net.NetworkUtils; 61import android.net.RouteInfo; 62import android.net.UidRange; 63import android.net.wifi.WifiConfiguration; 64import android.net.wifi.WifiConfiguration.KeyMgmt; 65import android.os.BatteryStats; 66import android.os.Binder; 67import android.os.Handler; 68import android.os.INetworkActivityListener; 69import android.os.INetworkManagementService; 70import android.os.PowerManager; 71import android.os.Process; 72import android.os.RemoteCallbackList; 73import android.os.RemoteException; 74import android.os.ServiceManager; 75import android.os.ServiceSpecificException; 76import android.os.StrictMode; 77import android.os.SystemClock; 78import android.os.SystemProperties; 79import android.telephony.DataConnectionRealTimeInfo; 80import android.telephony.PhoneStateListener; 81import android.telephony.SubscriptionManager; 82import android.telephony.TelephonyManager; 83import android.util.Log; 84import android.util.Slog; 85import android.util.SparseBooleanArray; 86import android.util.SparseIntArray; 87 88import com.android.internal.annotations.GuardedBy; 89import com.android.internal.app.IBatteryStats; 90import com.android.internal.net.NetworkStatsFactory; 91import com.android.internal.util.HexDump; 92import com.android.internal.util.Preconditions; 93import com.android.server.NativeDaemonConnector.Command; 94import com.android.server.NativeDaemonConnector.SensitiveArg; 95import com.android.server.net.LockdownVpnTracker; 96import com.google.android.collect.Maps; 97 98import java.io.BufferedReader; 99import java.io.DataInputStream; 100import java.io.File; 101import java.io.FileDescriptor; 102import java.io.FileInputStream; 103import java.io.IOException; 104import java.io.InputStreamReader; 105import java.io.PrintWriter; 106import java.net.InetAddress; 107import java.net.InterfaceAddress; 108import java.net.NetworkInterface; 109import java.net.SocketException; 110import java.util.ArrayList; 111import java.util.Arrays; 112import java.util.HashMap; 113import java.util.List; 114import java.util.Map; 115import java.util.NoSuchElementException; 116import java.util.StringTokenizer; 117import java.util.concurrent.CountDownLatch; 118 119/** 120 * @hide 121 */ 122public class NetworkManagementService extends INetworkManagementService.Stub 123 implements Watchdog.Monitor { 124 private static final String TAG = "NetworkManagement"; 125 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); 126 private static final String NETD_TAG = "NetdConnector"; 127 private static final String NETD_SERVICE_NAME = "netd"; 128 129 private static final int MAX_UID_RANGES_PER_COMMAND = 10; 130 131 /** 132 * Name representing {@link #setGlobalAlert(long)} limit when delivered to 133 * {@link INetworkManagementEventObserver#limitReached(String, String)}. 134 */ 135 public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; 136 137 /** 138 * String to pass to netd to indicate that a network is only accessible 139 * to apps that have the CHANGE_NETWORK_STATE permission. 140 */ 141 public static final String PERMISSION_NETWORK = "NETWORK"; 142 143 /** 144 * String to pass to netd to indicate that a network is only 145 * accessible to system apps and those with the CONNECTIVITY_INTERNAL 146 * permission. 147 */ 148 public static final String PERMISSION_SYSTEM = "SYSTEM"; 149 150 class NetdResponseCode { 151 /* Keep in sync with system/netd/server/ResponseCode.h */ 152 public static final int InterfaceListResult = 110; 153 public static final int TetherInterfaceListResult = 111; 154 public static final int TetherDnsFwdTgtListResult = 112; 155 public static final int TtyListResult = 113; 156 public static final int TetheringStatsListResult = 114; 157 158 public static final int TetherStatusResult = 210; 159 public static final int IpFwdStatusResult = 211; 160 public static final int InterfaceGetCfgResult = 213; 161 public static final int SoftapStatusResult = 214; 162 public static final int InterfaceRxCounterResult = 216; 163 public static final int InterfaceTxCounterResult = 217; 164 public static final int QuotaCounterResult = 220; 165 public static final int TetheringStatsResult = 221; 166 public static final int DnsProxyQueryResult = 222; 167 public static final int ClatdStatusResult = 223; 168 169 public static final int InterfaceChange = 600; 170 public static final int BandwidthControl = 601; 171 public static final int InterfaceClassActivity = 613; 172 public static final int InterfaceAddressChange = 614; 173 public static final int InterfaceDnsServerInfo = 615; 174 public static final int RouteChange = 616; 175 public static final int StrictCleartext = 617; 176 } 177 178 /** 179 * String indicating a softap command. 180 */ 181 static final String SOFT_AP_COMMAND = "softap"; 182 183 /** 184 * String passed back to netd connector indicating softap command success. 185 */ 186 static final String SOFT_AP_COMMAND_SUCCESS = "Ok"; 187 188 static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1; 189 190 /** 191 * Binder context for this service 192 */ 193 private final Context mContext; 194 195 /** 196 * connector object for communicating with netd 197 */ 198 private final NativeDaemonConnector mConnector; 199 200 private final Handler mFgHandler; 201 private final Handler mDaemonHandler; 202 203 private INetd mNetdService; 204 205 private IBatteryStats mBatteryStats; 206 207 private final Thread mThread; 208 private CountDownLatch mConnectedSignal = new CountDownLatch(1); 209 210 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers = 211 new RemoteCallbackList<INetworkManagementEventObserver>(); 212 213 private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory(); 214 215 private Object mQuotaLock = new Object(); 216 217 /** Set of interfaces with active quotas. */ 218 @GuardedBy("mQuotaLock") 219 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap(); 220 /** Set of interfaces with active alerts. */ 221 @GuardedBy("mQuotaLock") 222 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap(); 223 /** Set of UIDs blacklisted on metered networks. */ 224 @GuardedBy("mQuotaLock") 225 private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray(); 226 /** Set of UIDs whitelisted on metered networks. */ 227 @GuardedBy("mQuotaLock") 228 private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray(); 229 /** Set of UIDs with cleartext penalties. */ 230 @GuardedBy("mQuotaLock") 231 private SparseIntArray mUidCleartextPolicy = new SparseIntArray(); 232 /** Set of UIDs that are to be blocked/allowed by firewall controller. */ 233 @GuardedBy("mQuotaLock") 234 private SparseIntArray mUidFirewallRules = new SparseIntArray(); 235 /** 236 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches 237 * to application idles. 238 */ 239 @GuardedBy("mQuotaLock") 240 private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray(); 241 /** 242 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches 243 * to device idles. 244 */ 245 @GuardedBy("mQuotaLock") 246 private SparseIntArray mUidFirewallDozableRules = new SparseIntArray(); 247 /** 248 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches 249 * to device on power-save mode. 250 */ 251 @GuardedBy("mQuotaLock") 252 private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray(); 253 /** Set of states for the child firewall chains. True if the chain is active. */ 254 @GuardedBy("mQuotaLock") 255 final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray(); 256 257 @GuardedBy("mQuotaLock") 258 private boolean mDataSaverMode; 259 260 private Object mIdleTimerLock = new Object(); 261 /** Set of interfaces with active idle timers. */ 262 private static class IdleTimerParams { 263 public final int timeout; 264 public final int type; 265 public int networkCount; 266 267 IdleTimerParams(int timeout, int type) { 268 this.timeout = timeout; 269 this.type = type; 270 this.networkCount = 1; 271 } 272 } 273 private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap(); 274 275 private volatile boolean mBandwidthControlEnabled; 276 private volatile boolean mFirewallEnabled; 277 private volatile boolean mStrictEnabled; 278 279 private boolean mMobileActivityFromRadio = false; 280 private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; 281 private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; 282 283 private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners = 284 new RemoteCallbackList<INetworkActivityListener>(); 285 private boolean mNetworkActive; 286 287 /** 288 * Constructs a new NetworkManagementService instance 289 * 290 * @param context Binder context for this service 291 */ 292 private NetworkManagementService(Context context, String socket) { 293 mContext = context; 294 295 // make sure this is on the same looper as our NativeDaemonConnector for sync purposes 296 mFgHandler = new Handler(FgThread.get().getLooper()); 297 298 // Don't need this wake lock, since we now have a time stamp for when 299 // the network actually went inactive. (It might be nice to still do this, 300 // but I don't want to do it through the power manager because that pollutes the 301 // battery stats history with pointless noise.) 302 //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 303 PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG); 304 305 mConnector = new NativeDaemonConnector( 306 new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl, 307 FgThread.get().getLooper()); 308 mThread = new Thread(mConnector, NETD_TAG); 309 310 mDaemonHandler = new Handler(FgThread.get().getLooper()); 311 312 // Add ourself to the Watchdog monitors. 313 Watchdog.getInstance().addMonitor(this); 314 } 315 316 static NetworkManagementService create(Context context, String socket) 317 throws InterruptedException { 318 final NetworkManagementService service = new NetworkManagementService(context, socket); 319 final CountDownLatch connectedSignal = service.mConnectedSignal; 320 if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); 321 service.mThread.start(); 322 if (DBG) Slog.d(TAG, "Awaiting socket connection"); 323 connectedSignal.await(); 324 if (DBG) Slog.d(TAG, "Connected"); 325 return service; 326 } 327 328 public static NetworkManagementService create(Context context) throws InterruptedException { 329 return create(context, NETD_SERVICE_NAME); 330 } 331 332 public void systemReady() { 333 if (DBG) { 334 final long start = System.currentTimeMillis(); 335 prepareNativeDaemon(); 336 final long delta = System.currentTimeMillis() - start; 337 Slog.d(TAG, "Prepared in " + delta + "ms"); 338 return; 339 } else { 340 prepareNativeDaemon(); 341 } 342 } 343 344 private IBatteryStats getBatteryStats() { 345 synchronized (this) { 346 if (mBatteryStats != null) { 347 return mBatteryStats; 348 } 349 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( 350 BatteryStats.SERVICE_NAME)); 351 return mBatteryStats; 352 } 353 } 354 355 @Override 356 public void registerObserver(INetworkManagementEventObserver observer) { 357 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 358 mObservers.register(observer); 359 } 360 361 @Override 362 public void unregisterObserver(INetworkManagementEventObserver observer) { 363 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 364 mObservers.unregister(observer); 365 } 366 367 /** 368 * Notify our observers of an interface status change 369 */ 370 private void notifyInterfaceStatusChanged(String iface, boolean up) { 371 final int length = mObservers.beginBroadcast(); 372 try { 373 for (int i = 0; i < length; i++) { 374 try { 375 mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up); 376 } catch (RemoteException | RuntimeException e) { 377 } 378 } 379 } finally { 380 mObservers.finishBroadcast(); 381 } 382 } 383 384 /** 385 * Notify our observers of an interface link state change 386 * (typically, an Ethernet cable has been plugged-in or unplugged). 387 */ 388 private void notifyInterfaceLinkStateChanged(String iface, boolean up) { 389 final int length = mObservers.beginBroadcast(); 390 try { 391 for (int i = 0; i < length; i++) { 392 try { 393 mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up); 394 } catch (RemoteException | RuntimeException e) { 395 } 396 } 397 } finally { 398 mObservers.finishBroadcast(); 399 } 400 } 401 402 /** 403 * Notify our observers of an interface addition. 404 */ 405 private void notifyInterfaceAdded(String iface) { 406 final int length = mObservers.beginBroadcast(); 407 try { 408 for (int i = 0; i < length; i++) { 409 try { 410 mObservers.getBroadcastItem(i).interfaceAdded(iface); 411 } catch (RemoteException | RuntimeException e) { 412 } 413 } 414 } finally { 415 mObservers.finishBroadcast(); 416 } 417 } 418 419 /** 420 * Notify our observers of an interface removal. 421 */ 422 private void notifyInterfaceRemoved(String iface) { 423 // netd already clears out quota and alerts for removed ifaces; update 424 // our sanity-checking state. 425 mActiveAlerts.remove(iface); 426 mActiveQuotas.remove(iface); 427 428 final int length = mObservers.beginBroadcast(); 429 try { 430 for (int i = 0; i < length; i++) { 431 try { 432 mObservers.getBroadcastItem(i).interfaceRemoved(iface); 433 } catch (RemoteException | RuntimeException e) { 434 } 435 } 436 } finally { 437 mObservers.finishBroadcast(); 438 } 439 } 440 441 /** 442 * Notify our observers of a limit reached. 443 */ 444 private void notifyLimitReached(String limitName, String iface) { 445 final int length = mObservers.beginBroadcast(); 446 try { 447 for (int i = 0; i < length; i++) { 448 try { 449 mObservers.getBroadcastItem(i).limitReached(limitName, iface); 450 } catch (RemoteException | RuntimeException e) { 451 } 452 } 453 } finally { 454 mObservers.finishBroadcast(); 455 } 456 } 457 458 /** 459 * Notify our observers of a change in the data activity state of the interface 460 */ 461 private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos, 462 boolean fromRadio) { 463 final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type); 464 if (isMobile) { 465 if (!fromRadio) { 466 if (mMobileActivityFromRadio) { 467 // If this call is not coming from a report from the radio itself, but we 468 // have previously received reports from the radio, then we will take the 469 // power state to just be whatever the radio last reported. 470 powerState = mLastPowerStateFromRadio; 471 } 472 } else { 473 mMobileActivityFromRadio = true; 474 } 475 if (mLastPowerStateFromRadio != powerState) { 476 mLastPowerStateFromRadio = powerState; 477 try { 478 getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos); 479 } catch (RemoteException e) { 480 } 481 } 482 } 483 484 if (ConnectivityManager.isNetworkTypeWifi(type)) { 485 if (mLastPowerStateFromWifi != powerState) { 486 mLastPowerStateFromWifi = powerState; 487 try { 488 getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos); 489 } catch (RemoteException e) { 490 } 491 } 492 } 493 494 boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM 495 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH; 496 497 if (!isMobile || fromRadio || !mMobileActivityFromRadio) { 498 // Report the change in data activity. We don't do this if this is a change 499 // on the mobile network, that is not coming from the radio itself, and we 500 // have previously seen change reports from the radio. In that case only 501 // the radio is the authority for the current state. 502 final int length = mObservers.beginBroadcast(); 503 try { 504 for (int i = 0; i < length; i++) { 505 try { 506 mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged( 507 Integer.toString(type), isActive, tsNanos); 508 } catch (RemoteException | RuntimeException e) { 509 } 510 } 511 } finally { 512 mObservers.finishBroadcast(); 513 } 514 } 515 516 boolean report = false; 517 synchronized (mIdleTimerLock) { 518 if (mActiveIdleTimers.isEmpty()) { 519 // If there are no idle timers, we are not monitoring activity, so we 520 // are always considered active. 521 isActive = true; 522 } 523 if (mNetworkActive != isActive) { 524 mNetworkActive = isActive; 525 report = isActive; 526 } 527 } 528 if (report) { 529 reportNetworkActive(); 530 } 531 } 532 533 // Sync the state of the given chain with the native daemon. 534 private void syncFirewallChainLocked(int chain, SparseIntArray uidFirewallRules, String name) { 535 int size = uidFirewallRules.size(); 536 if (size > 0) { 537 // Make a copy of the current rules, and then clear them. This is because 538 // setFirewallUidRuleInternal only pushes down rules to the native daemon if they are 539 // different from the current rules stored in the mUidFirewall*Rules array for the 540 // specified chain. If we don't clear the rules, setFirewallUidRuleInternal will do 541 // nothing. 542 final SparseIntArray rules = uidFirewallRules.clone(); 543 uidFirewallRules.clear(); 544 545 // Now push the rules. setFirewallUidRuleInternal will push each of these down to the 546 // native daemon, and also add them to the mUidFirewall*Rules array for the specified 547 // chain. 548 if (DBG) Slog.d(TAG, "Pushing " + size + " active firewall " + name + "UID rules"); 549 for (int i = 0; i < rules.size(); i++) { 550 setFirewallUidRuleInternal(chain, rules.keyAt(i), rules.valueAt(i)); 551 } 552 } 553 } 554 555 /** 556 * Prepare native daemon once connected, enabling modules and pushing any 557 * existing in-memory rules. 558 */ 559 private void prepareNativeDaemon() { 560 boolean nativeServiceAvailable = false; 561 try { 562 mNetdService = INetd.Stub.asInterface(ServiceManager.getService(NETD_SERVICE_NAME)); 563 nativeServiceAvailable = mNetdService.isAlive(); 564 } catch (RemoteException e) {} 565 if (!nativeServiceAvailable) { 566 Slog.wtf(TAG, "Can't connect to NativeNetdService " + NETD_SERVICE_NAME); 567 } 568 569 mBandwidthControlEnabled = false; 570 571 // only enable bandwidth control when support exists 572 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists(); 573 if (hasKernelSupport) { 574 Slog.d(TAG, "enabling bandwidth control"); 575 try { 576 mConnector.execute("bandwidth", "enable"); 577 mBandwidthControlEnabled = true; 578 } catch (NativeDaemonConnectorException e) { 579 Log.wtf(TAG, "problem enabling bandwidth controls", e); 580 } 581 } else { 582 Slog.i(TAG, "not enabling bandwidth control"); 583 } 584 585 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); 586 587 if (mBandwidthControlEnabled) { 588 try { 589 getBatteryStats().noteNetworkStatsEnabled(); 590 } catch (RemoteException e) { 591 } 592 } 593 594 try { 595 mConnector.execute("strict", "enable"); 596 mStrictEnabled = true; 597 } catch (NativeDaemonConnectorException e) { 598 Log.wtf(TAG, "Failed strict enable", e); 599 } 600 601 // push any existing quota or UID rules 602 synchronized (mQuotaLock) { 603 604 setDataSaverModeEnabled(mDataSaverMode); 605 606 int size = mActiveQuotas.size(); 607 if (size > 0) { 608 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules"); 609 final HashMap<String, Long> activeQuotas = mActiveQuotas; 610 mActiveQuotas = Maps.newHashMap(); 611 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) { 612 setInterfaceQuota(entry.getKey(), entry.getValue()); 613 } 614 } 615 616 size = mActiveAlerts.size(); 617 if (size > 0) { 618 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules"); 619 final HashMap<String, Long> activeAlerts = mActiveAlerts; 620 mActiveAlerts = Maps.newHashMap(); 621 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) { 622 setInterfaceAlert(entry.getKey(), entry.getValue()); 623 } 624 } 625 626 size = mUidRejectOnMetered.size(); 627 if (size > 0) { 628 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules"); 629 final SparseBooleanArray uidRejectOnQuota = mUidRejectOnMetered; 630 mUidRejectOnMetered = new SparseBooleanArray(); 631 for (int i = 0; i < uidRejectOnQuota.size(); i++) { 632 setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i), 633 uidRejectOnQuota.valueAt(i)); 634 } 635 } 636 637 size = mUidAllowOnMetered.size(); 638 if (size > 0) { 639 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules"); 640 final SparseBooleanArray uidAcceptOnQuota = mUidAllowOnMetered; 641 mUidAllowOnMetered = new SparseBooleanArray(); 642 for (int i = 0; i < uidAcceptOnQuota.size(); i++) { 643 setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i), 644 uidAcceptOnQuota.valueAt(i)); 645 } 646 } 647 648 size = mUidCleartextPolicy.size(); 649 if (size > 0) { 650 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies"); 651 final SparseIntArray local = mUidCleartextPolicy; 652 mUidCleartextPolicy = new SparseIntArray(); 653 for (int i = 0; i < local.size(); i++) { 654 setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i)); 655 } 656 } 657 658 setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); 659 660 syncFirewallChainLocked(FIREWALL_CHAIN_NONE, mUidFirewallRules, ""); 661 syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, mUidFirewallStandbyRules, "standby "); 662 syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mUidFirewallDozableRules, "dozable "); 663 syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, mUidFirewallPowerSaveRules, 664 "powersave "); 665 666 if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)) { 667 setFirewallChainEnabled(FIREWALL_CHAIN_STANDBY, true); 668 } 669 if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)) { 670 setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true); 671 } 672 if (mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)) { 673 setFirewallChainEnabled(FIREWALL_CHAIN_POWERSAVE, true); 674 } 675 } 676 } 677 678 /** 679 * Notify our observers of a new or updated interface address. 680 */ 681 private void notifyAddressUpdated(String iface, LinkAddress address) { 682 final int length = mObservers.beginBroadcast(); 683 try { 684 for (int i = 0; i < length; i++) { 685 try { 686 mObservers.getBroadcastItem(i).addressUpdated(iface, address); 687 } catch (RemoteException | RuntimeException e) { 688 } 689 } 690 } finally { 691 mObservers.finishBroadcast(); 692 } 693 } 694 695 /** 696 * Notify our observers of a deleted interface address. 697 */ 698 private void notifyAddressRemoved(String iface, LinkAddress address) { 699 final int length = mObservers.beginBroadcast(); 700 try { 701 for (int i = 0; i < length; i++) { 702 try { 703 mObservers.getBroadcastItem(i).addressRemoved(iface, address); 704 } catch (RemoteException | RuntimeException e) { 705 } 706 } 707 } finally { 708 mObservers.finishBroadcast(); 709 } 710 } 711 712 /** 713 * Notify our observers of DNS server information received. 714 */ 715 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) { 716 final int length = mObservers.beginBroadcast(); 717 try { 718 for (int i = 0; i < length; i++) { 719 try { 720 mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime, 721 addresses); 722 } catch (RemoteException | RuntimeException e) { 723 } 724 } 725 } finally { 726 mObservers.finishBroadcast(); 727 } 728 } 729 730 /** 731 * Notify our observers of a route change. 732 */ 733 private void notifyRouteChange(String action, RouteInfo route) { 734 final int length = mObservers.beginBroadcast(); 735 try { 736 for (int i = 0; i < length; i++) { 737 try { 738 if (action.equals("updated")) { 739 mObservers.getBroadcastItem(i).routeUpdated(route); 740 } else { 741 mObservers.getBroadcastItem(i).routeRemoved(route); 742 } 743 } catch (RemoteException | RuntimeException e) { 744 } 745 } 746 } finally { 747 mObservers.finishBroadcast(); 748 } 749 } 750 751 // 752 // Netd Callback handling 753 // 754 755 private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { 756 @Override 757 public void onDaemonConnected() { 758 Slog.i(TAG, "onDaemonConnected()"); 759 // event is dispatched from internal NDC thread, so we prepare the 760 // daemon back on main thread. 761 if (mConnectedSignal != null) { 762 mConnectedSignal.countDown(); 763 mConnectedSignal = null; 764 } else { 765 mFgHandler.post(new Runnable() { 766 @Override 767 public void run() { 768 prepareNativeDaemon(); 769 } 770 }); 771 } 772 } 773 774 @Override 775 public boolean onCheckHoldWakeLock(int code) { 776 return code == NetdResponseCode.InterfaceClassActivity; 777 } 778 779 @Override 780 public boolean onEvent(int code, String raw, String[] cooked) { 781 String errorMessage = String.format("Invalid event from daemon (%s)", raw); 782 switch (code) { 783 case NetdResponseCode.InterfaceChange: 784 /* 785 * a network interface change occured 786 * Format: "NNN Iface added <name>" 787 * "NNN Iface removed <name>" 788 * "NNN Iface changed <name> <up/down>" 789 * "NNN Iface linkstatus <name> <up/down>" 790 */ 791 if (cooked.length < 4 || !cooked[1].equals("Iface")) { 792 throw new IllegalStateException(errorMessage); 793 } 794 if (cooked[2].equals("added")) { 795 notifyInterfaceAdded(cooked[3]); 796 return true; 797 } else if (cooked[2].equals("removed")) { 798 notifyInterfaceRemoved(cooked[3]); 799 return true; 800 } else if (cooked[2].equals("changed") && cooked.length == 5) { 801 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); 802 return true; 803 } else if (cooked[2].equals("linkstate") && cooked.length == 5) { 804 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); 805 return true; 806 } 807 throw new IllegalStateException(errorMessage); 808 // break; 809 case NetdResponseCode.BandwidthControl: 810 /* 811 * Bandwidth control needs some attention 812 * Format: "NNN limit alert <alertName> <ifaceName>" 813 */ 814 if (cooked.length < 5 || !cooked[1].equals("limit")) { 815 throw new IllegalStateException(errorMessage); 816 } 817 if (cooked[2].equals("alert")) { 818 notifyLimitReached(cooked[3], cooked[4]); 819 return true; 820 } 821 throw new IllegalStateException(errorMessage); 822 // break; 823 case NetdResponseCode.InterfaceClassActivity: 824 /* 825 * An network interface class state changed (active/idle) 826 * Format: "NNN IfaceClass <active/idle> <label>" 827 */ 828 if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) { 829 throw new IllegalStateException(errorMessage); 830 } 831 long timestampNanos = 0; 832 if (cooked.length == 5) { 833 try { 834 timestampNanos = Long.parseLong(cooked[4]); 835 } catch(NumberFormatException ne) {} 836 } else { 837 timestampNanos = SystemClock.elapsedRealtimeNanos(); 838 } 839 boolean isActive = cooked[2].equals("active"); 840 notifyInterfaceClassActivity(Integer.parseInt(cooked[3]), 841 isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH 842 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, timestampNanos, false); 843 return true; 844 // break; 845 case NetdResponseCode.InterfaceAddressChange: 846 /* 847 * A network address change occurred 848 * Format: "NNN Address updated <addr> <iface> <flags> <scope>" 849 * "NNN Address removed <addr> <iface> <flags> <scope>" 850 */ 851 if (cooked.length < 7 || !cooked[1].equals("Address")) { 852 throw new IllegalStateException(errorMessage); 853 } 854 855 String iface = cooked[4]; 856 LinkAddress address; 857 try { 858 int flags = Integer.parseInt(cooked[5]); 859 int scope = Integer.parseInt(cooked[6]); 860 address = new LinkAddress(cooked[3], flags, scope); 861 } catch(NumberFormatException e) { // Non-numeric lifetime or scope. 862 throw new IllegalStateException(errorMessage, e); 863 } catch(IllegalArgumentException e) { // Malformed/invalid IP address. 864 throw new IllegalStateException(errorMessage, e); 865 } 866 867 if (cooked[2].equals("updated")) { 868 notifyAddressUpdated(iface, address); 869 } else { 870 notifyAddressRemoved(iface, address); 871 } 872 return true; 873 // break; 874 case NetdResponseCode.InterfaceDnsServerInfo: 875 /* 876 * Information about available DNS servers has been received. 877 * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>" 878 */ 879 long lifetime; // Actually a 32-bit unsigned integer. 880 881 if (cooked.length == 6 && 882 cooked[1].equals("DnsInfo") && 883 cooked[2].equals("servers")) { 884 try { 885 lifetime = Long.parseLong(cooked[4]); 886 } catch (NumberFormatException e) { 887 throw new IllegalStateException(errorMessage); 888 } 889 String[] servers = cooked[5].split(","); 890 notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers); 891 } 892 return true; 893 // break; 894 case NetdResponseCode.RouteChange: 895 /* 896 * A route has been updated or removed. 897 * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]" 898 */ 899 if (!cooked[1].equals("Route") || cooked.length < 6) { 900 throw new IllegalStateException(errorMessage); 901 } 902 903 String via = null; 904 String dev = null; 905 boolean valid = true; 906 for (int i = 4; (i + 1) < cooked.length && valid; i += 2) { 907 if (cooked[i].equals("dev")) { 908 if (dev == null) { 909 dev = cooked[i+1]; 910 } else { 911 valid = false; // Duplicate interface. 912 } 913 } else if (cooked[i].equals("via")) { 914 if (via == null) { 915 via = cooked[i+1]; 916 } else { 917 valid = false; // Duplicate gateway. 918 } 919 } else { 920 valid = false; // Unknown syntax. 921 } 922 } 923 if (valid) { 924 try { 925 // InetAddress.parseNumericAddress(null) inexplicably returns ::1. 926 InetAddress gateway = null; 927 if (via != null) gateway = InetAddress.parseNumericAddress(via); 928 RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev); 929 notifyRouteChange(cooked[2], route); 930 return true; 931 } catch (IllegalArgumentException e) {} 932 } 933 throw new IllegalStateException(errorMessage); 934 // break; 935 case NetdResponseCode.StrictCleartext: 936 final int uid = Integer.parseInt(cooked[1]); 937 final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]); 938 try { 939 ActivityManagerNative.getDefault().notifyCleartextNetwork(uid, firstPacket); 940 } catch (RemoteException ignored) { 941 } 942 break; 943 default: break; 944 } 945 return false; 946 } 947 } 948 949 950 // 951 // INetworkManagementService members 952 // 953 954 @Override 955 public String[] listInterfaces() { 956 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 957 try { 958 return NativeDaemonEvent.filterMessageList( 959 mConnector.executeForList("interface", "list"), InterfaceListResult); 960 } catch (NativeDaemonConnectorException e) { 961 throw e.rethrowAsParcelableException(); 962 } 963 } 964 965 @Override 966 public InterfaceConfiguration getInterfaceConfig(String iface) { 967 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 968 969 final NativeDaemonEvent event; 970 try { 971 event = mConnector.execute("interface", "getcfg", iface); 972 } catch (NativeDaemonConnectorException e) { 973 throw e.rethrowAsParcelableException(); 974 } 975 976 event.checkCode(InterfaceGetCfgResult); 977 978 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3 979 final StringTokenizer st = new StringTokenizer(event.getMessage()); 980 981 InterfaceConfiguration cfg; 982 try { 983 cfg = new InterfaceConfiguration(); 984 cfg.setHardwareAddress(st.nextToken(" ")); 985 InetAddress addr = null; 986 int prefixLength = 0; 987 try { 988 addr = NetworkUtils.numericToInetAddress(st.nextToken()); 989 } catch (IllegalArgumentException iae) { 990 Slog.e(TAG, "Failed to parse ipaddr", iae); 991 } 992 993 try { 994 prefixLength = Integer.parseInt(st.nextToken()); 995 } catch (NumberFormatException nfe) { 996 Slog.e(TAG, "Failed to parse prefixLength", nfe); 997 } 998 999 cfg.setLinkAddress(new LinkAddress(addr, prefixLength)); 1000 while (st.hasMoreTokens()) { 1001 cfg.setFlag(st.nextToken()); 1002 } 1003 } catch (NoSuchElementException nsee) { 1004 throw new IllegalStateException("Invalid response from daemon: " + event); 1005 } 1006 return cfg; 1007 } 1008 1009 @Override 1010 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { 1011 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1012 LinkAddress linkAddr = cfg.getLinkAddress(); 1013 if (linkAddr == null || linkAddr.getAddress() == null) { 1014 throw new IllegalStateException("Null LinkAddress given"); 1015 } 1016 1017 final Command cmd = new Command("interface", "setcfg", iface, 1018 linkAddr.getAddress().getHostAddress(), 1019 linkAddr.getPrefixLength()); 1020 for (String flag : cfg.getFlags()) { 1021 cmd.appendArg(flag); 1022 } 1023 1024 try { 1025 mConnector.execute(cmd); 1026 } catch (NativeDaemonConnectorException e) { 1027 throw e.rethrowAsParcelableException(); 1028 } 1029 } 1030 1031 @Override 1032 public void setInterfaceDown(String iface) { 1033 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1034 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 1035 ifcg.setInterfaceDown(); 1036 setInterfaceConfig(iface, ifcg); 1037 } 1038 1039 @Override 1040 public void setInterfaceUp(String iface) { 1041 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1042 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 1043 ifcg.setInterfaceUp(); 1044 setInterfaceConfig(iface, ifcg); 1045 } 1046 1047 @Override 1048 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { 1049 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1050 try { 1051 mConnector.execute( 1052 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable"); 1053 } catch (NativeDaemonConnectorException e) { 1054 throw e.rethrowAsParcelableException(); 1055 } 1056 } 1057 1058 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 1059 IPv6 addresses on interface down, but we need to do full clean up here */ 1060 @Override 1061 public void clearInterfaceAddresses(String iface) { 1062 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1063 try { 1064 mConnector.execute("interface", "clearaddrs", iface); 1065 } catch (NativeDaemonConnectorException e) { 1066 throw e.rethrowAsParcelableException(); 1067 } 1068 } 1069 1070 @Override 1071 public void enableIpv6(String iface) { 1072 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1073 try { 1074 mConnector.execute("interface", "ipv6", iface, "enable"); 1075 } catch (NativeDaemonConnectorException e) { 1076 throw e.rethrowAsParcelableException(); 1077 } 1078 } 1079 1080 @Override 1081 public void disableIpv6(String iface) { 1082 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1083 try { 1084 mConnector.execute("interface", "ipv6", iface, "disable"); 1085 } catch (NativeDaemonConnectorException e) { 1086 throw e.rethrowAsParcelableException(); 1087 } 1088 } 1089 1090 @Override 1091 public void setInterfaceIpv6NdOffload(String iface, boolean enable) { 1092 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1093 try { 1094 mConnector.execute( 1095 "interface", "ipv6ndoffload", iface, (enable ? "enable" : "disable")); 1096 } catch (NativeDaemonConnectorException e) { 1097 throw e.rethrowAsParcelableException(); 1098 } 1099 } 1100 1101 @Override 1102 public void addRoute(int netId, RouteInfo route) { 1103 modifyRoute("add", "" + netId, route); 1104 } 1105 1106 @Override 1107 public void removeRoute(int netId, RouteInfo route) { 1108 modifyRoute("remove", "" + netId, route); 1109 } 1110 1111 private void modifyRoute(String action, String netId, RouteInfo route) { 1112 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1113 1114 final Command cmd = new Command("network", "route", action, netId); 1115 1116 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr 1117 cmd.appendArg(route.getInterface()); 1118 cmd.appendArg(route.getDestination().toString()); 1119 1120 switch (route.getType()) { 1121 case RouteInfo.RTN_UNICAST: 1122 if (route.hasGateway()) { 1123 cmd.appendArg(route.getGateway().getHostAddress()); 1124 } 1125 break; 1126 case RouteInfo.RTN_UNREACHABLE: 1127 cmd.appendArg("unreachable"); 1128 break; 1129 case RouteInfo.RTN_THROW: 1130 cmd.appendArg("throw"); 1131 break; 1132 } 1133 1134 try { 1135 mConnector.execute(cmd); 1136 } catch (NativeDaemonConnectorException e) { 1137 throw e.rethrowAsParcelableException(); 1138 } 1139 } 1140 1141 private ArrayList<String> readRouteList(String filename) { 1142 FileInputStream fstream = null; 1143 ArrayList<String> list = new ArrayList<String>(); 1144 1145 try { 1146 fstream = new FileInputStream(filename); 1147 DataInputStream in = new DataInputStream(fstream); 1148 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 1149 String s; 1150 1151 // throw away the title line 1152 1153 while (((s = br.readLine()) != null) && (s.length() != 0)) { 1154 list.add(s); 1155 } 1156 } catch (IOException ex) { 1157 // return current list, possibly empty 1158 } finally { 1159 if (fstream != null) { 1160 try { 1161 fstream.close(); 1162 } catch (IOException ex) {} 1163 } 1164 } 1165 1166 return list; 1167 } 1168 1169 @Override 1170 public void setMtu(String iface, int mtu) { 1171 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1172 1173 final NativeDaemonEvent event; 1174 try { 1175 event = mConnector.execute("interface", "setmtu", iface, mtu); 1176 } catch (NativeDaemonConnectorException e) { 1177 throw e.rethrowAsParcelableException(); 1178 } 1179 } 1180 1181 @Override 1182 public void shutdown() { 1183 // TODO: remove from aidl if nobody calls externally 1184 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG); 1185 1186 Slog.i(TAG, "Shutting down"); 1187 } 1188 1189 @Override 1190 public boolean getIpForwardingEnabled() throws IllegalStateException{ 1191 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1192 1193 final NativeDaemonEvent event; 1194 try { 1195 event = mConnector.execute("ipfwd", "status"); 1196 } catch (NativeDaemonConnectorException e) { 1197 throw e.rethrowAsParcelableException(); 1198 } 1199 1200 // 211 Forwarding enabled 1201 event.checkCode(IpFwdStatusResult); 1202 return event.getMessage().endsWith("enabled"); 1203 } 1204 1205 @Override 1206 public void setIpForwardingEnabled(boolean enable) { 1207 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1208 try { 1209 mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering"); 1210 } catch (NativeDaemonConnectorException e) { 1211 throw e.rethrowAsParcelableException(); 1212 } 1213 } 1214 1215 @Override 1216 public void startTethering(String[] dhcpRange) { 1217 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1218 // cmd is "tether start first_start first_stop second_start second_stop ..." 1219 // an odd number of addrs will fail 1220 1221 final Command cmd = new Command("tether", "start"); 1222 for (String d : dhcpRange) { 1223 cmd.appendArg(d); 1224 } 1225 1226 try { 1227 mConnector.execute(cmd); 1228 } catch (NativeDaemonConnectorException e) { 1229 throw e.rethrowAsParcelableException(); 1230 } 1231 } 1232 1233 @Override 1234 public void stopTethering() { 1235 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1236 try { 1237 mConnector.execute("tether", "stop"); 1238 } catch (NativeDaemonConnectorException e) { 1239 throw e.rethrowAsParcelableException(); 1240 } 1241 } 1242 1243 @Override 1244 public boolean isTetheringStarted() { 1245 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1246 1247 final NativeDaemonEvent event; 1248 try { 1249 event = mConnector.execute("tether", "status"); 1250 } catch (NativeDaemonConnectorException e) { 1251 throw e.rethrowAsParcelableException(); 1252 } 1253 1254 // 210 Tethering services started 1255 event.checkCode(TetherStatusResult); 1256 return event.getMessage().endsWith("started"); 1257 } 1258 1259 @Override 1260 public void tetherInterface(String iface) { 1261 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1262 try { 1263 mConnector.execute("tether", "interface", "add", iface); 1264 } catch (NativeDaemonConnectorException e) { 1265 throw e.rethrowAsParcelableException(); 1266 } 1267 List<RouteInfo> routes = new ArrayList<RouteInfo>(); 1268 // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it 1269 // suitable to use as a route destination. 1270 routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface)); 1271 addInterfaceToLocalNetwork(iface, routes); 1272 } 1273 1274 @Override 1275 public void untetherInterface(String iface) { 1276 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1277 try { 1278 mConnector.execute("tether", "interface", "remove", iface); 1279 } catch (NativeDaemonConnectorException e) { 1280 throw e.rethrowAsParcelableException(); 1281 } 1282 removeInterfaceFromLocalNetwork(iface); 1283 } 1284 1285 @Override 1286 public String[] listTetheredInterfaces() { 1287 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1288 try { 1289 return NativeDaemonEvent.filterMessageList( 1290 mConnector.executeForList("tether", "interface", "list"), 1291 TetherInterfaceListResult); 1292 } catch (NativeDaemonConnectorException e) { 1293 throw e.rethrowAsParcelableException(); 1294 } 1295 } 1296 1297 @Override 1298 public void setDnsForwarders(Network network, String[] dns) { 1299 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1300 1301 int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET; 1302 final Command cmd = new Command("tether", "dns", "set", netId); 1303 1304 for (String s : dns) { 1305 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress()); 1306 } 1307 1308 try { 1309 mConnector.execute(cmd); 1310 } catch (NativeDaemonConnectorException e) { 1311 throw e.rethrowAsParcelableException(); 1312 } 1313 } 1314 1315 @Override 1316 public String[] getDnsForwarders() { 1317 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1318 try { 1319 return NativeDaemonEvent.filterMessageList( 1320 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult); 1321 } catch (NativeDaemonConnectorException e) { 1322 throw e.rethrowAsParcelableException(); 1323 } 1324 } 1325 1326 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) { 1327 ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size()); 1328 for (InterfaceAddress ia : addresses) { 1329 if (!ia.getAddress().isLinkLocalAddress()) 1330 filtered.add(ia); 1331 } 1332 return filtered; 1333 } 1334 1335 private void modifyInterfaceForward(boolean add, String fromIface, String toIface) { 1336 final Command cmd = new Command("ipfwd", add ? "add" : "remove", fromIface, toIface); 1337 try { 1338 mConnector.execute(cmd); 1339 } catch (NativeDaemonConnectorException e) { 1340 throw e.rethrowAsParcelableException(); 1341 } 1342 } 1343 1344 @Override 1345 public void startInterfaceForwarding(String fromIface, String toIface) { 1346 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1347 modifyInterfaceForward(true, fromIface, toIface); 1348 } 1349 1350 @Override 1351 public void stopInterfaceForwarding(String fromIface, String toIface) { 1352 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1353 modifyInterfaceForward(false, fromIface, toIface); 1354 } 1355 1356 private void modifyNat(String action, String internalInterface, String externalInterface) 1357 throws SocketException { 1358 final Command cmd = new Command("nat", action, internalInterface, externalInterface); 1359 1360 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName( 1361 internalInterface); 1362 if (internalNetworkInterface == null) { 1363 cmd.appendArg("0"); 1364 } else { 1365 // Don't touch link-local routes, as link-local addresses aren't routable, 1366 // kernel creates link-local routes on all interfaces automatically 1367 List<InterfaceAddress> interfaceAddresses = excludeLinkLocal( 1368 internalNetworkInterface.getInterfaceAddresses()); 1369 cmd.appendArg(interfaceAddresses.size()); 1370 for (InterfaceAddress ia : interfaceAddresses) { 1371 InetAddress addr = NetworkUtils.getNetworkPart( 1372 ia.getAddress(), ia.getNetworkPrefixLength()); 1373 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength()); 1374 } 1375 } 1376 1377 try { 1378 mConnector.execute(cmd); 1379 } catch (NativeDaemonConnectorException e) { 1380 throw e.rethrowAsParcelableException(); 1381 } 1382 } 1383 1384 @Override 1385 public void enableNat(String internalInterface, String externalInterface) { 1386 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1387 try { 1388 modifyNat("enable", internalInterface, externalInterface); 1389 } catch (SocketException e) { 1390 throw new IllegalStateException(e); 1391 } 1392 } 1393 1394 @Override 1395 public void disableNat(String internalInterface, String externalInterface) { 1396 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1397 try { 1398 modifyNat("disable", internalInterface, externalInterface); 1399 } catch (SocketException e) { 1400 throw new IllegalStateException(e); 1401 } 1402 } 1403 1404 @Override 1405 public String[] listTtys() { 1406 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1407 try { 1408 return NativeDaemonEvent.filterMessageList( 1409 mConnector.executeForList("list_ttys"), TtyListResult); 1410 } catch (NativeDaemonConnectorException e) { 1411 throw e.rethrowAsParcelableException(); 1412 } 1413 } 1414 1415 @Override 1416 public void attachPppd( 1417 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) { 1418 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1419 try { 1420 mConnector.execute("pppd", "attach", tty, 1421 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 1422 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 1423 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 1424 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()); 1425 } catch (NativeDaemonConnectorException e) { 1426 throw e.rethrowAsParcelableException(); 1427 } 1428 } 1429 1430 @Override 1431 public void detachPppd(String tty) { 1432 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1433 try { 1434 mConnector.execute("pppd", "detach", tty); 1435 } catch (NativeDaemonConnectorException e) { 1436 throw e.rethrowAsParcelableException(); 1437 } 1438 } 1439 1440 /** 1441 * Private method used to call execute for a command given the provided arguments. 1442 * 1443 * This function checks the returned NativeDaemonEvent for the provided expected response code 1444 * and message. If either of these is not correct, an error is logged. 1445 * 1446 * @param String command The command to execute. 1447 * @param Object[] args If needed, arguments for the command to execute. 1448 * @param int expectedResponseCode The code expected to be returned in the corresponding event. 1449 * @param String expectedResponseMessage The message expected in the returned event. 1450 * @param String logMsg The message to log as an error (TAG will be applied). 1451 */ 1452 private void executeOrLogWithMessage(String command, Object[] args, 1453 int expectedResponseCode, String expectedResponseMessage, String logMsg) 1454 throws NativeDaemonConnectorException { 1455 NativeDaemonEvent event = mConnector.execute(command, args); 1456 if (event.getCode() != expectedResponseCode 1457 || !event.getMessage().equals(expectedResponseMessage)) { 1458 Log.e(TAG, logMsg + ": event = " + event); 1459 } 1460 } 1461 1462 @Override 1463 public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { 1464 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1465 Object[] args; 1466 String logMsg = "startAccessPoint Error setting up softap"; 1467 try { 1468 if (wifiConfig == null) { 1469 args = new Object[] {"set", wlanIface}; 1470 } else { 1471 args = new Object[] {"set", wlanIface, wifiConfig.SSID, 1472 "broadcast", Integer.toString(wifiConfig.apChannel), 1473 getSecurityType(wifiConfig), new SensitiveArg(wifiConfig.preSharedKey)}; 1474 } 1475 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult, 1476 SOFT_AP_COMMAND_SUCCESS, logMsg); 1477 1478 logMsg = "startAccessPoint Error starting softap"; 1479 args = new Object[] {"startap"}; 1480 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult, 1481 SOFT_AP_COMMAND_SUCCESS, logMsg); 1482 } catch (NativeDaemonConnectorException e) { 1483 throw e.rethrowAsParcelableException(); 1484 } 1485 } 1486 1487 private static String getSecurityType(WifiConfiguration wifiConfig) { 1488 switch (wifiConfig.getAuthType()) { 1489 case KeyMgmt.WPA_PSK: 1490 return "wpa-psk"; 1491 case KeyMgmt.WPA2_PSK: 1492 return "wpa2-psk"; 1493 default: 1494 return "open"; 1495 } 1496 } 1497 1498 /* @param mode can be "AP", "STA" or "P2P" */ 1499 @Override 1500 public void wifiFirmwareReload(String wlanIface, String mode) { 1501 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1502 Object[] args = {"fwreload", wlanIface, mode}; 1503 String logMsg = "wifiFirmwareReload Error reloading " 1504 + wlanIface + " fw in " + mode + " mode"; 1505 try { 1506 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult, 1507 SOFT_AP_COMMAND_SUCCESS, logMsg); 1508 } catch (NativeDaemonConnectorException e) { 1509 throw e.rethrowAsParcelableException(); 1510 } 1511 1512 // Ensure that before we return from this command, any asynchronous 1513 // notifications generated before the command completed have been 1514 // processed by all NetworkManagementEventObservers. 1515 mConnector.waitForCallbacks(); 1516 } 1517 1518 @Override 1519 public void stopAccessPoint(String wlanIface) { 1520 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1521 Object[] args = {"stopap"}; 1522 String logMsg = "stopAccessPoint Error stopping softap"; 1523 1524 try { 1525 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult, 1526 SOFT_AP_COMMAND_SUCCESS, logMsg); 1527 wifiFirmwareReload(wlanIface, "STA"); 1528 } catch (NativeDaemonConnectorException e) { 1529 throw e.rethrowAsParcelableException(); 1530 } 1531 } 1532 1533 @Override 1534 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { 1535 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1536 Object[] args; 1537 String logMsg = "startAccessPoint Error setting up softap"; 1538 try { 1539 if (wifiConfig == null) { 1540 args = new Object[] {"set", wlanIface}; 1541 } else { 1542 // TODO: understand why this is set to "6" instead of 1543 // Integer.toString(wifiConfig.apChannel) as in startAccessPoint 1544 // TODO: should startAccessPoint call this instead of repeating code? 1545 args = new Object[] {"set", wlanIface, wifiConfig.SSID, 1546 "broadcast", "6", 1547 getSecurityType(wifiConfig), new SensitiveArg(wifiConfig.preSharedKey)}; 1548 } 1549 executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult, 1550 SOFT_AP_COMMAND_SUCCESS, logMsg); 1551 } catch (NativeDaemonConnectorException e) { 1552 throw e.rethrowAsParcelableException(); 1553 } 1554 } 1555 1556 @Override 1557 public void addIdleTimer(String iface, int timeout, final int type) { 1558 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1559 1560 if (DBG) Slog.d(TAG, "Adding idletimer"); 1561 1562 synchronized (mIdleTimerLock) { 1563 IdleTimerParams params = mActiveIdleTimers.get(iface); 1564 if (params != null) { 1565 // the interface already has idletimer, update network count 1566 params.networkCount++; 1567 return; 1568 } 1569 1570 try { 1571 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout), 1572 Integer.toString(type)); 1573 } catch (NativeDaemonConnectorException e) { 1574 throw e.rethrowAsParcelableException(); 1575 } 1576 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type)); 1577 1578 // Networks start up. 1579 if (ConnectivityManager.isNetworkTypeMobile(type)) { 1580 mNetworkActive = false; 1581 } 1582 mDaemonHandler.post(new Runnable() { 1583 @Override public void run() { 1584 notifyInterfaceClassActivity(type, 1585 DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 1586 SystemClock.elapsedRealtimeNanos(), false); 1587 } 1588 }); 1589 } 1590 } 1591 1592 @Override 1593 public void removeIdleTimer(String iface) { 1594 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1595 1596 if (DBG) Slog.d(TAG, "Removing idletimer"); 1597 1598 synchronized (mIdleTimerLock) { 1599 final IdleTimerParams params = mActiveIdleTimers.get(iface); 1600 if (params == null || --(params.networkCount) > 0) { 1601 return; 1602 } 1603 1604 try { 1605 mConnector.execute("idletimer", "remove", iface, 1606 Integer.toString(params.timeout), Integer.toString(params.type)); 1607 } catch (NativeDaemonConnectorException e) { 1608 throw e.rethrowAsParcelableException(); 1609 } 1610 mActiveIdleTimers.remove(iface); 1611 mDaemonHandler.post(new Runnable() { 1612 @Override public void run() { 1613 notifyInterfaceClassActivity(params.type, 1614 DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, 1615 SystemClock.elapsedRealtimeNanos(), false); 1616 } 1617 }); 1618 } 1619 } 1620 1621 @Override 1622 public NetworkStats getNetworkStatsSummaryDev() { 1623 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1624 try { 1625 return mStatsFactory.readNetworkStatsSummaryDev(); 1626 } catch (IOException e) { 1627 throw new IllegalStateException(e); 1628 } 1629 } 1630 1631 @Override 1632 public NetworkStats getNetworkStatsSummaryXt() { 1633 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1634 try { 1635 return mStatsFactory.readNetworkStatsSummaryXt(); 1636 } catch (IOException e) { 1637 throw new IllegalStateException(e); 1638 } 1639 } 1640 1641 @Override 1642 public NetworkStats getNetworkStatsDetail() { 1643 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1644 try { 1645 return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); 1646 } catch (IOException e) { 1647 throw new IllegalStateException(e); 1648 } 1649 } 1650 1651 @Override 1652 public void setInterfaceQuota(String iface, long quotaBytes) { 1653 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1654 1655 // silently discard when control disabled 1656 // TODO: eventually migrate to be always enabled 1657 if (!mBandwidthControlEnabled) return; 1658 1659 synchronized (mQuotaLock) { 1660 if (mActiveQuotas.containsKey(iface)) { 1661 throw new IllegalStateException("iface " + iface + " already has quota"); 1662 } 1663 1664 try { 1665 // TODO: support quota shared across interfaces 1666 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes); 1667 mActiveQuotas.put(iface, quotaBytes); 1668 } catch (NativeDaemonConnectorException e) { 1669 throw e.rethrowAsParcelableException(); 1670 } 1671 } 1672 } 1673 1674 @Override 1675 public void removeInterfaceQuota(String iface) { 1676 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1677 1678 // silently discard when control disabled 1679 // TODO: eventually migrate to be always enabled 1680 if (!mBandwidthControlEnabled) return; 1681 1682 synchronized (mQuotaLock) { 1683 if (!mActiveQuotas.containsKey(iface)) { 1684 // TODO: eventually consider throwing 1685 return; 1686 } 1687 1688 mActiveQuotas.remove(iface); 1689 mActiveAlerts.remove(iface); 1690 1691 try { 1692 // TODO: support quota shared across interfaces 1693 mConnector.execute("bandwidth", "removeiquota", iface); 1694 } catch (NativeDaemonConnectorException e) { 1695 throw e.rethrowAsParcelableException(); 1696 } 1697 } 1698 } 1699 1700 @Override 1701 public void setInterfaceAlert(String iface, long alertBytes) { 1702 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1703 1704 // silently discard when control disabled 1705 // TODO: eventually migrate to be always enabled 1706 if (!mBandwidthControlEnabled) return; 1707 1708 // quick sanity check 1709 if (!mActiveQuotas.containsKey(iface)) { 1710 throw new IllegalStateException("setting alert requires existing quota on iface"); 1711 } 1712 1713 synchronized (mQuotaLock) { 1714 if (mActiveAlerts.containsKey(iface)) { 1715 throw new IllegalStateException("iface " + iface + " already has alert"); 1716 } 1717 1718 try { 1719 // TODO: support alert shared across interfaces 1720 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes); 1721 mActiveAlerts.put(iface, alertBytes); 1722 } catch (NativeDaemonConnectorException e) { 1723 throw e.rethrowAsParcelableException(); 1724 } 1725 } 1726 } 1727 1728 @Override 1729 public void removeInterfaceAlert(String iface) { 1730 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1731 1732 // silently discard when control disabled 1733 // TODO: eventually migrate to be always enabled 1734 if (!mBandwidthControlEnabled) return; 1735 1736 synchronized (mQuotaLock) { 1737 if (!mActiveAlerts.containsKey(iface)) { 1738 // TODO: eventually consider throwing 1739 return; 1740 } 1741 1742 try { 1743 // TODO: support alert shared across interfaces 1744 mConnector.execute("bandwidth", "removeinterfacealert", iface); 1745 mActiveAlerts.remove(iface); 1746 } catch (NativeDaemonConnectorException e) { 1747 throw e.rethrowAsParcelableException(); 1748 } 1749 } 1750 } 1751 1752 @Override 1753 public void setGlobalAlert(long alertBytes) { 1754 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1755 1756 // silently discard when control disabled 1757 // TODO: eventually migrate to be always enabled 1758 if (!mBandwidthControlEnabled) return; 1759 1760 try { 1761 mConnector.execute("bandwidth", "setglobalalert", alertBytes); 1762 } catch (NativeDaemonConnectorException e) { 1763 throw e.rethrowAsParcelableException(); 1764 } 1765 } 1766 1767 private void setUidOnMeteredNetworkList(SparseBooleanArray quotaList, int uid, 1768 boolean blacklist, boolean enable) { 1769 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1770 1771 // silently discard when control disabled 1772 // TODO: eventually migrate to be always enabled 1773 if (!mBandwidthControlEnabled) return; 1774 1775 final String chain = blacklist ? "naughtyapps" : "niceapps"; 1776 final String suffix = enable ? "add" : "remove"; 1777 1778 synchronized (mQuotaLock) { 1779 final boolean oldEnable = quotaList.get(uid, false); 1780 if (oldEnable == enable) { 1781 // TODO: eventually consider throwing 1782 return; 1783 } 1784 1785 try { 1786 mConnector.execute("bandwidth", suffix + chain, uid); 1787 if (enable) { 1788 quotaList.put(uid, true); 1789 } else { 1790 quotaList.delete(uid); 1791 } 1792 } catch (NativeDaemonConnectorException e) { 1793 throw e.rethrowAsParcelableException(); 1794 } 1795 } 1796 } 1797 1798 @Override 1799 public void setUidMeteredNetworkBlacklist(int uid, boolean enable) { 1800 setUidOnMeteredNetworkList(mUidRejectOnMetered, uid, true, enable); 1801 } 1802 1803 @Override 1804 public void setUidMeteredNetworkWhitelist(int uid, boolean enable) { 1805 setUidOnMeteredNetworkList(mUidAllowOnMetered, uid, false, enable); 1806 } 1807 1808 @Override 1809 public boolean setDataSaverModeEnabled(boolean enable) { 1810 if (DBG) Log.d(TAG, "setDataSaverMode: " + enable); 1811 synchronized (mQuotaLock) { 1812 if (mDataSaverMode == enable) { 1813 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode); 1814 return true; 1815 } 1816 try { 1817 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable); 1818 if (changed) { 1819 mDataSaverMode = enable; 1820 } else { 1821 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed"); 1822 } 1823 return changed; 1824 } catch (RemoteException e) { 1825 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e); 1826 return false; 1827 } 1828 } 1829 } 1830 1831 @Override 1832 public void setUidCleartextNetworkPolicy(int uid, int policy) { 1833 if (Binder.getCallingUid() != uid) { 1834 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1835 } 1836 1837 synchronized (mQuotaLock) { 1838 final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT); 1839 if (oldPolicy == policy) { 1840 return; 1841 } 1842 1843 if (!mStrictEnabled) { 1844 // Module isn't enabled yet; stash the requested policy away to 1845 // apply later once the daemon is connected. 1846 mUidCleartextPolicy.put(uid, policy); 1847 return; 1848 } 1849 1850 final String policyString; 1851 switch (policy) { 1852 case StrictMode.NETWORK_POLICY_ACCEPT: 1853 policyString = "accept"; 1854 break; 1855 case StrictMode.NETWORK_POLICY_LOG: 1856 policyString = "log"; 1857 break; 1858 case StrictMode.NETWORK_POLICY_REJECT: 1859 policyString = "reject"; 1860 break; 1861 default: 1862 throw new IllegalArgumentException("Unknown policy " + policy); 1863 } 1864 1865 try { 1866 mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString); 1867 mUidCleartextPolicy.put(uid, policy); 1868 } catch (NativeDaemonConnectorException e) { 1869 throw e.rethrowAsParcelableException(); 1870 } 1871 } 1872 } 1873 1874 @Override 1875 public boolean isBandwidthControlEnabled() { 1876 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1877 return mBandwidthControlEnabled; 1878 } 1879 1880 @Override 1881 public NetworkStats getNetworkStatsUidDetail(int uid) { 1882 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1883 try { 1884 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null); 1885 } catch (IOException e) { 1886 throw new IllegalStateException(e); 1887 } 1888 } 1889 1890 @Override 1891 public NetworkStats getNetworkStatsTethering() { 1892 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1893 1894 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1895 try { 1896 final NativeDaemonEvent[] events = mConnector.executeForList( 1897 "bandwidth", "gettetherstats"); 1898 for (NativeDaemonEvent event : events) { 1899 if (event.getCode() != TetheringStatsListResult) continue; 1900 1901 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets 1902 final StringTokenizer tok = new StringTokenizer(event.getMessage()); 1903 try { 1904 final String ifaceIn = tok.nextToken(); 1905 final String ifaceOut = tok.nextToken(); 1906 1907 final NetworkStats.Entry entry = new NetworkStats.Entry(); 1908 entry.iface = ifaceOut; 1909 entry.uid = UID_TETHERING; 1910 entry.set = SET_DEFAULT; 1911 entry.tag = TAG_NONE; 1912 entry.rxBytes = Long.parseLong(tok.nextToken()); 1913 entry.rxPackets = Long.parseLong(tok.nextToken()); 1914 entry.txBytes = Long.parseLong(tok.nextToken()); 1915 entry.txPackets = Long.parseLong(tok.nextToken()); 1916 stats.combineValues(entry); 1917 } catch (NoSuchElementException e) { 1918 throw new IllegalStateException("problem parsing tethering stats: " + event); 1919 } catch (NumberFormatException e) { 1920 throw new IllegalStateException("problem parsing tethering stats: " + event); 1921 } 1922 } 1923 } catch (NativeDaemonConnectorException e) { 1924 throw e.rethrowAsParcelableException(); 1925 } 1926 return stats; 1927 } 1928 1929 @Override 1930 public void setDnsServersForNetwork(int netId, String[] servers, String domains) { 1931 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1932 1933 Command cmd; 1934 if (servers.length > 0) { 1935 cmd = new Command("resolver", "setnetdns", netId, 1936 (domains == null ? "" : domains)); 1937 for (String s : servers) { 1938 InetAddress a = NetworkUtils.numericToInetAddress(s); 1939 if (a.isAnyLocalAddress() == false) { 1940 cmd.appendArg(a.getHostAddress()); 1941 } 1942 } 1943 } else { 1944 cmd = new Command("resolver", "clearnetdns", netId); 1945 } 1946 1947 try { 1948 mConnector.execute(cmd); 1949 } catch (NativeDaemonConnectorException e) { 1950 throw e.rethrowAsParcelableException(); 1951 } 1952 } 1953 1954 @Override 1955 public void addVpnUidRanges(int netId, UidRange[] ranges) { 1956 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1957 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 1958 argv[0] = "users"; 1959 argv[1] = "add"; 1960 argv[2] = netId; 1961 int argc = 3; 1962 // Avoid overly long commands by limiting number of UID ranges per command. 1963 for (int i = 0; i < ranges.length; i++) { 1964 argv[argc++] = ranges[i].toString(); 1965 if (i == (ranges.length - 1) || argc == argv.length) { 1966 try { 1967 mConnector.execute("network", Arrays.copyOf(argv, argc)); 1968 } catch (NativeDaemonConnectorException e) { 1969 throw e.rethrowAsParcelableException(); 1970 } 1971 argc = 3; 1972 } 1973 } 1974 } 1975 1976 @Override 1977 public void removeVpnUidRanges(int netId, UidRange[] ranges) { 1978 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1979 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 1980 argv[0] = "users"; 1981 argv[1] = "remove"; 1982 argv[2] = netId; 1983 int argc = 3; 1984 // Avoid overly long commands by limiting number of UID ranges per command. 1985 for (int i = 0; i < ranges.length; i++) { 1986 argv[argc++] = ranges[i].toString(); 1987 if (i == (ranges.length - 1) || argc == argv.length) { 1988 try { 1989 mConnector.execute("network", Arrays.copyOf(argv, argc)); 1990 } catch (NativeDaemonConnectorException e) { 1991 throw e.rethrowAsParcelableException(); 1992 } 1993 argc = 3; 1994 } 1995 } 1996 } 1997 1998 @Override 1999 public void setFirewallEnabled(boolean enabled) { 2000 enforceSystemUid(); 2001 try { 2002 mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist"); 2003 mFirewallEnabled = enabled; 2004 } catch (NativeDaemonConnectorException e) { 2005 throw e.rethrowAsParcelableException(); 2006 } 2007 } 2008 2009 @Override 2010 public boolean isFirewallEnabled() { 2011 enforceSystemUid(); 2012 return mFirewallEnabled; 2013 } 2014 2015 @Override 2016 public void setFirewallInterfaceRule(String iface, boolean allow) { 2017 enforceSystemUid(); 2018 Preconditions.checkState(mFirewallEnabled); 2019 final String rule = allow ? "allow" : "deny"; 2020 try { 2021 mConnector.execute("firewall", "set_interface_rule", iface, rule); 2022 } catch (NativeDaemonConnectorException e) { 2023 throw e.rethrowAsParcelableException(); 2024 } 2025 } 2026 2027 @Override 2028 public void setFirewallEgressSourceRule(String addr, boolean allow) { 2029 enforceSystemUid(); 2030 Preconditions.checkState(mFirewallEnabled); 2031 final String rule = allow ? "allow" : "deny"; 2032 try { 2033 mConnector.execute("firewall", "set_egress_source_rule", addr, rule); 2034 } catch (NativeDaemonConnectorException e) { 2035 throw e.rethrowAsParcelableException(); 2036 } 2037 } 2038 2039 @Override 2040 public void setFirewallEgressDestRule(String addr, int port, boolean allow) { 2041 enforceSystemUid(); 2042 Preconditions.checkState(mFirewallEnabled); 2043 final String rule = allow ? "allow" : "deny"; 2044 try { 2045 mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule); 2046 } catch (NativeDaemonConnectorException e) { 2047 throw e.rethrowAsParcelableException(); 2048 } 2049 } 2050 2051 private void closeSocketsForFirewallChainLocked(int chain, String chainName) { 2052 // UID ranges to close sockets on. 2053 UidRange[] ranges; 2054 // UID ranges whose sockets we won't touch. 2055 int[] exemptUids; 2056 2057 final SparseIntArray rules = getUidFirewallRules(chain); 2058 int numUids = 0; 2059 2060 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) { 2061 // Close all sockets on all non-system UIDs... 2062 ranges = new UidRange[] { 2063 // TODO: is there a better way of finding all existing users? If so, we could 2064 // specify their ranges here. 2065 new UidRange(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE), 2066 }; 2067 // ... except for the UIDs that have allow rules. 2068 exemptUids = new int[rules.size()]; 2069 for (int i = 0; i < exemptUids.length; i++) { 2070 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { 2071 exemptUids[numUids] = rules.keyAt(i); 2072 numUids++; 2073 } 2074 } 2075 // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length. 2076 // But the code does not guarantee this in any way, and at least in one case - if we add 2077 // a UID rule to the firewall, and then disable the firewall - the chains can contain 2078 // the wrong type of rule. In this case, don't close connections that we shouldn't. 2079 // 2080 // TODO: tighten up this code by ensuring we never set the wrong type of rule, and 2081 // fix setFirewallEnabled to grab mQuotaLock and clear rules. 2082 if (numUids != exemptUids.length) { 2083 exemptUids = Arrays.copyOf(exemptUids, numUids); 2084 } 2085 } else { 2086 // Close sockets for every UID that has a deny rule... 2087 ranges = new UidRange[rules.size()]; 2088 for (int i = 0; i < ranges.length; i++) { 2089 if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_DENY) { 2090 int uid = rules.keyAt(i); 2091 ranges[numUids] = new UidRange(uid, uid); 2092 numUids++; 2093 } 2094 } 2095 // As above; usually numUids == ranges.length, but not always. 2096 if (numUids != ranges.length) { 2097 ranges = Arrays.copyOf(ranges, numUids); 2098 } 2099 // ... with no exceptions. 2100 exemptUids = new int[0]; 2101 } 2102 2103 try { 2104 mNetdService.socketDestroy(ranges, exemptUids); 2105 } catch(RemoteException | ServiceSpecificException e) { 2106 Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e); 2107 } 2108 } 2109 2110 @Override 2111 public void setFirewallChainEnabled(int chain, boolean enable) { 2112 enforceSystemUid(); 2113 synchronized (mQuotaLock) { 2114 if (mFirewallChainStates.get(chain) == enable) { 2115 // All is the same, nothing to do. This relies on the fact that netd has child 2116 // chains default detached. 2117 return; 2118 } 2119 mFirewallChainStates.put(chain, enable); 2120 2121 final String operation = enable ? "enable_chain" : "disable_chain"; 2122 final String chainName; 2123 switch(chain) { 2124 case FIREWALL_CHAIN_STANDBY: 2125 chainName = FIREWALL_CHAIN_NAME_STANDBY; 2126 break; 2127 case FIREWALL_CHAIN_DOZABLE: 2128 chainName = FIREWALL_CHAIN_NAME_DOZABLE; 2129 break; 2130 case FIREWALL_CHAIN_POWERSAVE: 2131 chainName = FIREWALL_CHAIN_NAME_POWERSAVE; 2132 break; 2133 default: 2134 throw new IllegalArgumentException("Bad child chain: " + chain); 2135 } 2136 2137 try { 2138 mConnector.execute("firewall", operation, chainName); 2139 } catch (NativeDaemonConnectorException e) { 2140 throw e.rethrowAsParcelableException(); 2141 } 2142 2143 // Close any sockets that were opened by the affected UIDs. This has to be done after 2144 // disabling network connectivity, in case they react to the socket close by reopening 2145 // the connection and race with the iptables commands that enable the firewall. All 2146 // whitelist and blacklist chains allow RSTs through. 2147 if (enable) { 2148 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName); 2149 closeSocketsForFirewallChainLocked(chain, chainName); 2150 } 2151 } 2152 } 2153 2154 private int getFirewallType(int chain) { 2155 switch (chain) { 2156 case FIREWALL_CHAIN_STANDBY: 2157 return FIREWALL_TYPE_BLACKLIST; 2158 case FIREWALL_CHAIN_DOZABLE: 2159 return FIREWALL_TYPE_WHITELIST; 2160 case FIREWALL_CHAIN_POWERSAVE: 2161 return FIREWALL_TYPE_WHITELIST; 2162 default: 2163 return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST; 2164 } 2165 } 2166 2167 @Override 2168 public void setFirewallUidRules(int chain, int[] uids, int[] rules) { 2169 enforceSystemUid(); 2170 synchronized (mQuotaLock) { 2171 SparseIntArray uidFirewallRules = getUidFirewallRules(chain); 2172 SparseIntArray newRules = new SparseIntArray(); 2173 // apply new set of rules 2174 for (int index = uids.length - 1; index >= 0; --index) { 2175 int uid = uids[index]; 2176 int rule = rules[index]; 2177 setFirewallUidRule(chain, uid, rule); 2178 newRules.put(uid, rule); 2179 } 2180 // collect the rules to remove. 2181 SparseIntArray rulesToRemove = new SparseIntArray(); 2182 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) { 2183 int uid = uidFirewallRules.keyAt(index); 2184 if (newRules.indexOfKey(uid) < 0) { 2185 rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT); 2186 } 2187 } 2188 // remove dead rules 2189 for (int index = rulesToRemove.size() - 1; index >= 0; --index) { 2190 int uid = rulesToRemove.keyAt(index); 2191 setFirewallUidRuleInternal(chain, uid, FIREWALL_RULE_DEFAULT); 2192 } 2193 } 2194 } 2195 2196 @Override 2197 public void setFirewallUidRule(int chain, int uid, int rule) { 2198 enforceSystemUid(); 2199 setFirewallUidRuleInternal(chain, uid, rule); 2200 } 2201 2202 private void setFirewallUidRuleInternal(int chain, int uid, int rule) { 2203 synchronized (mQuotaLock) { 2204 SparseIntArray uidFirewallRules = getUidFirewallRules(chain); 2205 2206 final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT); 2207 if (DBG) { 2208 Slog.d(TAG, "oldRule = " + oldUidFirewallRule 2209 + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain); 2210 } 2211 if (oldUidFirewallRule == rule) { 2212 if (DBG) Slog.d(TAG, "!!!!! Skipping change"); 2213 // TODO: eventually consider throwing 2214 return; 2215 } 2216 2217 try { 2218 String ruleName = getFirewallRuleName(chain, rule); 2219 String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule); 2220 2221 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { 2222 uidFirewallRules.delete(uid); 2223 } else { 2224 uidFirewallRules.put(uid, rule); 2225 } 2226 2227 if (!ruleName.equals(oldRuleName)) { 2228 mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid, 2229 ruleName); 2230 } 2231 } catch (NativeDaemonConnectorException e) { 2232 throw e.rethrowAsParcelableException(); 2233 } 2234 } 2235 } 2236 2237 private @NonNull String getFirewallRuleName(int chain, int rule) { 2238 String ruleName; 2239 if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) { 2240 if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { 2241 ruleName = "allow"; 2242 } else { 2243 ruleName = "deny"; 2244 } 2245 } else { // Blacklist mode 2246 if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) { 2247 ruleName = "deny"; 2248 } else { 2249 ruleName = "allow"; 2250 } 2251 } 2252 return ruleName; 2253 } 2254 2255 private @NonNull SparseIntArray getUidFirewallRules(int chain) { 2256 switch (chain) { 2257 case FIREWALL_CHAIN_STANDBY: 2258 return mUidFirewallStandbyRules; 2259 case FIREWALL_CHAIN_DOZABLE: 2260 return mUidFirewallDozableRules; 2261 case FIREWALL_CHAIN_POWERSAVE: 2262 return mUidFirewallPowerSaveRules; 2263 case FIREWALL_CHAIN_NONE: 2264 return mUidFirewallRules; 2265 default: 2266 throw new IllegalArgumentException("Unknown chain:" + chain); 2267 } 2268 } 2269 2270 public @NonNull String getFirewallChainName(int chain) { 2271 switch (chain) { 2272 case FIREWALL_CHAIN_STANDBY: 2273 return FIREWALL_CHAIN_NAME_STANDBY; 2274 case FIREWALL_CHAIN_DOZABLE: 2275 return FIREWALL_CHAIN_NAME_DOZABLE; 2276 case FIREWALL_CHAIN_POWERSAVE: 2277 return FIREWALL_CHAIN_NAME_POWERSAVE; 2278 case FIREWALL_CHAIN_NONE: 2279 return FIREWALL_CHAIN_NAME_NONE; 2280 default: 2281 throw new IllegalArgumentException("Unknown chain:" + chain); 2282 } 2283 } 2284 2285 private static void enforceSystemUid() { 2286 final int uid = Binder.getCallingUid(); 2287 if (uid != Process.SYSTEM_UID) { 2288 throw new SecurityException("Only available to AID_SYSTEM"); 2289 } 2290 } 2291 2292 @Override 2293 public void startClatd(String interfaceName) throws IllegalStateException { 2294 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2295 2296 try { 2297 mConnector.execute("clatd", "start", interfaceName); 2298 } catch (NativeDaemonConnectorException e) { 2299 throw e.rethrowAsParcelableException(); 2300 } 2301 } 2302 2303 @Override 2304 public void stopClatd(String interfaceName) throws IllegalStateException { 2305 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2306 2307 try { 2308 mConnector.execute("clatd", "stop", interfaceName); 2309 } catch (NativeDaemonConnectorException e) { 2310 throw e.rethrowAsParcelableException(); 2311 } 2312 } 2313 2314 @Override 2315 public boolean isClatdStarted(String interfaceName) { 2316 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2317 2318 final NativeDaemonEvent event; 2319 try { 2320 event = mConnector.execute("clatd", "status", interfaceName); 2321 } catch (NativeDaemonConnectorException e) { 2322 throw e.rethrowAsParcelableException(); 2323 } 2324 2325 event.checkCode(ClatdStatusResult); 2326 return event.getMessage().endsWith("started"); 2327 } 2328 2329 @Override 2330 public void registerNetworkActivityListener(INetworkActivityListener listener) { 2331 mNetworkActivityListeners.register(listener); 2332 } 2333 2334 @Override 2335 public void unregisterNetworkActivityListener(INetworkActivityListener listener) { 2336 mNetworkActivityListeners.unregister(listener); 2337 } 2338 2339 @Override 2340 public boolean isNetworkActive() { 2341 synchronized (mNetworkActivityListeners) { 2342 return mNetworkActive || mActiveIdleTimers.isEmpty(); 2343 } 2344 } 2345 2346 private void reportNetworkActive() { 2347 final int length = mNetworkActivityListeners.beginBroadcast(); 2348 try { 2349 for (int i = 0; i < length; i++) { 2350 try { 2351 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); 2352 } catch (RemoteException | RuntimeException e) { 2353 } 2354 } 2355 } finally { 2356 mNetworkActivityListeners.finishBroadcast(); 2357 } 2358 } 2359 2360 /** {@inheritDoc} */ 2361 @Override 2362 public void monitor() { 2363 if (mConnector != null) { 2364 mConnector.monitor(); 2365 } 2366 } 2367 2368 @Override 2369 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2370 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 2371 2372 pw.println("NetworkManagementService NativeDaemonConnector Log:"); 2373 mConnector.dump(fd, pw, args); 2374 pw.println(); 2375 2376 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 2377 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio); 2378 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio); 2379 pw.print("mNetworkActive="); pw.println(mNetworkActive); 2380 2381 synchronized (mQuotaLock) { 2382 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 2383 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 2384 pw.print("Data saver mode: "); pw.println(mDataSaverMode); 2385 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered); 2386 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered); 2387 } 2388 2389 synchronized (mUidFirewallRules) { 2390 dumpUidFirewallRule(pw, "", mUidFirewallRules); 2391 } 2392 2393 pw.print("UID firewall standby chain enabled: "); pw.println( 2394 mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)); 2395 synchronized (mUidFirewallStandbyRules) { 2396 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules); 2397 } 2398 2399 pw.print("UID firewall dozable chain enabled: "); pw.println( 2400 mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)); 2401 synchronized (mUidFirewallDozableRules) { 2402 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules); 2403 } 2404 2405 pw.println("UID firewall powersave chain enabled: " + 2406 mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)); 2407 synchronized (mUidFirewallPowerSaveRules) { 2408 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules); 2409 } 2410 2411 synchronized (mIdleTimerLock) { 2412 pw.println("Idle timers:"); 2413 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { 2414 pw.print(" "); pw.print(ent.getKey()); pw.println(":"); 2415 IdleTimerParams params = ent.getValue(); 2416 pw.print(" timeout="); pw.print(params.timeout); 2417 pw.print(" type="); pw.print(params.type); 2418 pw.print(" networkCount="); pw.println(params.networkCount); 2419 } 2420 } 2421 2422 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 2423 pw.print("Netd service status: " ); 2424 if (mNetdService == null) { 2425 pw.println("disconnected"); 2426 } else { 2427 try { 2428 final boolean alive = mNetdService.isAlive(); 2429 pw.println(alive ? "alive": "dead"); 2430 } catch (RemoteException e) { 2431 pw.println("unreachable"); 2432 } 2433 } 2434 } 2435 2436 private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) { 2437 pw.print("UID bandwith control "); 2438 pw.print(name); 2439 pw.print(" rule: ["); 2440 final int size = list.size(); 2441 for (int i = 0; i < size; i++) { 2442 pw.print(list.keyAt(i)); 2443 if (i < size - 1) pw.print(","); 2444 } 2445 pw.println("]"); 2446 } 2447 2448 private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) { 2449 pw.print("UID firewall "); 2450 pw.print(name); 2451 pw.print(" rule: ["); 2452 final int size = rules.size(); 2453 for (int i = 0; i < size; i++) { 2454 pw.print(rules.keyAt(i)); 2455 pw.print(":"); 2456 pw.print(rules.valueAt(i)); 2457 if (i < size - 1) pw.print(","); 2458 } 2459 pw.println("]"); 2460 } 2461 2462 @Override 2463 public void createPhysicalNetwork(int netId, String permission) { 2464 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2465 2466 try { 2467 if (permission != null) { 2468 mConnector.execute("network", "create", netId, permission); 2469 } else { 2470 mConnector.execute("network", "create", netId); 2471 } 2472 } catch (NativeDaemonConnectorException e) { 2473 throw e.rethrowAsParcelableException(); 2474 } 2475 } 2476 2477 @Override 2478 public void createVirtualNetwork(int netId, boolean hasDNS, boolean secure) { 2479 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2480 2481 try { 2482 mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0", 2483 secure ? "1" : "0"); 2484 } catch (NativeDaemonConnectorException e) { 2485 throw e.rethrowAsParcelableException(); 2486 } 2487 } 2488 2489 @Override 2490 public void removeNetwork(int netId) { 2491 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2492 2493 try { 2494 mConnector.execute("network", "destroy", netId); 2495 } catch (NativeDaemonConnectorException e) { 2496 throw e.rethrowAsParcelableException(); 2497 } 2498 } 2499 2500 @Override 2501 public void addInterfaceToNetwork(String iface, int netId) { 2502 modifyInterfaceInNetwork("add", "" + netId, iface); 2503 } 2504 2505 @Override 2506 public void removeInterfaceFromNetwork(String iface, int netId) { 2507 modifyInterfaceInNetwork("remove", "" + netId, iface); 2508 } 2509 2510 private void modifyInterfaceInNetwork(String action, String netId, String iface) { 2511 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2512 try { 2513 mConnector.execute("network", "interface", action, netId, iface); 2514 } catch (NativeDaemonConnectorException e) { 2515 throw e.rethrowAsParcelableException(); 2516 } 2517 } 2518 2519 @Override 2520 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) { 2521 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2522 2523 final Command cmd = new Command("network", "route", "legacy", uid, "add", netId); 2524 2525 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr 2526 final LinkAddress la = routeInfo.getDestinationLinkAddress(); 2527 cmd.appendArg(routeInfo.getInterface()); 2528 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength()); 2529 if (routeInfo.hasGateway()) { 2530 cmd.appendArg(routeInfo.getGateway().getHostAddress()); 2531 } 2532 2533 try { 2534 mConnector.execute(cmd); 2535 } catch (NativeDaemonConnectorException e) { 2536 throw e.rethrowAsParcelableException(); 2537 } 2538 } 2539 2540 @Override 2541 public void setDefaultNetId(int netId) { 2542 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2543 2544 try { 2545 mConnector.execute("network", "default", "set", netId); 2546 } catch (NativeDaemonConnectorException e) { 2547 throw e.rethrowAsParcelableException(); 2548 } 2549 } 2550 2551 @Override 2552 public void clearDefaultNetId() { 2553 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2554 2555 try { 2556 mConnector.execute("network", "default", "clear"); 2557 } catch (NativeDaemonConnectorException e) { 2558 throw e.rethrowAsParcelableException(); 2559 } 2560 } 2561 2562 @Override 2563 public void setNetworkPermission(int netId, String permission) { 2564 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2565 2566 try { 2567 if (permission != null) { 2568 mConnector.execute("network", "permission", "network", "set", permission, netId); 2569 } else { 2570 mConnector.execute("network", "permission", "network", "clear", netId); 2571 } 2572 } catch (NativeDaemonConnectorException e) { 2573 throw e.rethrowAsParcelableException(); 2574 } 2575 } 2576 2577 2578 @Override 2579 public void setPermission(String permission, int[] uids) { 2580 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2581 2582 Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND]; 2583 argv[0] = "permission"; 2584 argv[1] = "user"; 2585 argv[2] = "set"; 2586 argv[3] = permission; 2587 int argc = 4; 2588 // Avoid overly long commands by limiting number of UIDs per command. 2589 for (int i = 0; i < uids.length; ++i) { 2590 argv[argc++] = uids[i]; 2591 if (i == uids.length - 1 || argc == argv.length) { 2592 try { 2593 mConnector.execute("network", Arrays.copyOf(argv, argc)); 2594 } catch (NativeDaemonConnectorException e) { 2595 throw e.rethrowAsParcelableException(); 2596 } 2597 argc = 4; 2598 } 2599 } 2600 } 2601 2602 @Override 2603 public void clearPermission(int[] uids) { 2604 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2605 2606 Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND]; 2607 argv[0] = "permission"; 2608 argv[1] = "user"; 2609 argv[2] = "clear"; 2610 int argc = 3; 2611 // Avoid overly long commands by limiting number of UIDs per command. 2612 for (int i = 0; i < uids.length; ++i) { 2613 argv[argc++] = uids[i]; 2614 if (i == uids.length - 1 || argc == argv.length) { 2615 try { 2616 mConnector.execute("network", Arrays.copyOf(argv, argc)); 2617 } catch (NativeDaemonConnectorException e) { 2618 throw e.rethrowAsParcelableException(); 2619 } 2620 argc = 3; 2621 } 2622 } 2623 } 2624 2625 @Override 2626 public void allowProtect(int uid) { 2627 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2628 2629 try { 2630 mConnector.execute("network", "protect", "allow", uid); 2631 } catch (NativeDaemonConnectorException e) { 2632 throw e.rethrowAsParcelableException(); 2633 } 2634 } 2635 2636 @Override 2637 public void denyProtect(int uid) { 2638 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2639 2640 try { 2641 mConnector.execute("network", "protect", "deny", uid); 2642 } catch (NativeDaemonConnectorException e) { 2643 throw e.rethrowAsParcelableException(); 2644 } 2645 } 2646 2647 @Override 2648 public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) { 2649 modifyInterfaceInNetwork("add", "local", iface); 2650 2651 for (RouteInfo route : routes) { 2652 if (!route.isDefaultRoute()) { 2653 modifyRoute("add", "local", route); 2654 } 2655 } 2656 } 2657 2658 @Override 2659 public void removeInterfaceFromLocalNetwork(String iface) { 2660 modifyInterfaceInNetwork("remove", "local", iface); 2661 } 2662} 2663