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