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