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