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