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.net; 18 19 import static android.Manifest.permission.CONNECTIVITY_INTERNAL; 20 import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE; 21 import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY; 22 import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE; 23 import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED; 24 import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY; 25 import static android.net.INetd.FIREWALL_ALLOWLIST; 26 import static android.net.INetd.FIREWALL_CHAIN_NONE; 27 import static android.net.INetd.FIREWALL_DENYLIST; 28 import static android.net.INetd.FIREWALL_RULE_ALLOW; 29 import static android.net.INetd.FIREWALL_RULE_DENY; 30 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE; 31 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY; 32 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE; 33 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED; 34 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY; 35 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; 36 37 import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT; 38 39 import android.annotation.NonNull; 40 import android.app.ActivityManager; 41 import android.content.Context; 42 import android.net.ConnectivityManager; 43 import android.net.INetd; 44 import android.net.INetdUnsolicitedEventListener; 45 import android.net.INetworkManagementEventObserver; 46 import android.net.ITetheringStatsProvider; 47 import android.net.InetAddresses; 48 import android.net.InterfaceConfiguration; 49 import android.net.InterfaceConfigurationParcel; 50 import android.net.IpPrefix; 51 import android.net.LinkAddress; 52 import android.net.NetworkPolicyManager; 53 import android.net.NetworkStack; 54 import android.net.NetworkStats; 55 import android.net.RouteInfo; 56 import android.net.util.NetdService; 57 import android.os.BatteryStats; 58 import android.os.Binder; 59 import android.os.Handler; 60 import android.os.IBinder; 61 import android.os.INetworkManagementService; 62 import android.os.PermissionEnforcer; 63 import android.os.Process; 64 import android.os.RemoteCallbackList; 65 import android.os.RemoteException; 66 import android.os.ServiceManager; 67 import android.os.ServiceSpecificException; 68 import android.os.StrictMode; 69 import android.os.SystemClock; 70 import android.os.Trace; 71 import android.text.TextUtils; 72 import android.util.Log; 73 import android.util.Slog; 74 import android.util.SparseBooleanArray; 75 import android.util.SparseIntArray; 76 77 import com.android.internal.annotations.GuardedBy; 78 import com.android.internal.app.IBatteryStats; 79 import com.android.internal.util.DumpUtils; 80 import com.android.internal.util.HexDump; 81 import com.android.internal.util.Preconditions; 82 import com.android.net.module.util.NetdUtils; 83 import com.android.net.module.util.NetdUtils.ModifyOperation; 84 import com.android.server.FgThread; 85 import com.android.server.LocalServices; 86 87 import com.google.android.collect.Maps; 88 89 import java.io.BufferedReader; 90 import java.io.DataInputStream; 91 import java.io.FileDescriptor; 92 import java.io.FileInputStream; 93 import java.io.IOException; 94 import java.io.InputStreamReader; 95 import java.io.PrintWriter; 96 import java.net.InetAddress; 97 import java.net.InterfaceAddress; 98 import java.util.ArrayList; 99 import java.util.HashMap; 100 import java.util.List; 101 import java.util.Map; 102 import java.util.Objects; 103 104 /** 105 * @hide 106 */ 107 public class NetworkManagementService extends INetworkManagementService.Stub { 108 109 /** 110 * Helper class that encapsulates NetworkManagementService dependencies and makes them 111 * easier to mock in unit tests. 112 */ 113 static class Dependencies { getService(String name)114 public IBinder getService(String name) { 115 return ServiceManager.getService(name); 116 } registerLocalService(NetworkManagementInternal nmi)117 public void registerLocalService(NetworkManagementInternal nmi) { 118 LocalServices.addService(NetworkManagementInternal.class, nmi); 119 } getNetd()120 public INetd getNetd() { 121 return NetdService.get(); 122 } 123 getCallingUid()124 public int getCallingUid() { 125 return Binder.getCallingUid(); 126 } 127 } 128 129 private static final String TAG = "NetworkManagement"; 130 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); 131 132 private static final int MAX_UID_RANGES_PER_COMMAND = 10; 133 134 static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1; 135 136 static final boolean MODIFY_OPERATION_ADD = true; 137 static final boolean MODIFY_OPERATION_REMOVE = false; 138 139 /** 140 * Binder context for this service 141 */ 142 private final Context mContext; 143 144 private final Handler mDaemonHandler; 145 146 private final Dependencies mDeps; 147 148 private INetd mNetdService; 149 150 private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener; 151 152 private IBatteryStats mBatteryStats; 153 154 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers = 155 new RemoteCallbackList<>(); 156 157 @GuardedBy("mTetheringStatsProviders") 158 private final HashMap<ITetheringStatsProvider, String> 159 mTetheringStatsProviders = Maps.newHashMap(); 160 161 /** 162 * If both locks need to be held, then they should be obtained in the order: 163 * first {@link #mQuotaLock} and then {@link #mRulesLock}. 164 */ 165 private final Object mQuotaLock = new Object(); 166 private final Object mRulesLock = new Object(); 167 168 /** Set of interfaces with active quotas. */ 169 @GuardedBy("mQuotaLock") 170 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap(); 171 /** Set of interfaces with active alerts. */ 172 @GuardedBy("mQuotaLock") 173 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap(); 174 /** Set of UIDs denied on metered networks. */ 175 @GuardedBy("mRulesLock") 176 private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray(); 177 /** Set of UIDs allowed on metered networks. */ 178 @GuardedBy("mRulesLock") 179 private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray(); 180 /** Set of UIDs with cleartext penalties. */ 181 @GuardedBy("mQuotaLock") 182 private SparseIntArray mUidCleartextPolicy = new SparseIntArray(); 183 /** Set of UIDs that are to be blocked/allowed by firewall controller. */ 184 @GuardedBy("mRulesLock") 185 private SparseIntArray mUidFirewallRules = new SparseIntArray(); 186 /** 187 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches 188 * to application idles. 189 */ 190 @GuardedBy("mRulesLock") 191 private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray(); 192 /** 193 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches 194 * to device idles. 195 */ 196 @GuardedBy("mRulesLock") 197 private SparseIntArray mUidFirewallDozableRules = new SparseIntArray(); 198 /** 199 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches 200 * to device on power-save mode. 201 */ 202 @GuardedBy("mRulesLock") 203 private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray(); 204 /** 205 * Contains the per-UID firewall rules that are used when Restricted Networking Mode is enabled. 206 */ 207 @GuardedBy("mRulesLock") 208 private SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray(); 209 /** 210 * Contains the per-UID firewall rules that are used when Low Power Standby is enabled. 211 */ 212 @GuardedBy("mRulesLock") 213 private SparseIntArray mUidFirewallLowPowerStandbyRules = new SparseIntArray(); 214 /** Set of states for the child firewall chains. True if the chain is active. */ 215 @GuardedBy("mRulesLock") 216 final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray(); 217 218 @GuardedBy("mQuotaLock") 219 private volatile boolean mDataSaverMode; 220 221 private volatile boolean mFirewallEnabled; 222 private volatile boolean mStrictEnabled; 223 224 /** 225 * Constructs a new NetworkManagementService instance 226 * 227 * @param context Binder context for this service 228 */ NetworkManagementService( Context context, Dependencies deps)229 private NetworkManagementService( 230 Context context, Dependencies deps) { 231 super(PermissionEnforcer.fromContext(context)); 232 mContext = context; 233 mDeps = deps; 234 235 mDaemonHandler = new Handler(FgThread.get().getLooper()); 236 237 mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener(); 238 239 mDeps.registerLocalService(new LocalService()); 240 241 synchronized (mTetheringStatsProviders) { 242 mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd"); 243 } 244 } 245 NetworkManagementService()246 private NetworkManagementService() { 247 mContext = null; 248 mDaemonHandler = null; 249 mDeps = null; 250 mNetdUnsolicitedEventListener = null; 251 } 252 create(Context context, Dependencies deps)253 static NetworkManagementService create(Context context, Dependencies deps) 254 throws InterruptedException { 255 final NetworkManagementService service = 256 new NetworkManagementService(context, deps); 257 if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); 258 if (DBG) Slog.d(TAG, "Connecting native netd service"); 259 service.connectNativeNetdService(); 260 if (DBG) Slog.d(TAG, "Connected"); 261 return service; 262 } 263 create(Context context)264 public static NetworkManagementService create(Context context) throws InterruptedException { 265 return create(context, new Dependencies()); 266 } 267 systemReady()268 public void systemReady() { 269 if (DBG) { 270 final long start = System.currentTimeMillis(); 271 prepareNativeDaemon(); 272 final long delta = System.currentTimeMillis() - start; 273 Slog.d(TAG, "Prepared in " + delta + "ms"); 274 return; 275 } else { 276 prepareNativeDaemon(); 277 } 278 } 279 getBatteryStats()280 private IBatteryStats getBatteryStats() { 281 synchronized (this) { 282 if (mBatteryStats != null) { 283 return mBatteryStats; 284 } 285 mBatteryStats = 286 IBatteryStats.Stub.asInterface(mDeps.getService(BatteryStats.SERVICE_NAME)); 287 return mBatteryStats; 288 } 289 } 290 291 @Override registerObserver(INetworkManagementEventObserver observer)292 public void registerObserver(INetworkManagementEventObserver observer) { 293 NetworkStack.checkNetworkStackPermission(mContext); 294 mObservers.register(observer); 295 } 296 297 @Override unregisterObserver(INetworkManagementEventObserver observer)298 public void unregisterObserver(INetworkManagementEventObserver observer) { 299 NetworkStack.checkNetworkStackPermission(mContext); 300 mObservers.unregister(observer); 301 } 302 303 @FunctionalInterface 304 private interface NetworkManagementEventCallback { sendCallback(INetworkManagementEventObserver o)305 public void sendCallback(INetworkManagementEventObserver o) throws RemoteException; 306 } 307 invokeForAllObservers(NetworkManagementEventCallback eventCallback)308 private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) { 309 final int length = mObservers.beginBroadcast(); 310 try { 311 for (int i = 0; i < length; i++) { 312 try { 313 eventCallback.sendCallback(mObservers.getBroadcastItem(i)); 314 } catch (RemoteException | RuntimeException e) { 315 } 316 } 317 } finally { 318 mObservers.finishBroadcast(); 319 } 320 } 321 322 /** 323 * Notify our observers of an interface status change 324 */ notifyInterfaceStatusChanged(String iface, boolean up)325 private void notifyInterfaceStatusChanged(String iface, boolean up) { 326 invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up)); 327 } 328 329 /** 330 * Notify our observers of an interface link state change 331 * (typically, an Ethernet cable has been plugged-in or unplugged). 332 */ notifyInterfaceLinkStateChanged(String iface, boolean up)333 private void notifyInterfaceLinkStateChanged(String iface, boolean up) { 334 invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up)); 335 } 336 337 /** 338 * Notify our observers of an interface addition. 339 */ notifyInterfaceAdded(String iface)340 private void notifyInterfaceAdded(String iface) { 341 invokeForAllObservers(o -> o.interfaceAdded(iface)); 342 } 343 344 /** 345 * Notify our observers of an interface removal. 346 */ notifyInterfaceRemoved(String iface)347 private void notifyInterfaceRemoved(String iface) { 348 // netd already clears out quota and alerts for removed ifaces; update 349 // our validity-checking state. 350 mActiveAlerts.remove(iface); 351 mActiveQuotas.remove(iface); 352 invokeForAllObservers(o -> o.interfaceRemoved(iface)); 353 } 354 355 /** 356 * Notify our observers of a limit reached. 357 */ notifyLimitReached(String limitName, String iface)358 private void notifyLimitReached(String limitName, String iface) { 359 invokeForAllObservers(o -> o.limitReached(limitName, iface)); 360 } 361 362 /** 363 * Notify our observers of a change in the data activity state of the interface 364 */ notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos, int uid)365 private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos, 366 int uid) { 367 invokeForAllObservers(o -> o.interfaceClassDataActivityChanged( 368 type, isActive, tsNanos, uid)); 369 } 370 371 @Override registerTetheringStatsProvider(ITetheringStatsProvider provider, String name)372 public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) { 373 NetworkStack.checkNetworkStackPermission(mContext); 374 Objects.requireNonNull(provider); 375 synchronized(mTetheringStatsProviders) { 376 mTetheringStatsProviders.put(provider, name); 377 } 378 } 379 380 @Override unregisterTetheringStatsProvider(ITetheringStatsProvider provider)381 public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) { 382 NetworkStack.checkNetworkStackPermission(mContext); 383 synchronized(mTetheringStatsProviders) { 384 mTetheringStatsProviders.remove(provider); 385 } 386 } 387 388 @Override tetherLimitReached(ITetheringStatsProvider provider)389 public void tetherLimitReached(ITetheringStatsProvider provider) { 390 NetworkStack.checkNetworkStackPermission(mContext); 391 synchronized(mTetheringStatsProviders) { 392 if (!mTetheringStatsProviders.containsKey(provider)) { 393 return; 394 } 395 // No current code examines the interface parameter in a global alert. Just pass null. 396 mDaemonHandler.post(() -> notifyLimitReached(LIMIT_GLOBAL_ALERT, null)); 397 } 398 } 399 400 // Sync the state of the given chain with the native daemon. syncFirewallChainLocked(int chain, String name)401 private void syncFirewallChainLocked(int chain, String name) { 402 SparseIntArray rules; 403 synchronized (mRulesLock) { 404 final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain); 405 // Make a copy of the current rules, and then clear them. This is because 406 // setFirewallUidRuleInternal only pushes down rules to the native daemon if they 407 // are different from the current rules stored in the mUidFirewall*Rules array for 408 // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal 409 // will do nothing. 410 rules = uidFirewallRules.clone(); 411 uidFirewallRules.clear(); 412 } 413 if (rules.size() > 0) { 414 // Now push the rules. setFirewallUidRuleInternal will push each of these down to the 415 // native daemon, and also add them to the mUidFirewall*Rules array for the specified 416 // chain. 417 if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall " 418 + name + "UID rules"); 419 for (int i = 0; i < rules.size(); i++) { 420 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i)); 421 } 422 } 423 } 424 connectNativeNetdService()425 private void connectNativeNetdService() { 426 mNetdService = mDeps.getNetd(); 427 try { 428 mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener); 429 if (DBG) Slog.d(TAG, "Register unsolicited event listener"); 430 } catch (RemoteException | ServiceSpecificException e) { 431 Slog.e(TAG, "Failed to set Netd unsolicited event listener " + e); 432 } 433 } 434 435 /** 436 * Prepare native daemon once connected, enabling modules and pushing any 437 * existing in-memory rules. 438 */ prepareNativeDaemon()439 private void prepareNativeDaemon() { 440 441 // push any existing quota or UID rules 442 synchronized (mQuotaLock) { 443 444 mStrictEnabled = true; 445 446 setDataSaverModeEnabled(mDataSaverMode); 447 448 int size = mActiveQuotas.size(); 449 if (size > 0) { 450 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules"); 451 final HashMap<String, Long> activeQuotas = mActiveQuotas; 452 mActiveQuotas = Maps.newHashMap(); 453 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) { 454 setInterfaceQuota(entry.getKey(), entry.getValue()); 455 } 456 } 457 458 size = mActiveAlerts.size(); 459 if (size > 0) { 460 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules"); 461 final HashMap<String, Long> activeAlerts = mActiveAlerts; 462 mActiveAlerts = Maps.newHashMap(); 463 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) { 464 setInterfaceAlert(entry.getKey(), entry.getValue()); 465 } 466 } 467 468 SparseBooleanArray uidRejectOnQuota = null; 469 SparseBooleanArray uidAcceptOnQuota = null; 470 synchronized (mRulesLock) { 471 size = mUidRejectOnMetered.size(); 472 if (size > 0) { 473 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered denylist rules"); 474 uidRejectOnQuota = mUidRejectOnMetered; 475 mUidRejectOnMetered = new SparseBooleanArray(); 476 } 477 478 size = mUidAllowOnMetered.size(); 479 if (size > 0) { 480 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered allowlist rules"); 481 uidAcceptOnQuota = mUidAllowOnMetered; 482 mUidAllowOnMetered = new SparseBooleanArray(); 483 } 484 } 485 if (uidRejectOnQuota != null) { 486 for (int i = 0; i < uidRejectOnQuota.size(); i++) { 487 setUidOnMeteredNetworkDenylist(uidRejectOnQuota.keyAt(i), 488 uidRejectOnQuota.valueAt(i)); 489 } 490 } 491 if (uidAcceptOnQuota != null) { 492 for (int i = 0; i < uidAcceptOnQuota.size(); i++) { 493 setUidOnMeteredNetworkAllowlist(uidAcceptOnQuota.keyAt(i), 494 uidAcceptOnQuota.valueAt(i)); 495 } 496 } 497 498 size = mUidCleartextPolicy.size(); 499 if (size > 0) { 500 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies"); 501 final SparseIntArray local = mUidCleartextPolicy; 502 mUidCleartextPolicy = new SparseIntArray(); 503 for (int i = 0; i < local.size(); i++) { 504 setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i)); 505 } 506 } 507 508 setFirewallEnabled(mFirewallEnabled); 509 510 syncFirewallChainLocked(FIREWALL_CHAIN_NONE, ""); 511 syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby "); 512 syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable "); 513 syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave "); 514 syncFirewallChainLocked(FIREWALL_CHAIN_RESTRICTED, "restricted "); 515 syncFirewallChainLocked(FIREWALL_CHAIN_LOW_POWER_STANDBY, "low power standby "); 516 517 final int[] chains = { 518 FIREWALL_CHAIN_STANDBY, 519 FIREWALL_CHAIN_DOZABLE, 520 FIREWALL_CHAIN_POWERSAVE, 521 FIREWALL_CHAIN_RESTRICTED, 522 FIREWALL_CHAIN_LOW_POWER_STANDBY 523 }; 524 525 for (int chain : chains) { 526 if (getFirewallChainState(chain)) { 527 setFirewallChainEnabled(chain, true); 528 } 529 } 530 } 531 532 533 try { 534 getBatteryStats().noteNetworkStatsEnabled(); 535 } catch (RemoteException e) { 536 } 537 538 } 539 540 /** 541 * Notify our observers of a new or updated interface address. 542 */ notifyAddressUpdated(String iface, LinkAddress address)543 private void notifyAddressUpdated(String iface, LinkAddress address) { 544 invokeForAllObservers(o -> o.addressUpdated(iface, address)); 545 } 546 547 /** 548 * Notify our observers of a deleted interface address. 549 */ notifyAddressRemoved(String iface, LinkAddress address)550 private void notifyAddressRemoved(String iface, LinkAddress address) { 551 invokeForAllObservers(o -> o.addressRemoved(iface, address)); 552 } 553 554 /** 555 * Notify our observers of DNS server information received. 556 */ notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses)557 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) { 558 invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses)); 559 } 560 561 /** 562 * Notify our observers of a route change. 563 */ notifyRouteChange(boolean updated, RouteInfo route)564 private void notifyRouteChange(boolean updated, RouteInfo route) { 565 if (updated) { 566 invokeForAllObservers(o -> o.routeUpdated(route)); 567 } else { 568 invokeForAllObservers(o -> o.routeRemoved(route)); 569 } 570 } 571 572 private class NetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub { 573 @Override onInterfaceClassActivityChanged(boolean isActive, int label, long timestamp, int uid)574 public void onInterfaceClassActivityChanged(boolean isActive, 575 int label, long timestamp, int uid) throws RemoteException { 576 final long timestampNanos; 577 if (timestamp <= 0) { 578 timestampNanos = SystemClock.elapsedRealtimeNanos(); 579 } else { 580 timestampNanos = timestamp; 581 } 582 mDaemonHandler.post(() -> 583 notifyInterfaceClassActivity(label, isActive, timestampNanos, uid)); 584 } 585 586 @Override onQuotaLimitReached(String alertName, String ifName)587 public void onQuotaLimitReached(String alertName, String ifName) 588 throws RemoteException { 589 mDaemonHandler.post(() -> notifyLimitReached(alertName, ifName)); 590 } 591 592 @Override onInterfaceDnsServerInfo(String ifName, long lifetime, String[] servers)593 public void onInterfaceDnsServerInfo(String ifName, 594 long lifetime, String[] servers) throws RemoteException { 595 mDaemonHandler.post(() -> notifyInterfaceDnsServerInfo(ifName, lifetime, servers)); 596 } 597 598 @Override onInterfaceAddressUpdated(String addr, String ifName, int flags, int scope)599 public void onInterfaceAddressUpdated(String addr, 600 String ifName, int flags, int scope) throws RemoteException { 601 final LinkAddress address = new LinkAddress(addr, flags, scope); 602 mDaemonHandler.post(() -> notifyAddressUpdated(ifName, address)); 603 } 604 605 @Override onInterfaceAddressRemoved(String addr, String ifName, int flags, int scope)606 public void onInterfaceAddressRemoved(String addr, 607 String ifName, int flags, int scope) throws RemoteException { 608 final LinkAddress address = new LinkAddress(addr, flags, scope); 609 mDaemonHandler.post(() -> notifyAddressRemoved(ifName, address)); 610 } 611 612 @Override onInterfaceAdded(String ifName)613 public void onInterfaceAdded(String ifName) throws RemoteException { 614 mDaemonHandler.post(() -> notifyInterfaceAdded(ifName)); 615 } 616 617 @Override onInterfaceRemoved(String ifName)618 public void onInterfaceRemoved(String ifName) throws RemoteException { 619 mDaemonHandler.post(() -> notifyInterfaceRemoved(ifName)); 620 } 621 622 @Override onInterfaceChanged(String ifName, boolean up)623 public void onInterfaceChanged(String ifName, boolean up) 624 throws RemoteException { 625 mDaemonHandler.post(() -> notifyInterfaceStatusChanged(ifName, up)); 626 } 627 628 @Override onInterfaceLinkStateChanged(String ifName, boolean up)629 public void onInterfaceLinkStateChanged(String ifName, boolean up) 630 throws RemoteException { 631 mDaemonHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up)); 632 } 633 634 @Override onRouteChanged(boolean updated, String route, String gateway, String ifName)635 public void onRouteChanged(boolean updated, 636 String route, String gateway, String ifName) throws RemoteException { 637 final RouteInfo processRoute = new RouteInfo(new IpPrefix(route), 638 ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway), 639 ifName, RouteInfo.RTN_UNICAST); 640 mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute)); 641 } 642 643 @Override onStrictCleartextDetected(int uid, String hex)644 public void onStrictCleartextDetected(int uid, String hex) throws RemoteException { 645 // Don't need to post to mDaemonHandler because the only thing 646 // that notifyCleartextNetwork does is post to a handler 647 ActivityManager.getService().notifyCleartextNetwork(uid, 648 HexDump.hexStringToByteArray(hex)); 649 } 650 651 @Override getInterfaceVersion()652 public int getInterfaceVersion() { 653 return INetdUnsolicitedEventListener.VERSION; 654 } 655 656 @Override getInterfaceHash()657 public String getInterfaceHash() { 658 return INetdUnsolicitedEventListener.HASH; 659 } 660 } 661 662 // 663 // INetworkManagementService members 664 // 665 @Override listInterfaces()666 public String[] listInterfaces() { 667 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these 668 // APIs. 669 NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL); 670 try { 671 return mNetdService.interfaceGetList(); 672 } catch (RemoteException | ServiceSpecificException e) { 673 throw new IllegalStateException(e); 674 } 675 } 676 677 /** 678 * Convert InterfaceConfiguration to InterfaceConfigurationParcel with given ifname. 679 */ toStableParcel(InterfaceConfiguration cfg, String iface)680 private static InterfaceConfigurationParcel toStableParcel(InterfaceConfiguration cfg, 681 String iface) { 682 InterfaceConfigurationParcel cfgParcel = new InterfaceConfigurationParcel(); 683 cfgParcel.ifName = iface; 684 String hwAddr = cfg.getHardwareAddress(); 685 if (!TextUtils.isEmpty(hwAddr)) { 686 cfgParcel.hwAddr = hwAddr; 687 } else { 688 cfgParcel.hwAddr = ""; 689 } 690 cfgParcel.ipv4Addr = cfg.getLinkAddress().getAddress().getHostAddress(); 691 cfgParcel.prefixLength = cfg.getLinkAddress().getPrefixLength(); 692 ArrayList<String> flags = new ArrayList<>(); 693 for (String flag : cfg.getFlags()) { 694 flags.add(flag); 695 } 696 cfgParcel.flags = flags.toArray(new String[0]); 697 698 return cfgParcel; 699 } 700 701 /** 702 * Construct InterfaceConfiguration from InterfaceConfigurationParcel. 703 */ fromStableParcel(InterfaceConfigurationParcel p)704 public static InterfaceConfiguration fromStableParcel(InterfaceConfigurationParcel p) { 705 InterfaceConfiguration cfg = new InterfaceConfiguration(); 706 cfg.setHardwareAddress(p.hwAddr); 707 708 final InetAddress addr = InetAddresses.parseNumericAddress(p.ipv4Addr); 709 cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength)); 710 for (String flag : p.flags) { 711 cfg.setFlag(flag); 712 } 713 714 return cfg; 715 } 716 717 @Override getInterfaceConfig(String iface)718 public InterfaceConfiguration getInterfaceConfig(String iface) { 719 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these 720 // APIs. 721 NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL); 722 final InterfaceConfigurationParcel result; 723 try { 724 result = mNetdService.interfaceGetCfg(iface); 725 } catch (RemoteException | ServiceSpecificException e) { 726 throw new IllegalStateException(e); 727 } 728 729 try { 730 final InterfaceConfiguration cfg = fromStableParcel(result); 731 return cfg; 732 } catch (IllegalArgumentException iae) { 733 throw new IllegalStateException("Invalid InterfaceConfigurationParcel", iae); 734 } 735 } 736 737 @Override setInterfaceConfig(String iface, InterfaceConfiguration cfg)738 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { 739 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these 740 // APIs. 741 NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL); 742 LinkAddress linkAddr = cfg.getLinkAddress(); 743 if (linkAddr == null || linkAddr.getAddress() == null) { 744 throw new IllegalStateException("Null LinkAddress given"); 745 } 746 747 final InterfaceConfigurationParcel cfgParcel = toStableParcel(cfg, iface); 748 749 try { 750 mNetdService.interfaceSetCfg(cfgParcel); 751 } catch (RemoteException | ServiceSpecificException e) { 752 throw new IllegalStateException(e); 753 } 754 } 755 756 @Override setInterfaceDown(String iface)757 public void setInterfaceDown(String iface) { 758 NetworkStack.checkNetworkStackPermission(mContext); 759 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 760 ifcg.setInterfaceDown(); 761 setInterfaceConfig(iface, ifcg); 762 } 763 764 @Override setInterfaceUp(String iface)765 public void setInterfaceUp(String iface) { 766 NetworkStack.checkNetworkStackPermission(mContext); 767 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 768 ifcg.setInterfaceUp(); 769 setInterfaceConfig(iface, ifcg); 770 } 771 772 @Override setInterfaceIpv6PrivacyExtensions(String iface, boolean enable)773 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { 774 NetworkStack.checkNetworkStackPermission(mContext); 775 try { 776 mNetdService.interfaceSetIPv6PrivacyExtensions(iface, enable); 777 } catch (RemoteException | ServiceSpecificException e) { 778 throw new IllegalStateException(e); 779 } 780 } 781 782 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 783 IPv6 addresses on interface down, but we need to do full clean up here */ 784 @Override clearInterfaceAddresses(String iface)785 public void clearInterfaceAddresses(String iface) { 786 NetworkStack.checkNetworkStackPermission(mContext); 787 try { 788 mNetdService.interfaceClearAddrs(iface); 789 } catch (RemoteException | ServiceSpecificException e) { 790 throw new IllegalStateException(e); 791 } 792 } 793 794 @Override enableIpv6(String iface)795 public void enableIpv6(String iface) { 796 NetworkStack.checkNetworkStackPermission(mContext); 797 try { 798 mNetdService.interfaceSetEnableIPv6(iface, true); 799 } catch (RemoteException | ServiceSpecificException e) { 800 throw new IllegalStateException(e); 801 } 802 } 803 804 @Override setIPv6AddrGenMode(String iface, int mode)805 public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException { 806 NetworkStack.checkNetworkStackPermission(mContext); 807 try { 808 mNetdService.setIPv6AddrGenMode(iface, mode); 809 } catch (RemoteException e) { 810 throw e.rethrowAsRuntimeException(); 811 } 812 } 813 814 @Override disableIpv6(String iface)815 public void disableIpv6(String iface) { 816 NetworkStack.checkNetworkStackPermission(mContext); 817 try { 818 mNetdService.interfaceSetEnableIPv6(iface, false); 819 } catch (RemoteException | ServiceSpecificException e) { 820 throw new IllegalStateException(e); 821 } 822 } 823 824 @Override addRoute(int netId, RouteInfo route)825 public void addRoute(int netId, RouteInfo route) { 826 NetworkStack.checkNetworkStackPermission(mContext); 827 NetdUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route); 828 } 829 830 @Override removeRoute(int netId, RouteInfo route)831 public void removeRoute(int netId, RouteInfo route) { 832 NetworkStack.checkNetworkStackPermission(mContext); 833 NetdUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route); 834 } 835 readRouteList(String filename)836 private ArrayList<String> readRouteList(String filename) { 837 FileInputStream fstream = null; 838 ArrayList<String> list = new ArrayList<>(); 839 840 try { 841 fstream = new FileInputStream(filename); 842 DataInputStream in = new DataInputStream(fstream); 843 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 844 String s; 845 846 // throw away the title line 847 848 while (((s = br.readLine()) != null) && (s.length() != 0)) { 849 list.add(s); 850 } 851 } catch (IOException ex) { 852 // return current list, possibly empty 853 } finally { 854 if (fstream != null) { 855 try { 856 fstream.close(); 857 } catch (IOException ex) {} 858 } 859 } 860 861 return list; 862 } 863 864 @android.annotation.EnforcePermission(android.Manifest.permission.SHUTDOWN) 865 @Override shutdown()866 public void shutdown() { 867 // TODO: remove from aidl if nobody calls externally 868 869 super.shutdown_enforcePermission(); 870 871 Slog.i(TAG, "Shutting down"); 872 } 873 874 @Override getIpForwardingEnabled()875 public boolean getIpForwardingEnabled() throws IllegalStateException{ 876 NetworkStack.checkNetworkStackPermission(mContext); 877 878 try { 879 final boolean isEnabled = mNetdService.ipfwdEnabled(); 880 return isEnabled; 881 } catch (RemoteException | ServiceSpecificException e) { 882 throw new IllegalStateException(e); 883 } 884 } 885 886 @Override setIpForwardingEnabled(boolean enable)887 public void setIpForwardingEnabled(boolean enable) { 888 NetworkStack.checkNetworkStackPermission(mContext); 889 try { 890 if (enable) { 891 mNetdService.ipfwdEnableForwarding("tethering"); 892 } else { 893 mNetdService.ipfwdDisableForwarding("tethering"); 894 } 895 } catch (RemoteException | ServiceSpecificException e) { 896 throw new IllegalStateException(e); 897 } 898 } 899 900 @Override startTethering(String[] dhcpRange)901 public void startTethering(String[] dhcpRange) { 902 startTetheringWithConfiguration(true, dhcpRange); 903 } 904 905 @Override startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange)906 public void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange) { 907 NetworkStack.checkNetworkStackPermission(mContext); 908 try { 909 NetdUtils.tetherStart(mNetdService, usingLegacyDnsProxy, dhcpRange); 910 } catch (RemoteException | ServiceSpecificException e) { 911 throw new IllegalStateException(e); 912 } 913 } 914 915 @Override stopTethering()916 public void stopTethering() { 917 NetworkStack.checkNetworkStackPermission(mContext); 918 try { 919 mNetdService.tetherStop(); 920 } catch (RemoteException | ServiceSpecificException e) { 921 throw new IllegalStateException(e); 922 } 923 } 924 925 @Override isTetheringStarted()926 public boolean isTetheringStarted() { 927 NetworkStack.checkNetworkStackPermission(mContext); 928 929 try { 930 final boolean isEnabled = mNetdService.tetherIsEnabled(); 931 return isEnabled; 932 } catch (RemoteException | ServiceSpecificException e) { 933 throw new IllegalStateException(e); 934 } 935 } 936 937 @Override tetherInterface(String iface)938 public void tetherInterface(String iface) { 939 NetworkStack.checkNetworkStackPermission(mContext); 940 try { 941 final LinkAddress addr = getInterfaceConfig(iface).getLinkAddress(); 942 final IpPrefix dest = new IpPrefix(addr.getAddress(), addr.getPrefixLength()); 943 NetdUtils.tetherInterface(mNetdService, iface, dest); 944 } catch (RemoteException | ServiceSpecificException e) { 945 throw new IllegalStateException(e); 946 } 947 } 948 949 @Override untetherInterface(String iface)950 public void untetherInterface(String iface) { 951 NetworkStack.checkNetworkStackPermission(mContext); 952 try { 953 NetdUtils.untetherInterface(mNetdService, iface); 954 } catch (RemoteException | ServiceSpecificException e) { 955 throw new IllegalStateException(e); 956 } 957 } 958 959 @Override listTetheredInterfaces()960 public String[] listTetheredInterfaces() { 961 NetworkStack.checkNetworkStackPermission(mContext); 962 try { 963 return mNetdService.tetherInterfaceList(); 964 } catch (RemoteException | ServiceSpecificException e) { 965 throw new IllegalStateException(e); 966 } 967 } 968 969 @Override getDnsForwarders()970 public String[] getDnsForwarders() { 971 NetworkStack.checkNetworkStackPermission(mContext); 972 try { 973 return mNetdService.tetherDnsList(); 974 } catch (RemoteException | ServiceSpecificException e) { 975 throw new IllegalStateException(e); 976 } 977 } 978 excludeLinkLocal(List<InterfaceAddress> addresses)979 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) { 980 ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size()); 981 for (InterfaceAddress ia : addresses) { 982 if (!ia.getAddress().isLinkLocalAddress()) 983 filtered.add(ia); 984 } 985 return filtered; 986 } 987 modifyInterfaceForward(boolean add, String fromIface, String toIface)988 private void modifyInterfaceForward(boolean add, String fromIface, String toIface) { 989 try { 990 if (add) { 991 mNetdService.ipfwdAddInterfaceForward(fromIface, toIface); 992 } else { 993 mNetdService.ipfwdRemoveInterfaceForward(fromIface, toIface); 994 } 995 } catch (RemoteException | ServiceSpecificException e) { 996 throw new IllegalStateException(e); 997 } 998 } 999 1000 @Override startInterfaceForwarding(String fromIface, String toIface)1001 public void startInterfaceForwarding(String fromIface, String toIface) { 1002 NetworkStack.checkNetworkStackPermission(mContext); 1003 modifyInterfaceForward(true, fromIface, toIface); 1004 } 1005 1006 @Override stopInterfaceForwarding(String fromIface, String toIface)1007 public void stopInterfaceForwarding(String fromIface, String toIface) { 1008 NetworkStack.checkNetworkStackPermission(mContext); 1009 modifyInterfaceForward(false, fromIface, toIface); 1010 } 1011 1012 @Override enableNat(String internalInterface, String externalInterface)1013 public void enableNat(String internalInterface, String externalInterface) { 1014 NetworkStack.checkNetworkStackPermission(mContext); 1015 try { 1016 mNetdService.tetherAddForward(internalInterface, externalInterface); 1017 } catch (RemoteException | ServiceSpecificException e) { 1018 throw new IllegalStateException(e); 1019 } 1020 } 1021 1022 @Override disableNat(String internalInterface, String externalInterface)1023 public void disableNat(String internalInterface, String externalInterface) { 1024 NetworkStack.checkNetworkStackPermission(mContext); 1025 try { 1026 mNetdService.tetherRemoveForward(internalInterface, externalInterface); 1027 } catch (RemoteException | ServiceSpecificException e) { 1028 throw new IllegalStateException(e); 1029 } 1030 } 1031 1032 @Override setInterfaceQuota(String iface, long quotaBytes)1033 public void setInterfaceQuota(String iface, long quotaBytes) { 1034 NetworkStack.checkNetworkStackPermission(mContext); 1035 1036 synchronized (mQuotaLock) { 1037 if (mActiveQuotas.containsKey(iface)) { 1038 throw new IllegalStateException("iface " + iface + " already has quota"); 1039 } 1040 1041 try { 1042 // TODO: support quota shared across interfaces 1043 mNetdService.bandwidthSetInterfaceQuota(iface, quotaBytes); 1044 1045 mActiveQuotas.put(iface, quotaBytes); 1046 } catch (RemoteException | ServiceSpecificException e) { 1047 throw new IllegalStateException(e); 1048 } 1049 1050 synchronized (mTetheringStatsProviders) { 1051 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) { 1052 try { 1053 provider.setInterfaceQuota(iface, quotaBytes); 1054 } catch (RemoteException e) { 1055 Log.e(TAG, "Problem setting tethering data limit on provider " + 1056 mTetheringStatsProviders.get(provider) + ": " + e); 1057 } 1058 } 1059 } 1060 } 1061 } 1062 1063 @Override removeInterfaceQuota(String iface)1064 public void removeInterfaceQuota(String iface) { 1065 NetworkStack.checkNetworkStackPermission(mContext); 1066 1067 synchronized (mQuotaLock) { 1068 if (!mActiveQuotas.containsKey(iface)) { 1069 // TODO: eventually consider throwing 1070 return; 1071 } 1072 1073 mActiveQuotas.remove(iface); 1074 mActiveAlerts.remove(iface); 1075 1076 try { 1077 // TODO: support quota shared across interfaces 1078 mNetdService.bandwidthRemoveInterfaceQuota(iface); 1079 } catch (RemoteException | ServiceSpecificException e) { 1080 throw new IllegalStateException(e); 1081 } 1082 1083 synchronized (mTetheringStatsProviders) { 1084 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) { 1085 try { 1086 provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED); 1087 } catch (RemoteException e) { 1088 Log.e(TAG, "Problem removing tethering data limit on provider " + 1089 mTetheringStatsProviders.get(provider) + ": " + e); 1090 } 1091 } 1092 } 1093 } 1094 } 1095 1096 @Override setInterfaceAlert(String iface, long alertBytes)1097 public void setInterfaceAlert(String iface, long alertBytes) { 1098 NetworkStack.checkNetworkStackPermission(mContext); 1099 1100 // quick validity check 1101 if (!mActiveQuotas.containsKey(iface)) { 1102 throw new IllegalStateException("setting alert requires existing quota on iface"); 1103 } 1104 1105 synchronized (mQuotaLock) { 1106 if (mActiveAlerts.containsKey(iface)) { 1107 throw new IllegalStateException("iface " + iface + " already has alert"); 1108 } 1109 1110 try { 1111 // TODO: support alert shared across interfaces 1112 mNetdService.bandwidthSetInterfaceAlert(iface, alertBytes); 1113 mActiveAlerts.put(iface, alertBytes); 1114 } catch (RemoteException | ServiceSpecificException e) { 1115 throw new IllegalStateException(e); 1116 } 1117 } 1118 } 1119 1120 @Override removeInterfaceAlert(String iface)1121 public void removeInterfaceAlert(String iface) { 1122 NetworkStack.checkNetworkStackPermission(mContext); 1123 1124 synchronized (mQuotaLock) { 1125 if (!mActiveAlerts.containsKey(iface)) { 1126 // TODO: eventually consider throwing 1127 return; 1128 } 1129 1130 try { 1131 // TODO: support alert shared across interfaces 1132 mNetdService.bandwidthRemoveInterfaceAlert(iface); 1133 mActiveAlerts.remove(iface); 1134 } catch (RemoteException | ServiceSpecificException e) { 1135 throw new IllegalStateException(e); 1136 } 1137 } 1138 } 1139 1140 @Override setGlobalAlert(long alertBytes)1141 public void setGlobalAlert(long alertBytes) { 1142 NetworkStack.checkNetworkStackPermission(mContext); 1143 1144 try { 1145 mNetdService.bandwidthSetGlobalAlert(alertBytes); 1146 } catch (RemoteException | ServiceSpecificException e) { 1147 throw new IllegalStateException(e); 1148 } 1149 } 1150 setUidOnMeteredNetworkList(int uid, boolean allowlist, boolean enable)1151 private void setUidOnMeteredNetworkList(int uid, boolean allowlist, boolean enable) { 1152 NetworkStack.checkNetworkStackPermission(mContext); 1153 1154 synchronized (mQuotaLock) { 1155 boolean oldEnable; 1156 SparseBooleanArray quotaList; 1157 synchronized (mRulesLock) { 1158 quotaList = allowlist ? mUidAllowOnMetered : mUidRejectOnMetered; 1159 oldEnable = quotaList.get(uid, false); 1160 } 1161 if (oldEnable == enable) { 1162 // TODO: eventually consider throwing 1163 return; 1164 } 1165 1166 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth"); 1167 final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1168 try { 1169 if (allowlist) { 1170 if (enable) { 1171 cm.addUidToMeteredNetworkAllowList(uid); 1172 } else { 1173 cm.removeUidFromMeteredNetworkAllowList(uid); 1174 } 1175 } else { 1176 if (enable) { 1177 cm.addUidToMeteredNetworkDenyList(uid); 1178 } else { 1179 cm.removeUidFromMeteredNetworkDenyList(uid); 1180 } 1181 } 1182 synchronized (mRulesLock) { 1183 if (enable) { 1184 quotaList.put(uid, true); 1185 } else { 1186 quotaList.delete(uid); 1187 } 1188 } 1189 } catch (RuntimeException e) { 1190 throw new IllegalStateException(e); 1191 } finally { 1192 Trace.traceEnd(Trace.TRACE_TAG_NETWORK); 1193 } 1194 } 1195 } 1196 1197 @Override setUidOnMeteredNetworkDenylist(int uid, boolean enable)1198 public void setUidOnMeteredNetworkDenylist(int uid, boolean enable) { 1199 setUidOnMeteredNetworkList(uid, false, enable); 1200 } 1201 1202 @Override setUidOnMeteredNetworkAllowlist(int uid, boolean enable)1203 public void setUidOnMeteredNetworkAllowlist(int uid, boolean enable) { 1204 setUidOnMeteredNetworkList(uid, true, enable); 1205 } 1206 1207 @android.annotation.EnforcePermission(android.Manifest.permission.NETWORK_SETTINGS) 1208 @Override setDataSaverModeEnabled(boolean enable)1209 public boolean setDataSaverModeEnabled(boolean enable) { 1210 1211 super.setDataSaverModeEnabled_enforcePermission(); 1212 1213 if (DBG) Log.d(TAG, "setDataSaverMode: " + enable); 1214 synchronized (mQuotaLock) { 1215 if (mDataSaverMode == enable) { 1216 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode); 1217 return true; 1218 } 1219 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver"); 1220 try { 1221 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable); 1222 if (changed) { 1223 mDataSaverMode = enable; 1224 } else { 1225 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed"); 1226 } 1227 return changed; 1228 } catch (RemoteException e) { 1229 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e); 1230 return false; 1231 } finally { 1232 Trace.traceEnd(Trace.TRACE_TAG_NETWORK); 1233 } 1234 } 1235 } 1236 applyUidCleartextNetworkPolicy(int uid, int policy)1237 private void applyUidCleartextNetworkPolicy(int uid, int policy) { 1238 final int policyValue; 1239 switch (policy) { 1240 case StrictMode.NETWORK_POLICY_ACCEPT: 1241 policyValue = INetd.PENALTY_POLICY_ACCEPT; 1242 break; 1243 case StrictMode.NETWORK_POLICY_LOG: 1244 policyValue = INetd.PENALTY_POLICY_LOG; 1245 break; 1246 case StrictMode.NETWORK_POLICY_REJECT: 1247 policyValue = INetd.PENALTY_POLICY_REJECT; 1248 break; 1249 default: 1250 throw new IllegalArgumentException("Unknown policy " + policy); 1251 } 1252 1253 try { 1254 mNetdService.strictUidCleartextPenalty(uid, policyValue); 1255 mUidCleartextPolicy.put(uid, policy); 1256 } catch (RemoteException | ServiceSpecificException e) { 1257 throw new IllegalStateException(e); 1258 } 1259 } 1260 1261 @Override setUidCleartextNetworkPolicy(int uid, int policy)1262 public void setUidCleartextNetworkPolicy(int uid, int policy) { 1263 if (mDeps.getCallingUid() != uid) { 1264 NetworkStack.checkNetworkStackPermission(mContext); 1265 } 1266 1267 synchronized (mQuotaLock) { 1268 final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT); 1269 if (oldPolicy == policy) { 1270 // This also ensures we won't needlessly apply an ACCEPT policy if we've just 1271 // enabled strict and the underlying iptables rules are empty. 1272 return; 1273 } 1274 1275 // TODO: remove this code after removing prepareNativeDaemon() 1276 if (!mStrictEnabled) { 1277 // Module isn't enabled yet; stash the requested policy away to 1278 // apply later once the daemon is connected. 1279 mUidCleartextPolicy.put(uid, policy); 1280 return; 1281 } 1282 1283 // netd does not keep state on strict mode policies, and cannot replace a non-accept 1284 // policy without deleting it first. Rather than add state to netd, just always send 1285 // it an accept policy when switching between two non-accept policies. 1286 // TODO: consider keeping state in netd so we can simplify this code. 1287 if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT && 1288 policy != StrictMode.NETWORK_POLICY_ACCEPT) { 1289 applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT); 1290 } 1291 1292 applyUidCleartextNetworkPolicy(uid, policy); 1293 } 1294 } 1295 1296 @Override isBandwidthControlEnabled()1297 public boolean isBandwidthControlEnabled() { 1298 return true; 1299 } 1300 1301 private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub { 1302 @Override getTetherStats(int how)1303 public NetworkStats getTetherStats(int how) { 1304 // Remove the implementation of NetdTetheringStatsProvider#getTetherStats 1305 // since all callers are migrated to use INetd#tetherGetStats directly. 1306 throw new UnsupportedOperationException(); 1307 } 1308 1309 @Override setInterfaceQuota(String iface, long quotaBytes)1310 public void setInterfaceQuota(String iface, long quotaBytes) { 1311 // Do nothing. netd is already informed of quota changes in setInterfaceQuota. 1312 } 1313 } 1314 1315 @Override getNetworkStatsTethering(int how)1316 public NetworkStats getNetworkStatsTethering(int how) { 1317 // Remove the implementation of getNetworkStatsTethering since all callers are migrated 1318 // to use INetd#tetherGetStats directly. 1319 throw new UnsupportedOperationException(); 1320 } 1321 1322 @Override setFirewallEnabled(boolean enabled)1323 public void setFirewallEnabled(boolean enabled) { 1324 enforceSystemUid(); 1325 try { 1326 mNetdService.firewallSetFirewallType( 1327 enabled ? INetd.FIREWALL_ALLOWLIST : INetd.FIREWALL_DENYLIST); 1328 mFirewallEnabled = enabled; 1329 } catch (RemoteException | ServiceSpecificException e) { 1330 throw new IllegalStateException(e); 1331 } 1332 } 1333 1334 @Override isFirewallEnabled()1335 public boolean isFirewallEnabled() { 1336 enforceSystemUid(); 1337 return mFirewallEnabled; 1338 } 1339 1340 @Override setFirewallInterfaceRule(String iface, boolean allow)1341 public void setFirewallInterfaceRule(String iface, boolean allow) { 1342 enforceSystemUid(); 1343 Preconditions.checkState(mFirewallEnabled); 1344 try { 1345 mNetdService.firewallSetInterfaceRule(iface, 1346 allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY); 1347 } catch (RemoteException | ServiceSpecificException e) { 1348 throw new IllegalStateException(e); 1349 } 1350 } 1351 1352 @Override setFirewallChainEnabled(int chain, boolean enable)1353 public void setFirewallChainEnabled(int chain, boolean enable) { 1354 enforceSystemUid(); 1355 synchronized (mQuotaLock) { 1356 synchronized (mRulesLock) { 1357 if (getFirewallChainState(chain) == enable) { 1358 // All is the same, nothing to do. This relies on the fact that netd has child 1359 // chains default detached. 1360 return; 1361 } 1362 setFirewallChainState(chain, enable); 1363 } 1364 1365 final String chainName = getFirewallChainName(chain); 1366 if (chain == FIREWALL_CHAIN_NONE) { 1367 throw new IllegalArgumentException("Bad child chain: " + chainName); 1368 } 1369 1370 final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1371 try { 1372 cm.setFirewallChainEnabled(chain, enable); 1373 } catch (RuntimeException e) { 1374 throw new IllegalStateException(e); 1375 } 1376 } 1377 } 1378 getFirewallChainName(int chain)1379 private String getFirewallChainName(int chain) { 1380 switch (chain) { 1381 case FIREWALL_CHAIN_STANDBY: 1382 return FIREWALL_CHAIN_NAME_STANDBY; 1383 case FIREWALL_CHAIN_DOZABLE: 1384 return FIREWALL_CHAIN_NAME_DOZABLE; 1385 case FIREWALL_CHAIN_POWERSAVE: 1386 return FIREWALL_CHAIN_NAME_POWERSAVE; 1387 case FIREWALL_CHAIN_RESTRICTED: 1388 return FIREWALL_CHAIN_NAME_RESTRICTED; 1389 case FIREWALL_CHAIN_LOW_POWER_STANDBY: 1390 return FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY; 1391 default: 1392 throw new IllegalArgumentException("Bad child chain: " + chain); 1393 } 1394 } 1395 getFirewallType(int chain)1396 private int getFirewallType(int chain) { 1397 switch (chain) { 1398 case FIREWALL_CHAIN_STANDBY: 1399 return FIREWALL_DENYLIST; 1400 case FIREWALL_CHAIN_DOZABLE: 1401 return FIREWALL_ALLOWLIST; 1402 case FIREWALL_CHAIN_POWERSAVE: 1403 return FIREWALL_ALLOWLIST; 1404 case FIREWALL_CHAIN_RESTRICTED: 1405 return FIREWALL_ALLOWLIST; 1406 case FIREWALL_CHAIN_LOW_POWER_STANDBY: 1407 return FIREWALL_ALLOWLIST; 1408 default: 1409 return isFirewallEnabled() ? FIREWALL_ALLOWLIST : FIREWALL_DENYLIST; 1410 } 1411 } 1412 1413 @Override setFirewallUidRules(int chain, int[] uids, int[] rules)1414 public void setFirewallUidRules(int chain, int[] uids, int[] rules) { 1415 enforceSystemUid(); 1416 synchronized (mQuotaLock) { 1417 synchronized (mRulesLock) { 1418 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain); 1419 SparseIntArray newRules = new SparseIntArray(); 1420 // apply new set of rules 1421 for (int index = uids.length - 1; index >= 0; --index) { 1422 int uid = uids[index]; 1423 int rule = rules[index]; 1424 updateFirewallUidRuleLocked(chain, uid, rule); 1425 newRules.put(uid, rule); 1426 } 1427 // collect the rules to remove. 1428 SparseIntArray rulesToRemove = new SparseIntArray(); 1429 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) { 1430 int uid = uidFirewallRules.keyAt(index); 1431 if (newRules.indexOfKey(uid) < 0) { 1432 rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT); 1433 } 1434 } 1435 // remove dead rules 1436 for (int index = rulesToRemove.size() - 1; index >= 0; --index) { 1437 int uid = rulesToRemove.keyAt(index); 1438 updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT); 1439 } 1440 } 1441 final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1442 try { 1443 cm.replaceFirewallChain(chain, uids); 1444 } catch (RuntimeException e) { 1445 Slog.w(TAG, "Error flushing firewall chain " + chain, e); 1446 } 1447 } 1448 } 1449 1450 @Override setFirewallUidRule(int chain, int uid, int rule)1451 public void setFirewallUidRule(int chain, int uid, int rule) { 1452 enforceSystemUid(); 1453 synchronized (mQuotaLock) { 1454 setFirewallUidRuleLocked(chain, uid, rule); 1455 } 1456 } 1457 setFirewallUidRuleLocked(int chain, int uid, int rule)1458 private void setFirewallUidRuleLocked(int chain, int uid, int rule) { 1459 if (updateFirewallUidRuleLocked(chain, uid, rule)) { 1460 final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1461 try { 1462 cm.setUidFirewallRule(chain, uid, rule); 1463 } catch (RuntimeException e) { 1464 throw new IllegalStateException(e); 1465 } 1466 } 1467 } 1468 1469 // TODO: now that netd supports batching, NMS should not keep these data structures anymore... updateFirewallUidRuleLocked(int chain, int uid, int rule)1470 private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) { 1471 synchronized (mRulesLock) { 1472 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain); 1473 1474 final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT); 1475 if (DBG) { 1476 Slog.d(TAG, "oldRule = " + oldUidFirewallRule 1477 + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain); 1478 } 1479 if (oldUidFirewallRule == rule) { 1480 if (DBG) Slog.d(TAG, "!!!!! Skipping change"); 1481 // TODO: eventually consider throwing 1482 return false; 1483 } 1484 1485 String ruleName = getFirewallRuleName(chain, rule); 1486 String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule); 1487 1488 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { 1489 uidFirewallRules.delete(uid); 1490 } else { 1491 uidFirewallRules.put(uid, rule); 1492 } 1493 return !ruleName.equals(oldRuleName); 1494 } 1495 } 1496 getFirewallRuleName(int chain, int rule)1497 private @NonNull String getFirewallRuleName(int chain, int rule) { 1498 String ruleName; 1499 if (getFirewallType(chain) == FIREWALL_ALLOWLIST) { 1500 if (rule == FIREWALL_RULE_ALLOW) { 1501 ruleName = "allow"; 1502 } else { 1503 ruleName = "deny"; 1504 } 1505 } else { // Deny mode 1506 if (rule == FIREWALL_RULE_DENY) { 1507 ruleName = "deny"; 1508 } else { 1509 ruleName = "allow"; 1510 } 1511 } 1512 return ruleName; 1513 } 1514 1515 @GuardedBy("mRulesLock") getUidFirewallRulesLR(int chain)1516 private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) { 1517 switch (chain) { 1518 case FIREWALL_CHAIN_STANDBY: 1519 return mUidFirewallStandbyRules; 1520 case FIREWALL_CHAIN_DOZABLE: 1521 return mUidFirewallDozableRules; 1522 case FIREWALL_CHAIN_POWERSAVE: 1523 return mUidFirewallPowerSaveRules; 1524 case FIREWALL_CHAIN_RESTRICTED: 1525 return mUidFirewallRestrictedRules; 1526 case FIREWALL_CHAIN_LOW_POWER_STANDBY: 1527 return mUidFirewallLowPowerStandbyRules; 1528 case FIREWALL_CHAIN_NONE: 1529 return mUidFirewallRules; 1530 default: 1531 throw new IllegalArgumentException("Unknown chain:" + chain); 1532 } 1533 } 1534 enforceSystemUid()1535 private void enforceSystemUid() { 1536 final int uid = mDeps.getCallingUid(); 1537 if (uid != Process.SYSTEM_UID) { 1538 throw new SecurityException("Only available to AID_SYSTEM"); 1539 } 1540 } 1541 1542 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1543 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1544 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1545 1546 synchronized (mQuotaLock) { 1547 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 1548 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 1549 pw.print("Data saver mode: "); pw.println(mDataSaverMode); 1550 synchronized (mRulesLock) { 1551 dumpUidRuleOnQuotaLocked(pw, "denied UIDs", mUidRejectOnMetered); 1552 dumpUidRuleOnQuotaLocked(pw, "allowed UIDs", mUidAllowOnMetered); 1553 } 1554 } 1555 1556 synchronized (mRulesLock) { 1557 dumpUidFirewallRule(pw, "", mUidFirewallRules); 1558 1559 pw.print("UID firewall standby chain enabled: "); 1560 pw.println(getFirewallChainState(FIREWALL_CHAIN_STANDBY)); 1561 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules); 1562 1563 pw.print("UID firewall dozable chain enabled: "); 1564 pw.println(getFirewallChainState(FIREWALL_CHAIN_DOZABLE)); 1565 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules); 1566 1567 pw.print("UID firewall powersave chain enabled: "); 1568 pw.println(getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)); 1569 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules); 1570 1571 pw.print("UID firewall restricted mode chain enabled: "); 1572 pw.println(getFirewallChainState(FIREWALL_CHAIN_RESTRICTED)); 1573 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_RESTRICTED, 1574 mUidFirewallRestrictedRules); 1575 1576 pw.print("UID firewall low power standby chain enabled: "); 1577 pw.println(getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY)); 1578 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY, 1579 mUidFirewallLowPowerStandbyRules); 1580 } 1581 1582 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 1583 pw.print("Netd service status: " ); 1584 if (mNetdService == null) { 1585 pw.println("disconnected"); 1586 } else { 1587 try { 1588 final boolean alive = mNetdService.isAlive(); 1589 pw.println(alive ? "alive": "dead"); 1590 } catch (RemoteException e) { 1591 pw.println("unreachable"); 1592 } 1593 } 1594 } 1595 dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list)1596 private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) { 1597 pw.print("UID bandwith control "); 1598 pw.print(name); 1599 pw.print(": ["); 1600 final int size = list.size(); 1601 for (int i = 0; i < size; i++) { 1602 pw.print(list.keyAt(i)); 1603 if (i < size - 1) pw.print(","); 1604 } 1605 pw.println("]"); 1606 } 1607 dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules)1608 private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) { 1609 pw.print("UID firewall "); 1610 pw.print(name); 1611 pw.print(" rule: ["); 1612 final int size = rules.size(); 1613 for (int i = 0; i < size; i++) { 1614 pw.print(rules.keyAt(i)); 1615 pw.print(":"); 1616 pw.print(rules.valueAt(i)); 1617 if (i < size - 1) pw.print(","); 1618 } 1619 pw.println("]"); 1620 } 1621 modifyInterfaceInNetwork(boolean add, int netId, String iface)1622 private void modifyInterfaceInNetwork(boolean add, int netId, String iface) { 1623 NetworkStack.checkNetworkStackPermission(mContext); 1624 try { 1625 if (add) { 1626 mNetdService.networkAddInterface(netId, iface); 1627 } else { 1628 mNetdService.networkRemoveInterface(netId, iface); 1629 } 1630 } catch (RemoteException | ServiceSpecificException e) { 1631 throw new IllegalStateException(e); 1632 } 1633 } 1634 1635 @Override allowProtect(int uid)1636 public void allowProtect(int uid) { 1637 NetworkStack.checkNetworkStackPermission(mContext); 1638 1639 try { 1640 mNetdService.networkSetProtectAllow(uid); 1641 } catch (RemoteException | ServiceSpecificException e) { 1642 throw new IllegalStateException(e); 1643 } 1644 } 1645 1646 @Override denyProtect(int uid)1647 public void denyProtect(int uid) { 1648 NetworkStack.checkNetworkStackPermission(mContext); 1649 1650 try { 1651 mNetdService.networkSetProtectDeny(uid); 1652 } catch (RemoteException | ServiceSpecificException e) { 1653 throw new IllegalStateException(e); 1654 } 1655 } 1656 1657 @Override addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes)1658 public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) { 1659 modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface); 1660 // modifyInterfaceInNetwork already check calling permission. 1661 NetdUtils.addRoutesToLocalNetwork(mNetdService, iface, routes); 1662 } 1663 1664 @Override removeInterfaceFromLocalNetwork(String iface)1665 public void removeInterfaceFromLocalNetwork(String iface) { 1666 modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, iface); 1667 } 1668 1669 @Override removeRoutesFromLocalNetwork(List<RouteInfo> routes)1670 public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) { 1671 NetworkStack.checkNetworkStackPermission(mContext); 1672 return NetdUtils.removeRoutesFromLocalNetwork(mNetdService, routes); 1673 } 1674 1675 @android.annotation.EnforcePermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) 1676 @Override isNetworkRestricted(int uid)1677 public boolean isNetworkRestricted(int uid) { 1678 super.isNetworkRestricted_enforcePermission(); 1679 1680 return isNetworkRestrictedInternal(uid); 1681 } 1682 isNetworkRestrictedInternal(int uid)1683 private boolean isNetworkRestrictedInternal(int uid) { 1684 synchronized (mRulesLock) { 1685 if (getFirewallChainState(FIREWALL_CHAIN_STANDBY) 1686 && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) { 1687 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode"); 1688 return true; 1689 } 1690 if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE) 1691 && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) { 1692 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode"); 1693 return true; 1694 } 1695 if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE) 1696 && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) { 1697 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode"); 1698 return true; 1699 } 1700 if (getFirewallChainState(FIREWALL_CHAIN_RESTRICTED) 1701 && mUidFirewallRestrictedRules.get(uid) != FIREWALL_RULE_ALLOW) { 1702 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of restricted mode"); 1703 return true; 1704 } 1705 if (getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY) 1706 && mUidFirewallLowPowerStandbyRules.get(uid) != FIREWALL_RULE_ALLOW) { 1707 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of low power standby"); 1708 return true; 1709 } 1710 if (mUidRejectOnMetered.get(uid)) { 1711 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data" 1712 + " in the background"); 1713 return true; 1714 } 1715 if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) { 1716 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode"); 1717 return true; 1718 } 1719 return false; 1720 } 1721 } 1722 setFirewallChainState(int chain, boolean state)1723 private void setFirewallChainState(int chain, boolean state) { 1724 synchronized (mRulesLock) { 1725 mFirewallChainStates.put(chain, state); 1726 } 1727 } 1728 getFirewallChainState(int chain)1729 private boolean getFirewallChainState(int chain) { 1730 synchronized (mRulesLock) { 1731 return mFirewallChainStates.get(chain); 1732 } 1733 } 1734 1735 private class LocalService extends NetworkManagementInternal { 1736 @Override isNetworkRestrictedForUid(int uid)1737 public boolean isNetworkRestrictedForUid(int uid) { 1738 return isNetworkRestrictedInternal(uid); 1739 } 1740 } 1741 } 1742