1 /* 2 * Copyright (C) 2016 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 android.net.ip; 18 19 import static android.net.INetd.LOCAL_NET_ID; 20 import static android.net.RouteInfo.RTN_UNICAST; 21 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL; 22 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL; 23 import static android.net.TetheringManager.TETHERING_BLUETOOTH; 24 import static android.net.TetheringManager.TETHERING_ETHERNET; 25 import static android.net.TetheringManager.TETHERING_NCM; 26 import static android.net.TetheringManager.TETHERING_WIFI; 27 import static android.net.TetheringManager.TETHERING_WIFI_P2P; 28 import static android.net.TetheringManager.TETHERING_WIGIG; 29 import static android.net.TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR; 30 import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR; 31 import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR; 32 import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR; 33 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; 34 import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL; 35 import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR; 36 import static android.net.TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR; 37 import static android.net.TetheringManager.TetheringRequest.checkStaticAddressConfiguration; 38 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; 39 import static android.net.util.NetworkConstants.asByte; 40 import static android.system.OsConstants.RT_SCOPE_UNIVERSE; 41 42 import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; 43 import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH; 44 import static com.android.networkstack.tethering.TetheringConfiguration.TETHERING_LOCAL_NETWORK_AGENT; 45 import static com.android.networkstack.tethering.TetheringConfiguration.USE_SYNC_SM; 46 import static com.android.networkstack.tethering.util.PrefixUtils.asIpPrefix; 47 import static com.android.networkstack.tethering.util.TetheringMessageBase.BASE_IPSERVER; 48 import static com.android.networkstack.tethering.util.TetheringUtils.getTransportTypeForTetherableType; 49 50 import android.annotation.SuppressLint; 51 import android.content.Context; 52 import android.net.INetd; 53 import android.net.INetworkStackStatusCallback; 54 import android.net.IpPrefix; 55 import android.net.LinkAddress; 56 import android.net.LinkProperties; 57 import android.net.MacAddress; 58 import android.net.NetworkAgent; 59 import android.net.RouteInfo; 60 import android.net.TetheredClient; 61 import android.net.TetheringManager.TetheringRequest; 62 import android.net.connectivity.ConnectivityInternalApiUtil; 63 import android.net.dhcp.DhcpLeaseParcelable; 64 import android.net.dhcp.DhcpServerCallbacks; 65 import android.net.dhcp.DhcpServingParamsParcel; 66 import android.net.dhcp.DhcpServingParamsParcelExt; 67 import android.net.dhcp.IDhcpEventCallbacks; 68 import android.net.dhcp.IDhcpServer; 69 import android.net.ip.RouterAdvertisementDaemon.RaParams; 70 import android.os.Build; 71 import android.os.Handler; 72 import android.os.Looper; 73 import android.os.Message; 74 import android.os.RemoteException; 75 import android.os.ServiceSpecificException; 76 import android.util.ArraySet; 77 import android.util.Log; 78 import android.util.SparseArray; 79 80 import androidx.annotation.NonNull; 81 import androidx.annotation.Nullable; 82 import androidx.annotation.RequiresApi; 83 84 import com.android.internal.annotations.VisibleForTesting; 85 import com.android.internal.util.MessageUtils; 86 import com.android.internal.util.State; 87 import com.android.modules.utils.build.SdkLevel; 88 import com.android.net.module.util.DeviceConfigUtils; 89 import com.android.net.module.util.IIpv4PrefixRequest; 90 import com.android.net.module.util.InterfaceParams; 91 import com.android.net.module.util.NetdUtils; 92 import com.android.net.module.util.RoutingCoordinatorManager; 93 import com.android.net.module.util.SharedLog; 94 import com.android.net.module.util.SyncStateMachine.StateInfo; 95 import com.android.net.module.util.ip.InterfaceController; 96 import com.android.networkstack.tethering.BpfCoordinator; 97 import com.android.networkstack.tethering.TetheringConfiguration; 98 import com.android.networkstack.tethering.metrics.TetheringMetrics; 99 import com.android.networkstack.tethering.util.InterfaceSet; 100 import com.android.networkstack.tethering.util.PrefixUtils; 101 import com.android.networkstack.tethering.util.StateMachineShim; 102 103 import java.net.Inet4Address; 104 import java.net.Inet6Address; 105 import java.net.UnknownHostException; 106 import java.util.ArrayList; 107 import java.util.Arrays; 108 import java.util.Collection; 109 import java.util.Collections; 110 import java.util.HashSet; 111 import java.util.List; 112 import java.util.Objects; 113 import java.util.Random; 114 import java.util.Set; 115 116 /** 117 * Provides the interface to IP-layer serving functionality for a given network 118 * interface, e.g. for tethering or "local-only hotspot" mode. 119 * 120 * @hide 121 */ 122 public class IpServer extends StateMachineShim { 123 public static final int STATE_UNAVAILABLE = 0; 124 public static final int STATE_AVAILABLE = 1; 125 public static final int STATE_TETHERED = 2; 126 public static final int STATE_LOCAL_ONLY = 3; 127 128 /** Get string name of |state|.*/ getStateString(int state)129 public static String getStateString(int state) { 130 switch (state) { 131 case STATE_UNAVAILABLE: return "UNAVAILABLE"; 132 case STATE_AVAILABLE: return "AVAILABLE"; 133 case STATE_TETHERED: return "TETHERED"; 134 case STATE_LOCAL_ONLY: return "LOCAL_ONLY"; 135 } 136 return "UNKNOWN: " + state; 137 } 138 139 private static final byte DOUG_ADAMS = (byte) 42; 140 141 // TODO: have PanService use some visible version of this constant 142 private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1/24"; 143 144 private static final String LEGACY_WIFI_P2P_IFACE_ADDRESS = "192.168.49.1/24"; 145 146 // TODO: have this configurable 147 private static final int DHCP_LEASE_TIME_SECS = 3600; 148 149 private static final int NO_UPSTREAM = 0; 150 private static final MacAddress NULL_MAC_ADDRESS = MacAddress.fromString("00:00:00:00:00:00"); 151 152 private static final String TAG = "IpServer"; 153 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); 154 private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE); 155 private static final Class[] sMessageClasses = { 156 IpServer.class 157 }; 158 private static final SparseArray<String> sMagicDecoderRing = 159 MessageUtils.findMessageNames(sMessageClasses); 160 161 /** IpServer callback. */ 162 public static class Callback { 163 /** 164 * Notify that |who| has changed its tethering state. 165 * 166 * @param who the calling instance of IpServer 167 * @param state one of STATE_* 168 * @param lastError one of TetheringManager.TETHER_ERROR_* 169 */ updateInterfaceState(IpServer who, int state, int lastError)170 public void updateInterfaceState(IpServer who, int state, int lastError) { } 171 172 /** 173 * Notify that |who| has new LinkProperties. 174 * 175 * @param who the calling instance of IpServer 176 * @param newLp the new LinkProperties to report 177 */ updateLinkProperties(IpServer who, LinkProperties newLp)178 public void updateLinkProperties(IpServer who, LinkProperties newLp) { } 179 180 /** 181 * Notify that the DHCP leases changed in one of the IpServers. 182 */ dhcpLeasesChanged()183 public void dhcpLeasesChanged() { } 184 185 /** 186 * Request Tethering change. 187 * 188 * @param tetheringType the downstream type of this IpServer. 189 * @param enabled enable or disable tethering. 190 */ requestEnableTethering(int tetheringType, boolean enabled)191 public void requestEnableTethering(int tetheringType, boolean enabled) { } 192 } 193 194 /** Capture IpServer dependencies, for injection. */ 195 public abstract static class Dependencies { 196 /** 197 * Create a DadProxy instance to be used by IpServer. 198 * To support multiple tethered interfaces concurrently DAD Proxy 199 * needs to be supported per IpServer instead of per upstream. 200 */ getDadProxy(Handler handler, InterfaceParams ifParams)201 public DadProxy getDadProxy(Handler handler, InterfaceParams ifParams) { 202 return new DadProxy(handler, ifParams); 203 } 204 205 /** Create a RouterAdvertisementDaemon instance to be used by IpServer.*/ getRouterAdvertisementDaemon(InterfaceParams ifParams)206 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) { 207 return new RouterAdvertisementDaemon(ifParams); 208 } 209 210 /** Get |ifName|'s interface information.*/ getInterfaceParams(String ifName)211 public InterfaceParams getInterfaceParams(String ifName) { 212 return InterfaceParams.getByName(ifName); 213 } 214 215 /** Create a DhcpServer instance to be used by IpServer. */ makeDhcpServer(String ifName, DhcpServingParamsParcel params, DhcpServerCallbacks cb)216 public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params, 217 DhcpServerCallbacks cb); 218 219 /** 220 * @see DeviceConfigUtils#isTetheringFeatureEnabled 221 */ isFeatureEnabled(Context context, String name)222 public boolean isFeatureEnabled(Context context, String name) { 223 return DeviceConfigUtils.isTetheringFeatureEnabled(context, name); 224 } 225 226 /** Create a NetworkAgent instance to be used by IpServer. */ 227 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 228 @SuppressLint("NewApi") makeNetworkAgent( @onNull Context context, @NonNull Looper looper, @NonNull String logTag, int interfaceType, @NonNull LinkProperties lp)229 public NetworkAgent makeNetworkAgent( 230 @NonNull Context context, @NonNull Looper looper, @NonNull String logTag, 231 int interfaceType, @NonNull LinkProperties lp) { 232 return ConnectivityInternalApiUtil.buildTetheringNetworkAgent( 233 context, looper, logTag, getTransportTypeForTetherableType(interfaceType), lp); 234 } 235 } 236 237 // request from the user that it wants to tether 238 public static final int CMD_TETHER_REQUESTED = BASE_IPSERVER + 1; 239 // request from the user that it wants to untether 240 public static final int CMD_TETHER_UNREQUESTED = BASE_IPSERVER + 2; 241 // notification that this interface is down 242 public static final int CMD_INTERFACE_DOWN = BASE_IPSERVER + 3; 243 // notification from the {@link Tethering.TetherMainSM} that it had trouble enabling IP 244 // Forwarding 245 public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IPSERVER + 4; 246 // notification from the {@link Tethering.TetherMainSM} SM that it had trouble disabling IP 247 // Forwarding 248 public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IPSERVER + 5; 249 // notification from the {@link Tethering.TetherMainSM} SM that it had trouble starting 250 // tethering 251 public static final int CMD_START_TETHERING_ERROR = BASE_IPSERVER + 6; 252 // notification from the {@link Tethering.TetherMainSM} that it had trouble stopping tethering 253 public static final int CMD_STOP_TETHERING_ERROR = BASE_IPSERVER + 7; 254 // notification from the {@link Tethering.TetherMainSM} that it had trouble setting the DNS 255 // forwarders 256 public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IPSERVER + 8; 257 // the upstream connection has changed 258 public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IPSERVER + 9; 259 // new IPv6 tethering parameters need to be processed 260 public static final int CMD_IPV6_TETHER_UPDATE = BASE_IPSERVER + 10; 261 // request from DHCP server that it wants to have a new prefix 262 public static final int CMD_NEW_PREFIX_REQUEST = BASE_IPSERVER + 11; 263 // request from PrivateAddressCoordinator to restart tethering. 264 public static final int CMD_NOTIFY_PREFIX_CONFLICT = BASE_IPSERVER + 12; 265 public static final int CMD_SERVICE_FAILED_TO_START = BASE_IPSERVER + 13; 266 267 private final State mInitialState; 268 private final State mLocalHotspotState; 269 private final State mTetheredState; 270 private final State mUnavailableState; 271 private final State mWaitingForRestartState; 272 273 private final SharedLog mLog; 274 private final INetd mNetd; 275 @NonNull 276 private final BpfCoordinator mBpfCoordinator; 277 @NonNull 278 private final RoutingCoordinatorManager mRoutingCoordinator; 279 @NonNull 280 private final IIpv4PrefixRequest mIpv4PrefixRequest; 281 private final Callback mCallback; 282 private final InterfaceController mInterfaceCtrl; 283 284 private final String mIfaceName; 285 private final int mInterfaceType; 286 private final LinkProperties mLinkProperties; 287 private final boolean mUsingLegacyDhcp; 288 private final int mP2pLeasesSubnetPrefixLength; 289 private final boolean mIsWifiP2pDedicatedIpEnabled; 290 291 private final Dependencies mDeps; 292 293 private int mLastError; 294 private int mServingMode; 295 private InterfaceSet mUpstreamIfaceSet; // may change over time 296 // mInterfaceParams can't be final now because IpServer will be created when receives 297 // WIFI_AP_STATE_CHANGED broadcasts or when it detects that the wifi interface has come up. 298 // In the latter case, the interface is not fully initialized and the MAC address might not 299 // be correct (it will be set with a randomized MAC address later). 300 // TODO: Consider create the IpServer only when tethering want to enable it, then we can 301 // make mInterfaceParams final. 302 private InterfaceParams mInterfaceParams; 303 // TODO: De-duplicate this with mLinkProperties above. Currently, these link 304 // properties are those selected by the IPv6TetheringCoordinator and relayed 305 // to us. By comparison, mLinkProperties contains the addresses and directly 306 // connected routes that have been formed from these properties iff. we have 307 // succeeded in configuring them and are able to announce them within Router 308 // Advertisements (otherwise, we do not add them to mLinkProperties at all). 309 private LinkProperties mLastIPv6LinkProperties; 310 private RouterAdvertisementDaemon mRaDaemon; 311 private DadProxy mDadProxy; 312 313 // To be accessed only on the handler thread 314 private int mDhcpServerStartIndex = 0; 315 private IDhcpServer mDhcpServer; 316 private RaParams mLastRaParams; 317 318 private LinkAddress mStaticIpv4ServerAddr; 319 private LinkAddress mStaticIpv4ClientAddr; 320 321 @NonNull 322 private List<TetheredClient> mDhcpLeases = Collections.emptyList(); 323 324 private int mLastIPv6UpstreamIfindex = 0; 325 @NonNull 326 private Set<IpPrefix> mLastIPv6UpstreamPrefixes = Collections.emptySet(); 327 328 private LinkAddress mIpv4Address; 329 330 @Nullable 331 private TetheringRequest mTetheringRequest; 332 333 private final TetheringMetrics mTetheringMetrics; 334 private final Handler mHandler; 335 private final Context mContext; 336 337 private final boolean mSupportLocalAgent; 338 339 // This will be null if the TetheredState is not entered or feature not supported. 340 // This will be only accessed from the IpServer handler thread. 341 private NetworkAgent mTetheringAgent; 342 everRegistered(@onNull NetworkAgent agent)343 private static boolean everRegistered(@NonNull NetworkAgent agent) { 344 return agent.getNetwork() != null; 345 } 346 347 // TODO: Add a dependency object to pass the data members or variables from the tethering 348 // object. It helps to reduce the arguments of the constructor. IpServer( String ifaceName, @NonNull Context context, Handler handler, int interfaceType, SharedLog log, INetd netd, @NonNull BpfCoordinator bpfCoordinator, RoutingCoordinatorManager routingCoordinatorManager, Callback callback, TetheringConfiguration config, TetheringMetrics tetheringMetrics, Dependencies deps)349 public IpServer( 350 String ifaceName, @NonNull Context context, Handler handler, int interfaceType, 351 SharedLog log, INetd netd, @NonNull BpfCoordinator bpfCoordinator, 352 RoutingCoordinatorManager routingCoordinatorManager, Callback callback, 353 TetheringConfiguration config, 354 TetheringMetrics tetheringMetrics, Dependencies deps) { 355 super(ifaceName, USE_SYNC_SM ? null : handler.getLooper()); 356 mContext = Objects.requireNonNull(context); 357 mHandler = handler; 358 mLog = log.forSubComponent(ifaceName); 359 mNetd = netd; 360 mBpfCoordinator = bpfCoordinator; 361 mRoutingCoordinator = routingCoordinatorManager; 362 mIpv4PrefixRequest = new IIpv4PrefixRequest.Stub() { 363 @Override 364 public void onIpv4PrefixConflict(IpPrefix ipPrefix) throws RemoteException { 365 sendMessage(CMD_NOTIFY_PREFIX_CONFLICT); 366 } 367 }; 368 mCallback = callback; 369 mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog); 370 mIfaceName = ifaceName; 371 mInterfaceType = interfaceType; 372 mLinkProperties = new LinkProperties(); 373 mUsingLegacyDhcp = config.useLegacyDhcpServer(); 374 mP2pLeasesSubnetPrefixLength = config.getP2pLeasesSubnetPrefixLength(); 375 mIsWifiP2pDedicatedIpEnabled = config.shouldEnableWifiP2pDedicatedIp(); 376 mDeps = deps; 377 mTetheringMetrics = tetheringMetrics; 378 resetLinkProperties(); 379 mLastError = TETHER_ERROR_NO_ERROR; 380 mServingMode = STATE_AVAILABLE; 381 382 // Tethering network agent is supported on V+, and will be rolled out gradually. 383 mSupportLocalAgent = SdkLevel.isAtLeastV() 384 && mDeps.isFeatureEnabled(mContext, TETHERING_LOCAL_NETWORK_AGENT); 385 386 mInitialState = new InitialState(); 387 mLocalHotspotState = new LocalHotspotState(); 388 mTetheredState = new TetheredState(); 389 mUnavailableState = new UnavailableState(); 390 mWaitingForRestartState = new WaitingForRestartState(); 391 final ArrayList allStates = new ArrayList<StateInfo>(); 392 allStates.add(new StateInfo(mInitialState, null)); 393 allStates.add(new StateInfo(mLocalHotspotState, null)); 394 allStates.add(new StateInfo(mTetheredState, null)); 395 allStates.add(new StateInfo(mWaitingForRestartState, mTetheredState)); 396 allStates.add(new StateInfo(mUnavailableState, null)); 397 addAllStates(allStates); 398 } 399 getHandler()400 private Handler getHandler() { 401 return mHandler; 402 } 403 404 /** Start IpServer state machine. */ start()405 public void start() { 406 start(mInitialState); 407 } 408 409 /** Interface name which IpServer served.*/ interfaceName()410 public String interfaceName() { 411 return mIfaceName; 412 } 413 414 /** 415 * Tethering downstream type. It would be one of TetheringManager#TETHERING_*. 416 */ interfaceType()417 public int interfaceType() { 418 return mInterfaceType; 419 } 420 421 /** Last error from this IpServer. */ lastError()422 public int lastError() { 423 return mLastError; 424 } 425 426 /** Serving mode is the current state of IpServer state machine. */ servingMode()427 public int servingMode() { 428 return mServingMode; 429 } 430 431 /** The properties of the network link which IpServer is serving. */ linkProperties()432 public LinkProperties linkProperties() { 433 return new LinkProperties(mLinkProperties); 434 } 435 436 /** The address which IpServer is using. */ getAddress()437 public LinkAddress getAddress() { 438 return mIpv4Address; 439 } 440 441 /** The IPv6 upstream interface index */ getIpv6UpstreamIfindex()442 public int getIpv6UpstreamIfindex() { 443 return mLastIPv6UpstreamIfindex; 444 } 445 446 /** The IPv6 upstream interface prefixes */ 447 @NonNull getIpv6UpstreamPrefixes()448 public Set<IpPrefix> getIpv6UpstreamPrefixes() { 449 return Collections.unmodifiableSet(mLastIPv6UpstreamPrefixes); 450 } 451 452 /** The interface parameters which IpServer is using */ getInterfaceParams()453 public InterfaceParams getInterfaceParams() { 454 return mInterfaceParams; 455 } 456 457 @VisibleForTesting getIpv4PrefixRequest()458 public IIpv4PrefixRequest getIpv4PrefixRequest() { 459 return mIpv4PrefixRequest; 460 } 461 462 /** 463 * Get the latest list of DHCP leases that was reported. Must be called on the IpServer looper 464 * thread. 465 */ getAllLeases()466 public List<TetheredClient> getAllLeases() { 467 return Collections.unmodifiableList(mDhcpLeases); 468 } 469 470 /** 471 * Enable this IpServer. IpServer state machine will be tethered or localHotspot state based on 472 * the connectivity scope of the TetheringRequest. */ enable(@onNull final TetheringRequest request)473 public void enable(@NonNull final TetheringRequest request) { 474 sendMessage(CMD_TETHER_REQUESTED, 0, 0, request); 475 } 476 477 /** Stop this IpServer. After this is called this IpServer should not be used any more. */ stop()478 public void stop() { 479 sendMessage(CMD_INTERFACE_DOWN); 480 } 481 482 /** 483 * Tethering is canceled. IpServer state machine will be available and wait for 484 * next tethering request. 485 */ unwanted()486 public void unwanted() { 487 sendMessage(CMD_TETHER_UNREQUESTED); 488 } 489 490 /** Internals. */ 491 startIPv4(int scope)492 private boolean startIPv4(int scope) { 493 return configureIPv4(true, scope); 494 } 495 496 /** 497 * Convenience wrapper around INetworkStackStatusCallback to run callbacks on the IpServer 498 * handler. 499 * 500 * <p>Different instances of this class can be created for each call to IDhcpServer methods, 501 * with different implementations of the callback, to differentiate handling of success/error in 502 * each call. 503 */ 504 private abstract class OnHandlerStatusCallback extends INetworkStackStatusCallback.Stub { 505 @Override onStatusAvailable(int statusCode)506 public void onStatusAvailable(int statusCode) { 507 getHandler().post(() -> callback(statusCode)); 508 } 509 callback(int statusCode)510 public abstract void callback(int statusCode); 511 512 @Override getInterfaceVersion()513 public int getInterfaceVersion() { 514 return this.VERSION; 515 } 516 517 @Override getInterfaceHash()518 public String getInterfaceHash() { 519 return this.HASH; 520 } 521 } 522 523 private class DhcpServerCallbacksImpl extends DhcpServerCallbacks { 524 private final int mStartIndex; 525 DhcpServerCallbacksImpl(int startIndex)526 private DhcpServerCallbacksImpl(int startIndex) { 527 mStartIndex = startIndex; 528 } 529 530 @Override onDhcpServerCreated(int statusCode, IDhcpServer server)531 public void onDhcpServerCreated(int statusCode, IDhcpServer server) throws RemoteException { 532 getHandler().post(() -> { 533 // We are on the handler thread: mDhcpServerStartIndex can be read safely. 534 if (mStartIndex != mDhcpServerStartIndex) { 535 // This start request is obsolete. Explicitly stop the DHCP server to shut 536 // down its thread. When the |server| binder token goes out of scope, the 537 // garbage collector will finalize it, which causes the network stack process 538 // garbage collector to collect the server itself. 539 try { 540 server.stop(null); 541 } catch (RemoteException e) { } 542 return; 543 } 544 545 if (statusCode != STATUS_SUCCESS) { 546 mLog.e("Error obtaining DHCP server: " + statusCode); 547 handleError(); 548 return; 549 } 550 551 mDhcpServer = server; 552 try { 553 mDhcpServer.startWithCallbacks(new OnHandlerStatusCallback() { 554 @Override 555 public void callback(int startStatusCode) { 556 if (startStatusCode != STATUS_SUCCESS) { 557 mLog.e("Error starting DHCP server: " + startStatusCode); 558 handleError(); 559 } 560 } 561 }, new DhcpEventCallback()); 562 } catch (RemoteException e) { 563 throw new IllegalStateException(e); 564 } 565 }); 566 } 567 handleError()568 private void handleError() { 569 mLastError = TETHER_ERROR_DHCPSERVER_ERROR; 570 if (USE_SYNC_SM) { 571 sendMessage(CMD_SERVICE_FAILED_TO_START, TETHER_ERROR_DHCPSERVER_ERROR); 572 } else { 573 sendMessageAtFrontOfQueueToAsyncSM(CMD_SERVICE_FAILED_TO_START, 574 TETHER_ERROR_DHCPSERVER_ERROR); 575 } 576 } 577 } 578 579 private class DhcpEventCallback extends IDhcpEventCallbacks.Stub { 580 @Override onLeasesChanged(List<DhcpLeaseParcelable> leaseParcelables)581 public void onLeasesChanged(List<DhcpLeaseParcelable> leaseParcelables) { 582 final ArrayList<TetheredClient> leases = new ArrayList<>(); 583 for (DhcpLeaseParcelable lease : leaseParcelables) { 584 final LinkAddress address = new LinkAddress( 585 intToInet4AddressHTH(lease.netAddr), lease.prefixLength, 586 0 /* flags */, RT_SCOPE_UNIVERSE /* as per RFC6724#3.2 */, 587 lease.expTime /* deprecationTime */, lease.expTime /* expirationTime */); 588 589 final MacAddress macAddress; 590 try { 591 macAddress = MacAddress.fromBytes(lease.hwAddr); 592 } catch (IllegalArgumentException e) { 593 Log.wtf(TAG, "Invalid address received from DhcpServer: " 594 + Arrays.toString(lease.hwAddr)); 595 return; 596 } 597 598 final TetheredClient.AddressInfo addressInfo = new TetheredClient.AddressInfo( 599 address, lease.hostname); 600 leases.add(new TetheredClient( 601 macAddress, 602 Collections.singletonList(addressInfo), 603 mInterfaceType)); 604 } 605 606 getHandler().post(() -> { 607 mDhcpLeases = leases; 608 mCallback.dhcpLeasesChanged(); 609 }); 610 } 611 612 @Override onNewPrefixRequest(@onNull final IpPrefix currentPrefix)613 public void onNewPrefixRequest(@NonNull final IpPrefix currentPrefix) { 614 Objects.requireNonNull(currentPrefix); 615 sendMessage(CMD_NEW_PREFIX_REQUEST, currentPrefix); 616 } 617 618 @Override getInterfaceVersion()619 public int getInterfaceVersion() { 620 return this.VERSION; 621 } 622 623 @Override getInterfaceHash()624 public String getInterfaceHash() throws RemoteException { 625 return this.HASH; 626 } 627 } 628 getDirectConnectedRoute(@onNull final LinkAddress ipv4Address)629 private RouteInfo getDirectConnectedRoute(@NonNull final LinkAddress ipv4Address) { 630 Objects.requireNonNull(ipv4Address); 631 return new RouteInfo(PrefixUtils.asIpPrefix(ipv4Address), null, mIfaceName, RTN_UNICAST); 632 } 633 makeServingParams(@onNull final Inet4Address defaultRouter, @NonNull final Inet4Address dnsServer, @NonNull LinkAddress serverAddr, @Nullable Inet4Address clientAddr)634 private DhcpServingParamsParcel makeServingParams(@NonNull final Inet4Address defaultRouter, 635 @NonNull final Inet4Address dnsServer, @NonNull LinkAddress serverAddr, 636 @Nullable Inet4Address clientAddr) { 637 final boolean changePrefixOnDecline = 638 (mInterfaceType == TETHERING_NCM && clientAddr == null); 639 final int subnetPrefixLength = mInterfaceType == TETHERING_WIFI_P2P 640 ? mP2pLeasesSubnetPrefixLength : 0 /* default value */; 641 642 return new DhcpServingParamsParcelExt() 643 .setDefaultRouters(defaultRouter) 644 .setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS) 645 .setDnsServers(dnsServer) 646 .setServerAddr(serverAddr) 647 .setMetered(true) 648 .setSingleClientAddr(clientAddr) 649 .setChangePrefixOnDecline(changePrefixOnDecline) 650 .setLeasesSubnetPrefixLength(subnetPrefixLength); 651 // TODO: also advertise link MTU 652 } 653 startDhcp(final LinkAddress serverLinkAddr, final LinkAddress clientLinkAddr)654 private boolean startDhcp(final LinkAddress serverLinkAddr, final LinkAddress clientLinkAddr) { 655 if (mUsingLegacyDhcp) { 656 return true; 657 } 658 659 final Inet4Address addr = (Inet4Address) serverLinkAddr.getAddress(); 660 final Inet4Address clientAddr = clientLinkAddr == null ? null : 661 (Inet4Address) clientLinkAddr.getAddress(); 662 663 final DhcpServingParamsParcel params = makeServingParams(addr /* defaultRouter */, 664 addr /* dnsServer */, serverLinkAddr, clientAddr); 665 mDhcpServerStartIndex++; 666 mDeps.makeDhcpServer( 667 mIfaceName, params, new DhcpServerCallbacksImpl(mDhcpServerStartIndex)); 668 return true; 669 } 670 stopDhcp()671 private void stopDhcp() { 672 // Make all previous start requests obsolete so servers are not started later 673 mDhcpServerStartIndex++; 674 675 if (mDhcpServer != null) { 676 try { 677 mDhcpServer.stop(new OnHandlerStatusCallback() { 678 @Override 679 public void callback(int statusCode) { 680 if (statusCode != STATUS_SUCCESS) { 681 mLog.e("Error stopping DHCP server: " + statusCode); 682 mLastError = TETHER_ERROR_DHCPSERVER_ERROR; 683 // Not much more we can do here 684 } 685 mDhcpLeases.clear(); 686 getHandler().post(mCallback::dhcpLeasesChanged); 687 } 688 }); 689 mDhcpServer = null; 690 } catch (RemoteException e) { 691 mLog.e("Error stopping DHCP server", e); 692 // Not much more we can do here 693 } 694 } 695 } 696 configureDhcp(boolean enable, final LinkAddress serverAddr, final LinkAddress clientAddr)697 private boolean configureDhcp(boolean enable, final LinkAddress serverAddr, 698 final LinkAddress clientAddr) { 699 if (enable) { 700 return startDhcp(serverAddr, clientAddr); 701 } else { 702 stopDhcp(); 703 return true; 704 } 705 } 706 stopIPv4()707 private void stopIPv4() { 708 configureIPv4(false /* enabled */, CONNECTIVITY_SCOPE_GLOBAL /* not used */); 709 // NOTE: All of configureIPv4() will be refactored out of existence 710 // into calls to InterfaceController, shared with startIPv4(). 711 mInterfaceCtrl.clearIPv4Address(); 712 mRoutingCoordinator.releaseDownstream(mIpv4PrefixRequest); 713 mBpfCoordinator.tetherOffloadClientClear(this); 714 mIpv4Address = null; 715 mStaticIpv4ServerAddr = null; 716 mStaticIpv4ClientAddr = null; 717 } 718 configureIPv4(boolean enabled, int scope)719 private boolean configureIPv4(boolean enabled, int scope) { 720 if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")"); 721 722 if (enabled) { 723 mIpv4Address = requestIpv4Address(scope, true /* useLastAddress */); 724 } 725 726 if (mIpv4Address == null) { 727 mLog.e("No available ipv4 address"); 728 return false; 729 } 730 731 if (shouldNotConfigureBluetoothInterface()) { 732 // Interface was already configured elsewhere, only start DHCP. 733 return configureDhcp(enabled, mIpv4Address, null /* clientAddress */); 734 } 735 736 final IpPrefix ipv4Prefix = asIpPrefix(mIpv4Address); 737 738 final Boolean setIfaceUp; 739 if (mInterfaceType == TETHERING_WIFI 740 || mInterfaceType == TETHERING_WIFI_P2P 741 || mInterfaceType == TETHERING_ETHERNET 742 || mInterfaceType == TETHERING_WIGIG) { 743 // The WiFi and Ethernet stack has ownership of the interface up/down state. 744 // It is unclear whether the Bluetooth or USB stacks will manage their own 745 // state. 746 setIfaceUp = null; 747 } else { 748 setIfaceUp = enabled; 749 } 750 if (!mInterfaceCtrl.setInterfaceConfiguration(mIpv4Address, setIfaceUp)) { 751 mLog.e("Error configuring interface"); 752 if (!enabled) stopDhcp(); 753 return false; 754 } 755 756 if (enabled) { 757 mLinkProperties.addLinkAddress(mIpv4Address); 758 mLinkProperties.addRoute(getDirectConnectedRoute(mIpv4Address)); 759 } else { 760 mLinkProperties.removeLinkAddress(mIpv4Address); 761 mLinkProperties.removeRoute(getDirectConnectedRoute(mIpv4Address)); 762 } 763 return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr); 764 } 765 shouldNotConfigureBluetoothInterface()766 private boolean shouldNotConfigureBluetoothInterface() { 767 // Before T, bluetooth tethering configures the interface elsewhere. 768 return (mInterfaceType == TETHERING_BLUETOOTH) && !SdkLevel.isAtLeastT(); 769 } 770 shouldUseWifiP2pDedicatedIp()771 private boolean shouldUseWifiP2pDedicatedIp() { 772 return mIsWifiP2pDedicatedIpEnabled 773 && mInterfaceType == TETHERING_WIFI_P2P; 774 } 775 requestIpv4Address(final int scope, final boolean useLastAddress)776 private LinkAddress requestIpv4Address(final int scope, final boolean useLastAddress) { 777 if (mStaticIpv4ServerAddr != null) return mStaticIpv4ServerAddr; 778 779 if (shouldNotConfigureBluetoothInterface()) return new LinkAddress(BLUETOOTH_IFACE_ADDR); 780 781 if (shouldUseWifiP2pDedicatedIp()) return new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS); 782 783 if (useLastAddress) { 784 return mRoutingCoordinator.requestStickyDownstreamAddress(mInterfaceType, scope, 785 mIpv4PrefixRequest); 786 } 787 788 return mRoutingCoordinator.requestDownstreamAddress(mIpv4PrefixRequest); 789 } 790 startIPv6()791 private boolean startIPv6() { 792 mInterfaceParams = mDeps.getInterfaceParams(mIfaceName); 793 if (mInterfaceParams == null) { 794 mLog.e("Failed to find InterfaceParams"); 795 stopIPv6(); 796 return false; 797 } 798 799 mRaDaemon = mDeps.getRouterAdvertisementDaemon(mInterfaceParams); 800 if (!mRaDaemon.start()) { 801 stopIPv6(); 802 return false; 803 } 804 805 if (SdkLevel.isAtLeastS()) { 806 // DAD Proxy starts forwarding packets after IPv6 upstream is present. 807 mDadProxy = mDeps.getDadProxy(getHandler(), mInterfaceParams); 808 } 809 810 return true; 811 } 812 stopIPv6()813 private void stopIPv6() { 814 mInterfaceParams = null; 815 setRaParams(null); 816 817 if (mRaDaemon != null) { 818 mRaDaemon.stop(); 819 mRaDaemon = null; 820 } 821 822 if (mDadProxy != null) { 823 mDadProxy.stop(); 824 mDadProxy = null; 825 } 826 } 827 828 // IPv6TetheringCoordinator sends updates with carefully curated IPv6-only 829 // LinkProperties. These have extraneous data filtered out and only the 830 // necessary prefixes included (per its prefix distribution policy). 831 // 832 // TODO: Evaluate using a data structure than is more directly suited to 833 // communicating only the relevant information. 834 @SuppressLint("NewApi") updateUpstreamIPv6LinkProperties(LinkProperties v6only, int ttlAdjustment)835 private void updateUpstreamIPv6LinkProperties(LinkProperties v6only, int ttlAdjustment) { 836 if (mRaDaemon == null) return; 837 838 // Avoid unnecessary work on spurious updates. 839 if (Objects.equals(mLastIPv6LinkProperties, v6only)) { 840 return; 841 } 842 843 RaParams params = null; 844 String upstreamIface = null; 845 InterfaceParams upstreamIfaceParams = null; 846 int upstreamIfIndex = NO_UPSTREAM; 847 848 if (v6only != null) { 849 upstreamIface = v6only.getInterfaceName(); 850 upstreamIfaceParams = mDeps.getInterfaceParams(upstreamIface); 851 if (upstreamIfaceParams != null) { 852 upstreamIfIndex = upstreamIfaceParams.index; 853 } 854 params = new RaParams(); 855 params.mtu = v6only.getMtu(); 856 params.hasDefaultRoute = v6only.hasIpv6DefaultRoute(); 857 858 if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface, ttlAdjustment); 859 860 params.prefixes = getTetherableIpv6Prefixes(v6only); 861 for (IpPrefix prefix : params.prefixes) { 862 final Inet6Address dnsServer = getLocalDnsIpFor(prefix); 863 if (dnsServer != null) { 864 params.dnses.add(dnsServer); 865 } 866 } 867 } 868 869 // Add upstream index to name mapping. See the comment of the interface mapping update in 870 // CMD_TETHER_CONNECTION_CHANGED. Adding the mapping update here to the avoid potential 871 // timing issue. It prevents that the IPv6 capability is updated later than 872 // CMD_TETHER_CONNECTION_CHANGED. 873 mBpfCoordinator.maybeAddUpstreamToLookupTable(upstreamIfIndex, upstreamIface); 874 875 // If v6only is null, we pass in null to setRaParams(), which handles 876 // deprecation of any existing RA data. 877 setRaParams(params); 878 879 // Not support BPF on virtual upstream interface 880 final Set<IpPrefix> upstreamPrefixes = params != null ? params.prefixes : Set.of(); 881 // mBpfCoordinator#updateIpv6UpstreamInterface must be called before updating 882 // mLastIPv6UpstreamIfindex and mLastIPv6UpstreamPrefixes because BpfCoordinator will call 883 // IpServer#getIpv6UpstreamIfindex and IpServer#getIpv6UpstreamPrefixes to retrieve current 884 // upstream interface index and prefixes when handling upstream changes. 885 mBpfCoordinator.updateIpv6UpstreamInterface(this, upstreamIfIndex, upstreamPrefixes); 886 mLastIPv6LinkProperties = v6only; 887 mLastIPv6UpstreamIfindex = upstreamIfIndex; 888 mLastIPv6UpstreamPrefixes = upstreamPrefixes; 889 if (mDadProxy != null) { 890 mDadProxy.setUpstreamIface(upstreamIfaceParams); 891 } 892 } 893 removeRoutesFromNetwork(int netId, @NonNull final List<RouteInfo> toBeRemoved)894 private void removeRoutesFromNetwork(int netId, @NonNull final List<RouteInfo> toBeRemoved) { 895 final int removalFailures = NetdUtils.removeRoutesFromNetwork(mNetd, netId, toBeRemoved); 896 if (removalFailures > 0) { 897 mLog.e("Failed to remove " + removalFailures 898 + " IPv6 routes from network " + netId + "."); 899 } 900 } 901 addInterfaceToNetwork(final int netId, @NonNull final String ifaceName)902 private void addInterfaceToNetwork(final int netId, @NonNull final String ifaceName) { 903 try { 904 // TODO : remove this call in favor of using the LocalNetworkConfiguration 905 // correctly, which will let ConnectivityService do it automatically. 906 mRoutingCoordinator.addInterfaceToNetwork(netId, ifaceName); 907 } catch (ServiceSpecificException e) { 908 mLog.e("Failed to add " + mIfaceName + " to local table: ", e); 909 } 910 } 911 addInterfaceForward(@onNull final String fromIface, @NonNull final String toIface)912 private void addInterfaceForward(@NonNull final String fromIface, @NonNull final String toIface) 913 throws ServiceSpecificException { 914 mRoutingCoordinator.addInterfaceForward(fromIface, toIface); 915 } 916 removeInterfaceForward(@onNull final String fromIface, @NonNull final String toIface)917 private void removeInterfaceForward(@NonNull final String fromIface, 918 @NonNull final String toIface) { 919 try { 920 mRoutingCoordinator.removeInterfaceForward(fromIface, toIface); 921 } catch (RuntimeException e) { 922 mLog.e("Exception in removeInterfaceForward", e); 923 } 924 } 925 addRoutesToNetwork(int netId, @NonNull final List<RouteInfo> toBeAdded)926 private void addRoutesToNetwork(int netId, 927 @NonNull final List<RouteInfo> toBeAdded) { 928 // It's safe to call addInterfaceToNetwork() even if 929 // the interface is already in the network. 930 addInterfaceToNetwork(netId, mIfaceName); 931 try { 932 // Add routes from local network. Note that adding routes that 933 // already exist does not cause an error (EEXIST is silently ignored). 934 NetdUtils.addRoutesToNetwork(mNetd, netId, mIfaceName, toBeAdded); 935 } catch (IllegalStateException e) { 936 mLog.e("Failed to add IPv4/v6 routes to local table: " + e); 937 return; 938 } 939 } 940 configureLocalIPv6Routes( ArraySet<IpPrefix> deprecatedPrefixes, ArraySet<IpPrefix> newPrefixes)941 private void configureLocalIPv6Routes( 942 ArraySet<IpPrefix> deprecatedPrefixes, ArraySet<IpPrefix> newPrefixes) { 943 // [1] Remove the routes that are deprecated. 944 if (!deprecatedPrefixes.isEmpty()) { 945 final List<RouteInfo> routesToBeRemoved = 946 getLocalRoutesFor(mIfaceName, deprecatedPrefixes); 947 if (mTetheringAgent == null) { 948 removeRoutesFromNetwork(LOCAL_NET_ID, routesToBeRemoved); 949 } 950 for (RouteInfo route : routesToBeRemoved) mLinkProperties.removeRoute(route); 951 } 952 953 // [2] Add only the routes that have not previously been added. 954 if (newPrefixes != null && !newPrefixes.isEmpty()) { 955 ArraySet<IpPrefix> addedPrefixes = new ArraySet<IpPrefix>(newPrefixes); 956 if (mLastRaParams != null) { 957 addedPrefixes.removeAll(mLastRaParams.prefixes); 958 } 959 960 if (!addedPrefixes.isEmpty()) { 961 final List<RouteInfo> routesToBeAdded = 962 getLocalRoutesFor(mIfaceName, addedPrefixes); 963 if (mTetheringAgent == null) { 964 addRoutesToNetwork(LOCAL_NET_ID, routesToBeAdded); 965 } 966 for (RouteInfo route : routesToBeAdded) mLinkProperties.addRoute(route); 967 } 968 } 969 } 970 configureLocalIPv6Dns( ArraySet<Inet6Address> deprecatedDnses, ArraySet<Inet6Address> newDnses)971 private void configureLocalIPv6Dns( 972 ArraySet<Inet6Address> deprecatedDnses, ArraySet<Inet6Address> newDnses) { 973 // TODO: Is this really necessary? Can we not fail earlier if INetd cannot be located? 974 if (mNetd == null) { 975 if (newDnses != null) newDnses.clear(); 976 mLog.e("No netd service instance available; not setting local IPv6 addresses"); 977 return; 978 } 979 980 // [1] Remove deprecated local DNS IP addresses. 981 if (!deprecatedDnses.isEmpty()) { 982 for (Inet6Address dns : deprecatedDnses) { 983 if (!mInterfaceCtrl.removeAddress(dns, RFC7421_PREFIX_LENGTH)) { 984 mLog.e("Failed to remove local dns IP " + dns); 985 } 986 987 mLinkProperties.removeLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH)); 988 } 989 } 990 991 // [2] Add only the local DNS IP addresses that have not previously been added. 992 if (newDnses != null && !newDnses.isEmpty()) { 993 final ArraySet<Inet6Address> addedDnses = new ArraySet<Inet6Address>(newDnses); 994 if (mLastRaParams != null) { 995 addedDnses.removeAll(mLastRaParams.dnses); 996 } 997 998 for (Inet6Address dns : addedDnses) { 999 if (!mInterfaceCtrl.addAddress(dns, RFC7421_PREFIX_LENGTH)) { 1000 mLog.e("Failed to add local dns IP " + dns); 1001 newDnses.remove(dns); 1002 } 1003 1004 mLinkProperties.addLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH)); 1005 } 1006 } 1007 1008 try { 1009 mNetd.tetherApplyDnsInterfaces(); 1010 } catch (ServiceSpecificException | RemoteException e) { 1011 mLog.e("Failed to update local DNS caching server"); 1012 if (newDnses != null) newDnses.clear(); 1013 } 1014 } 1015 getHopLimit(String upstreamIface, int adjustTTL)1016 private byte getHopLimit(String upstreamIface, int adjustTTL) { 1017 try { 1018 int upstreamHopLimit = Integer.parseUnsignedInt( 1019 mNetd.getProcSysNet(INetd.IPV6, INetd.CONF, upstreamIface, "hop_limit")); 1020 upstreamHopLimit = upstreamHopLimit + adjustTTL; 1021 // Cap the hop limit to 255. 1022 return (byte) Integer.min(upstreamHopLimit, 255); 1023 } catch (Exception e) { 1024 mLog.e("Failed to find upstream interface hop limit", e); 1025 } 1026 return RaParams.DEFAULT_HOPLIMIT; 1027 } 1028 setRaParams(RaParams newParams)1029 private void setRaParams(RaParams newParams) { 1030 if (mRaDaemon != null) { 1031 final RaParams deprecatedParams = 1032 RaParams.getDeprecatedRaParams(mLastRaParams, newParams); 1033 1034 configureLocalIPv6Routes(deprecatedParams.prefixes, 1035 (newParams != null) ? newParams.prefixes : null); 1036 1037 configureLocalIPv6Dns(deprecatedParams.dnses, 1038 (newParams != null) ? newParams.dnses : null); 1039 1040 mRaDaemon.buildNewRa(deprecatedParams, newParams); 1041 } 1042 1043 mLastRaParams = newParams; 1044 } 1045 maybeLogMessage(State state, int what)1046 private void maybeLogMessage(State state, int what) { 1047 switch (what) { 1048 // Suppress some CMD_* to avoid log flooding. 1049 case CMD_IPV6_TETHER_UPDATE: 1050 break; 1051 default: 1052 mLog.log(state.getName() + " got " 1053 + sMagicDecoderRing.get(what, Integer.toString(what))); 1054 } 1055 } 1056 sendInterfaceState(int newInterfaceState)1057 private void sendInterfaceState(int newInterfaceState) { 1058 mServingMode = newInterfaceState; 1059 mCallback.updateInterfaceState(this, newInterfaceState, mLastError); 1060 sendLinkProperties(); 1061 } 1062 sendLinkProperties()1063 private void sendLinkProperties() { 1064 mCallback.updateLinkProperties(this, new LinkProperties(mLinkProperties)); 1065 } 1066 resetLinkProperties()1067 private void resetLinkProperties() { 1068 mLinkProperties.clear(); 1069 mLinkProperties.setInterfaceName(mIfaceName); 1070 } 1071 maybeConfigureStaticIp(@onNull final TetheringRequest request)1072 private void maybeConfigureStaticIp(@NonNull final TetheringRequest request) { 1073 // Ignore static address configuration if they are invalid or null. In theory, static 1074 // addresses should not be invalid here because TetheringManager do not allow caller to 1075 // specify invalid static address configuration. 1076 if (request.getLocalIpv4Address() == null 1077 || request.getClientStaticIpv4Address() == null || !checkStaticAddressConfiguration( 1078 request.getLocalIpv4Address(), request.getClientStaticIpv4Address())) { 1079 return; 1080 } 1081 1082 mStaticIpv4ServerAddr = request.getLocalIpv4Address(); 1083 mStaticIpv4ClientAddr = request.getClientStaticIpv4Address(); 1084 } 1085 1086 class InitialState extends State { 1087 @Override enter()1088 public void enter() { 1089 sendInterfaceState(STATE_AVAILABLE); 1090 } 1091 1092 @Override processMessage(Message message)1093 public boolean processMessage(Message message) { 1094 maybeLogMessage(this, message.what); 1095 switch (message.what) { 1096 case CMD_TETHER_REQUESTED: 1097 mLastError = TETHER_ERROR_NO_ERROR; 1098 mTetheringRequest = (TetheringRequest) message.obj; 1099 switch (mTetheringRequest.getConnectivityScope()) { 1100 case CONNECTIVITY_SCOPE_LOCAL: 1101 maybeConfigureStaticIp(mTetheringRequest); 1102 transitionTo(mLocalHotspotState); 1103 break; 1104 case CONNECTIVITY_SCOPE_GLOBAL: 1105 maybeConfigureStaticIp(mTetheringRequest); 1106 transitionTo(mTetheredState); 1107 break; 1108 default: 1109 mLog.e("Invalid tethering interface serving state specified."); 1110 } 1111 break; 1112 case CMD_INTERFACE_DOWN: 1113 transitionTo(mUnavailableState); 1114 break; 1115 default: 1116 return NOT_HANDLED; 1117 } 1118 return HANDLED; 1119 } 1120 } 1121 1122 abstract class BaseServingState extends State { 1123 private final int mDesiredInterfaceState; 1124 BaseServingState(int interfaceState)1125 BaseServingState(int interfaceState) { 1126 mDesiredInterfaceState = interfaceState; 1127 } 1128 1129 @Override enter()1130 public void enter() { 1131 mBpfCoordinator.addIpServer(IpServer.this); 1132 1133 startServingInterface(); 1134 1135 if (mLastError != TETHER_ERROR_NO_ERROR) { 1136 // This will transition to InitialState right away, regardless of whether any 1137 // message is already waiting in the StateMachine queue (including maybe some 1138 // message to go to InitialState). InitialState will then process any pending 1139 // message (and generally ignores them). It is difficult to know for sure whether 1140 // this is correct in all cases, but this is equivalent to what IpServer was doing 1141 // in previous versions of the mainline module. 1142 // TODO : remove sendMessageAtFrontOfQueueToAsyncSM after migrating to the Sync 1143 // StateMachine. 1144 if (USE_SYNC_SM) { 1145 sendSelfMessageToSyncSM(CMD_SERVICE_FAILED_TO_START, mLastError); 1146 } else { 1147 sendMessageAtFrontOfQueueToAsyncSM(CMD_SERVICE_FAILED_TO_START, mLastError); 1148 } 1149 } 1150 1151 if (DBG) Log.d(TAG, getStateString(mDesiredInterfaceState) + " serve " + mIfaceName); 1152 sendInterfaceState(mDesiredInterfaceState); 1153 } 1154 getScope()1155 private int getScope() { 1156 if (mDesiredInterfaceState == STATE_TETHERED) { 1157 return CONNECTIVITY_SCOPE_GLOBAL; 1158 } 1159 1160 return CONNECTIVITY_SCOPE_LOCAL; 1161 } 1162 1163 @SuppressLint("NewApi") startServingInterface()1164 private void startServingInterface() { 1165 // TODO: Enable Network Agent for Wifi P2P Group Owner mode when Network Agent 1166 // for Group Client mode is supported. 1167 if (mSupportLocalAgent && getScope() == CONNECTIVITY_SCOPE_GLOBAL) { 1168 try { 1169 mTetheringAgent = mDeps.makeNetworkAgent(mContext, Looper.myLooper(), TAG, 1170 mInterfaceType, mLinkProperties); 1171 // Entering CONNECTING state, the ConnectivityService will create the 1172 // native network. 1173 mTetheringAgent.register(); 1174 } catch (RuntimeException e) { 1175 mLog.e("Error Creating Local Network", e); 1176 // If an exception occurs during the creation or registration of the 1177 // NetworkAgent, it typically indicates a problem with the system services. 1178 mLastError = TETHER_ERROR_SERVICE_UNAVAIL; 1179 return; 1180 } 1181 } 1182 1183 if (!startIPv4(getScope())) { 1184 mLastError = TETHER_ERROR_IFACE_CFG_ERROR; 1185 return; 1186 } 1187 1188 try { 1189 // Enable IPv6, disable accepting RA, etc. See TetherController::tetherInterface() 1190 // for more detail. 1191 mNetd.tetherInterfaceAdd(mIfaceName); 1192 if (mTetheringAgent == null) { 1193 NetdUtils.networkAddInterface(mNetd, LOCAL_NET_ID, mIfaceName, 1194 20 /* maxAttempts */, 50 /* pollingIntervalMs */); 1195 // Activate a route to dest and IPv6 link local. 1196 NetdUtils.modifyRoute(mNetd, NetdUtils.ModifyOperation.ADD, LOCAL_NET_ID, 1197 new RouteInfo(asIpPrefix(mIpv4Address), null, mIfaceName, RTN_UNICAST)); 1198 NetdUtils.modifyRoute(mNetd, NetdUtils.ModifyOperation.ADD, LOCAL_NET_ID, 1199 new RouteInfo(new IpPrefix("fe80::/64"), null, mIfaceName, 1200 RTN_UNICAST)); 1201 } 1202 } catch (RemoteException | ServiceSpecificException | IllegalStateException e) { 1203 mLog.e("Error Tethering", e); 1204 mLastError = TETHER_ERROR_TETHER_IFACE_ERROR; 1205 return; 1206 } 1207 1208 if (!startIPv6()) { 1209 mLog.e("Failed to startIPv6"); 1210 // TODO: Make this a fatal error once Bluetooth IPv6 is sorted. 1211 return; 1212 } 1213 1214 if (mTetheringAgent != null && everRegistered(mTetheringAgent)) { 1215 mTetheringAgent.sendLinkProperties(mLinkProperties); 1216 // Mark it connected to notify the applications for 1217 // the network availability. 1218 mTetheringAgent.markConnected(); 1219 } 1220 } 1221 1222 @Override 1223 @SuppressLint("NewApi") exit()1224 public void exit() { 1225 // Note that at this point, we're leaving the tethered state. We can fail any 1226 // of these operations, but it doesn't really change that we have to try them 1227 // all in sequence. 1228 stopIPv6(); 1229 1230 // Reset interface for tethering. 1231 try { 1232 try { 1233 mNetd.tetherInterfaceRemove(mIfaceName); 1234 } finally { 1235 if (mTetheringAgent == null) { 1236 mNetd.networkRemoveInterface(LOCAL_NET_ID, mIfaceName); 1237 } 1238 } 1239 } catch (RemoteException | ServiceSpecificException e) { 1240 mLastError = TETHER_ERROR_UNTETHER_IFACE_ERROR; 1241 mLog.e("Failed to untether interface: " + e); 1242 } 1243 1244 stopIPv4(); 1245 mBpfCoordinator.removeIpServer(IpServer.this); 1246 1247 if (mTetheringAgent != null && everRegistered(mTetheringAgent)) { 1248 mTetheringAgent.unregister(); 1249 mTetheringAgent = null; 1250 } 1251 1252 resetLinkProperties(); 1253 1254 mTetheringMetrics.updateErrorCode(mInterfaceType, mLastError); 1255 mTetheringMetrics.sendReport(mInterfaceType); 1256 } 1257 1258 @Override processMessage(Message message)1259 public boolean processMessage(Message message) { 1260 switch (message.what) { 1261 case CMD_TETHER_UNREQUESTED: 1262 transitionTo(mInitialState); 1263 if (DBG) Log.d(TAG, "Untethered (unrequested)" + mIfaceName); 1264 break; 1265 case CMD_INTERFACE_DOWN: 1266 transitionTo(mUnavailableState); 1267 if (DBG) Log.d(TAG, "Untethered (ifdown)" + mIfaceName); 1268 break; 1269 case CMD_IPV6_TETHER_UPDATE: 1270 updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1); 1271 // Sends update to the NetworkAgent. 1272 // TODO: Refactor the callers of sendLinkProperties() 1273 // and move these code into sendLinkProperties(). 1274 if (mTetheringAgent != null && everRegistered(mTetheringAgent)) { 1275 mTetheringAgent.sendLinkProperties(mLinkProperties); 1276 } 1277 sendLinkProperties(); 1278 break; 1279 case CMD_IP_FORWARDING_ENABLE_ERROR: 1280 case CMD_IP_FORWARDING_DISABLE_ERROR: 1281 case CMD_START_TETHERING_ERROR: 1282 case CMD_STOP_TETHERING_ERROR: 1283 case CMD_SET_DNS_FORWARDERS_ERROR: 1284 mLastError = TETHER_ERROR_INTERNAL_ERROR; 1285 transitionTo(mInitialState); 1286 break; 1287 case CMD_NEW_PREFIX_REQUEST: 1288 handleNewPrefixRequest((IpPrefix) message.obj); 1289 break; 1290 case CMD_NOTIFY_PREFIX_CONFLICT: 1291 mLog.i("restart tethering: " + mInterfaceType); 1292 mCallback.requestEnableTethering(mInterfaceType, false /* enabled */); 1293 transitionTo(mWaitingForRestartState); 1294 break; 1295 case CMD_SERVICE_FAILED_TO_START: 1296 mLog.e("start serving fail, error: " + message.arg1); 1297 transitionTo(mInitialState); 1298 break; 1299 default: 1300 return false; 1301 } 1302 return true; 1303 } 1304 handleNewPrefixRequest(@onNull final IpPrefix currentPrefix)1305 private void handleNewPrefixRequest(@NonNull final IpPrefix currentPrefix) { 1306 if (!currentPrefix.contains(mIpv4Address.getAddress()) 1307 || currentPrefix.getPrefixLength() != mIpv4Address.getPrefixLength()) { 1308 Log.e(TAG, "Invalid prefix: " + currentPrefix); 1309 return; 1310 } 1311 1312 final LinkAddress deprecatedLinkAddress = mIpv4Address; 1313 mIpv4Address = requestIpv4Address(getScope(), false); 1314 if (mIpv4Address == null) { 1315 mLog.e("Fail to request a new downstream prefix"); 1316 return; 1317 } 1318 final Inet4Address srvAddr = (Inet4Address) mIpv4Address.getAddress(); 1319 1320 // Add new IPv4 address on the interface. 1321 if (!mInterfaceCtrl.addAddress(srvAddr, currentPrefix.getPrefixLength())) { 1322 mLog.e("Failed to add new IP " + srvAddr); 1323 return; 1324 } 1325 1326 // Remove deprecated routes from downstream network. 1327 final List<RouteInfo> routesToBeRemoved = 1328 List.of(getDirectConnectedRoute(deprecatedLinkAddress)); 1329 if (mTetheringAgent == null) { 1330 removeRoutesFromNetwork(LOCAL_NET_ID, routesToBeRemoved); 1331 } 1332 for (RouteInfo route : routesToBeRemoved) mLinkProperties.removeRoute(route); 1333 mLinkProperties.removeLinkAddress(deprecatedLinkAddress); 1334 1335 // Add new routes to downstream network. 1336 final List<RouteInfo> routesToBeAdded = List.of(getDirectConnectedRoute(mIpv4Address)); 1337 if (mTetheringAgent == null) { 1338 addRoutesToNetwork(LOCAL_NET_ID, routesToBeAdded); 1339 } 1340 for (RouteInfo route : routesToBeAdded) mLinkProperties.addRoute(route); 1341 mLinkProperties.addLinkAddress(mIpv4Address); 1342 1343 // Update local DNS caching server with new IPv4 address, otherwise, dnsmasq doesn't 1344 // listen on the interface configured with new IPv4 address, that results DNS validation 1345 // failure of downstream client even if appropriate routes have been configured. 1346 try { 1347 mNetd.tetherApplyDnsInterfaces(); 1348 } catch (ServiceSpecificException | RemoteException e) { 1349 mLog.e("Failed to update local DNS caching server"); 1350 return; 1351 } 1352 // Sends update to the NetworkAgent. 1353 if (mTetheringAgent != null && everRegistered(mTetheringAgent)) { 1354 mTetheringAgent.sendLinkProperties(mLinkProperties); 1355 } 1356 sendLinkProperties(); 1357 1358 // Notify DHCP server that new prefix/route has been applied on IpServer. 1359 final Inet4Address clientAddr = mStaticIpv4ClientAddr == null ? null : 1360 (Inet4Address) mStaticIpv4ClientAddr.getAddress(); 1361 final DhcpServingParamsParcel params = makeServingParams(srvAddr /* defaultRouter */, 1362 srvAddr /* dnsServer */, mIpv4Address /* serverLinkAddress */, clientAddr); 1363 try { 1364 mDhcpServer.updateParams(params, new OnHandlerStatusCallback() { 1365 @Override 1366 public void callback(int statusCode) { 1367 if (statusCode != STATUS_SUCCESS) { 1368 mLog.e("Error updating DHCP serving params: " + statusCode); 1369 } 1370 } 1371 }); 1372 } catch (RemoteException e) { 1373 mLog.e("Error updating DHCP serving params", e); 1374 } 1375 } 1376 } 1377 1378 // Handling errors in BaseServingState.enter() by transitioning is 1379 // problematic because transitioning during a multi-state jump yields 1380 // a Log.wtf(). Ultimately, there should be only one ServingState, 1381 // and forwarding and NAT rules should be handled by a coordinating 1382 // functional element outside of IpServer. 1383 class LocalHotspotState extends BaseServingState { LocalHotspotState()1384 LocalHotspotState() { 1385 super(STATE_LOCAL_ONLY); 1386 } 1387 1388 @Override processMessage(Message message)1389 public boolean processMessage(Message message) { 1390 if (super.processMessage(message)) return true; 1391 1392 maybeLogMessage(this, message.what); 1393 switch (message.what) { 1394 case CMD_TETHER_REQUESTED: 1395 mLog.e("CMD_TETHER_REQUESTED while in local-only hotspot mode."); 1396 break; 1397 case CMD_TETHER_CONNECTION_CHANGED: 1398 // Ignored in local hotspot state. 1399 break; 1400 default: 1401 return false; 1402 } 1403 return true; 1404 } 1405 } 1406 1407 // Handling errors in BaseServingState.enter() by transitioning is 1408 // problematic because transitioning during a multi-state jump yields 1409 // a Log.wtf(). Ultimately, there should be only one ServingState, 1410 // and forwarding and NAT rules should be handled by a coordinating 1411 // functional element outside of IpServer. 1412 class TetheredState extends BaseServingState { TetheredState()1413 TetheredState() { 1414 super(STATE_TETHERED); 1415 } 1416 1417 @Override exit()1418 public void exit() { 1419 cleanupUpstream(); 1420 mBpfCoordinator.clearAllIpv6Rules(IpServer.this); 1421 super.exit(); 1422 } 1423 1424 // Note that IPv4 offload rules cleanup is implemented in BpfCoordinator while upstream 1425 // state is null or changed because IPv4 and IPv6 tethering have different code flow 1426 // and behaviour. While upstream is switching from offload supported interface to 1427 // offload non-supportted interface, event CMD_TETHER_CONNECTION_CHANGED calls 1428 // #cleanupUpstreamInterface but #cleanupUpstream because new UpstreamIfaceSet is not null. 1429 // This case won't happen in IPv6 tethering because IPv6 tethering upstream state is 1430 // reported by IPv6TetheringCoordinator. #cleanupUpstream is also called by unwirding 1431 // adding NAT failure. In that case, the IPv4 offload rules are removed by #stopIPv4 1432 // in the state machine. Once there is any case out whish is not covered by previous cases, 1433 // probably consider clearing rules in #cleanupUpstream as well. cleanupUpstream()1434 private void cleanupUpstream() { 1435 if (mUpstreamIfaceSet == null) return; 1436 1437 for (String ifname : mUpstreamIfaceSet.ifnames) cleanupUpstreamInterface(ifname); 1438 mUpstreamIfaceSet = null; 1439 mBpfCoordinator.updateIpv6UpstreamInterface(IpServer.this, NO_UPSTREAM, 1440 Collections.emptySet()); 1441 } 1442 cleanupUpstreamInterface(String upstreamIface)1443 private void cleanupUpstreamInterface(String upstreamIface) { 1444 // Note that we don't care about errors here. 1445 // Sometimes interfaces are gone before we get 1446 // to remove their rules, which generates errors. 1447 // Just do the best we can. 1448 mBpfCoordinator.maybeDetachProgram(mIfaceName, upstreamIface); 1449 removeInterfaceForward(mIfaceName, upstreamIface); 1450 } 1451 1452 @Override processMessage(Message message)1453 public boolean processMessage(Message message) { 1454 if (super.processMessage(message)) return true; 1455 1456 maybeLogMessage(this, message.what); 1457 switch (message.what) { 1458 case CMD_TETHER_REQUESTED: 1459 mLog.e("CMD_TETHER_REQUESTED while already tethering."); 1460 break; 1461 case CMD_TETHER_CONNECTION_CHANGED: 1462 final InterfaceSet newUpstreamIfaceSet = (InterfaceSet) message.obj; 1463 if (noChangeInUpstreamIfaceSet(newUpstreamIfaceSet)) { 1464 if (VDBG) Log.d(TAG, "Connection changed noop - dropping"); 1465 break; 1466 } 1467 1468 if (newUpstreamIfaceSet == null) { 1469 cleanupUpstream(); 1470 break; 1471 } 1472 1473 for (String removed : upstreamInterfacesRemoved(newUpstreamIfaceSet)) { 1474 cleanupUpstreamInterface(removed); 1475 } 1476 1477 final Set<String> added = upstreamInterfacesAdd(newUpstreamIfaceSet); 1478 // This makes the call to cleanupUpstream() in the error 1479 // path for any interface neatly cleanup all the interfaces. 1480 mUpstreamIfaceSet = newUpstreamIfaceSet; 1481 1482 for (String ifname : added) { 1483 // Add upstream index to name mapping for the tether stats usage in the 1484 // coordinator. Although this mapping could be added by both class 1485 // Tethering and IpServer, adding mapping from IpServer guarantees that 1486 // the mapping is added before adding forwarding rules. That is because 1487 // there are different state machines in both classes. It is hard to 1488 // guarantee the link property update order between multiple state machines. 1489 // Note that both IPv4 and IPv6 interface may be added because 1490 // Tethering::setUpstreamNetwork calls getTetheringInterfaces which merges 1491 // IPv4 and IPv6 interface name (if any) into an InterfaceSet. The IPv6 1492 // capability may be updated later. In that case, IPv6 interface mapping is 1493 // updated in updateUpstreamIPv6LinkProperties. 1494 if (!ifname.startsWith("v4-")) { // ignore clat interfaces 1495 final InterfaceParams upstreamIfaceParams = 1496 mDeps.getInterfaceParams(ifname); 1497 if (upstreamIfaceParams != null) { 1498 mBpfCoordinator.maybeAddUpstreamToLookupTable( 1499 upstreamIfaceParams.index, ifname); 1500 } 1501 } 1502 1503 mBpfCoordinator.maybeAttachProgram(mIfaceName, ifname); 1504 try { 1505 addInterfaceForward(mIfaceName, ifname); 1506 } catch (RuntimeException e) { 1507 mLog.e("Exception enabling iface forward", e); 1508 cleanupUpstream(); 1509 mLastError = TETHER_ERROR_ENABLE_FORWARDING_ERROR; 1510 transitionTo(mInitialState); 1511 return true; 1512 } 1513 } 1514 break; 1515 default: 1516 return false; 1517 } 1518 return true; 1519 } 1520 noChangeInUpstreamIfaceSet(InterfaceSet newIfaces)1521 private boolean noChangeInUpstreamIfaceSet(InterfaceSet newIfaces) { 1522 if (mUpstreamIfaceSet == null && newIfaces == null) return true; 1523 if (mUpstreamIfaceSet != null && newIfaces != null) { 1524 return mUpstreamIfaceSet.equals(newIfaces); 1525 } 1526 return false; 1527 } 1528 upstreamInterfacesRemoved(InterfaceSet newIfaces)1529 private Set<String> upstreamInterfacesRemoved(InterfaceSet newIfaces) { 1530 if (mUpstreamIfaceSet == null) return new HashSet<>(); 1531 1532 final HashSet<String> removed = new HashSet<>(mUpstreamIfaceSet.ifnames); 1533 removed.removeAll(newIfaces.ifnames); 1534 return removed; 1535 } 1536 upstreamInterfacesAdd(InterfaceSet newIfaces)1537 private Set<String> upstreamInterfacesAdd(InterfaceSet newIfaces) { 1538 final HashSet<String> added = new HashSet<>(newIfaces.ifnames); 1539 if (mUpstreamIfaceSet != null) added.removeAll(mUpstreamIfaceSet.ifnames); 1540 return added; 1541 } 1542 } 1543 1544 /** 1545 * This state is terminal for the per interface state machine. At this 1546 * point, the tethering main state machine should have removed this interface 1547 * specific state machine from its list of possible recipients of 1548 * tethering requests. The state machine itself will hang around until 1549 * the garbage collector finds it. 1550 */ 1551 class UnavailableState extends State { 1552 @Override enter()1553 public void enter() { 1554 mLastError = TETHER_ERROR_NO_ERROR; 1555 // TODO: clean this up after the synchronous state machine is fully rolled out. Clean up 1556 // can be directly triggered after calling IpServer.stop() inside Tethering.java. 1557 sendInterfaceState(STATE_UNAVAILABLE); 1558 } 1559 1560 @Override processMessage(Message message)1561 public boolean processMessage(Message message) { 1562 switch (message.what) { 1563 case CMD_IPV6_TETHER_UPDATE: 1564 // sendInterfaceState(STATE_UNAVAILABLE) triggers 1565 // handleInterfaceServingStateInactive which in turn cleans up IPv6 tethering 1566 // (and calls into IpServer one more time). At this point, this is the only 1567 // message we potentially see in this state because this IpServer has already 1568 // been removed from mTetherStates before transitioning to this State; however, 1569 // handleInterfaceServiceStateInactive passes a reference. 1570 // TODO: This can be removed once SyncStateMachine is rolled out and the 1571 // teardown path is cleaned up. 1572 return true; 1573 default: 1574 return false; 1575 } 1576 } 1577 } 1578 1579 class WaitingForRestartState extends State { 1580 @Override processMessage(Message message)1581 public boolean processMessage(Message message) { 1582 maybeLogMessage(this, message.what); 1583 switch (message.what) { 1584 case CMD_TETHER_UNREQUESTED: 1585 transitionTo(mInitialState); 1586 mLog.i("Untethered (unrequested) and restarting " + mIfaceName); 1587 mCallback.requestEnableTethering(mInterfaceType, true /* enabled */); 1588 break; 1589 case CMD_INTERFACE_DOWN: 1590 transitionTo(mUnavailableState); 1591 mLog.i("Untethered (interface down) and restarting " + mIfaceName); 1592 mCallback.requestEnableTethering(mInterfaceType, true /* enabled */); 1593 break; 1594 default: 1595 return false; 1596 } 1597 return true; 1598 } 1599 } 1600 1601 // Accumulate routes representing "prefixes to be assigned to the local 1602 // interface", for subsequent modification of local_network routing. getLocalRoutesFor( String ifname, ArraySet<IpPrefix> prefixes)1603 private static ArrayList<RouteInfo> getLocalRoutesFor( 1604 String ifname, ArraySet<IpPrefix> prefixes) { 1605 final ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>(); 1606 for (IpPrefix ipp : prefixes) { 1607 localRoutes.add(new RouteInfo(ipp, null, ifname, RTN_UNICAST)); 1608 } 1609 return localRoutes; 1610 } 1611 1612 // Given a prefix like 2001:db8::/64 return an address like 2001:db8::1. getLocalDnsIpFor(IpPrefix localPrefix)1613 private static Inet6Address getLocalDnsIpFor(IpPrefix localPrefix) { 1614 final byte[] dnsBytes = localPrefix.getRawAddress(); 1615 dnsBytes[dnsBytes.length - 1] = getRandomSanitizedByte(DOUG_ADAMS, asByte(0), asByte(1)); 1616 try { 1617 return Inet6Address.getByAddress(null, dnsBytes, 0); 1618 } catch (UnknownHostException e) { 1619 Log.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix); 1620 return null; 1621 } 1622 } 1623 getRandomSanitizedByte(byte dflt, byte... excluded)1624 private static byte getRandomSanitizedByte(byte dflt, byte... excluded) { 1625 final byte random = (byte) (new Random()).nextInt(); 1626 for (int value : excluded) { 1627 if (random == value) return dflt; 1628 } 1629 return random; 1630 } 1631 1632 /** Get IPv6 prefixes from LinkProperties */ 1633 @NonNull 1634 @VisibleForTesting getTetherableIpv6Prefixes(@onNull Collection<LinkAddress> addrs)1635 static ArraySet<IpPrefix> getTetherableIpv6Prefixes(@NonNull Collection<LinkAddress> addrs) { 1636 final ArraySet<IpPrefix> prefixes = new ArraySet<>(); 1637 for (LinkAddress linkAddr : addrs) { 1638 if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue; 1639 prefixes.add(new IpPrefix(linkAddr.getAddress(), RFC7421_PREFIX_LENGTH)); 1640 } 1641 return prefixes; 1642 } 1643 1644 @NonNull getTetherableIpv6Prefixes(@onNull LinkProperties lp)1645 private ArraySet<IpPrefix> getTetherableIpv6Prefixes(@NonNull LinkProperties lp) { 1646 return getTetherableIpv6Prefixes(lp.getLinkAddresses()); 1647 } 1648 } 1649