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