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