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