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