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 com.android.server.connectivity.tethering; 18 19 import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH; 20 21 import android.net.ConnectivityManager; 22 import android.net.INetd; 23 import android.net.INetworkStatsService; 24 import android.net.InterfaceConfiguration; 25 import android.net.IpPrefix; 26 import android.net.LinkAddress; 27 import android.net.LinkProperties; 28 import android.net.NetworkUtils; 29 import android.net.RouteInfo; 30 import android.net.ip.RouterAdvertisementDaemon; 31 import android.net.ip.RouterAdvertisementDaemon.RaParams; 32 import android.net.util.NetdService; 33 import android.net.util.SharedLog; 34 import android.os.INetworkManagementService; 35 import android.os.Looper; 36 import android.os.Message; 37 import android.os.RemoteException; 38 import android.os.ServiceSpecificException; 39 import android.util.Log; 40 import android.util.Slog; 41 import android.util.SparseArray; 42 43 import com.android.internal.util.MessageUtils; 44 import com.android.internal.util.Protocol; 45 import com.android.internal.util.State; 46 import com.android.internal.util.StateMachine; 47 48 import java.net.Inet6Address; 49 import java.net.InetAddress; 50 import java.net.NetworkInterface; 51 import java.net.SocketException; 52 import java.net.UnknownHostException; 53 import java.util.ArrayList; 54 import java.util.HashSet; 55 import java.util.Objects; 56 import java.util.Random; 57 58 /** 59 * Provides the interface to IP-layer serving functionality for a given network 60 * interface, e.g. for tethering or "local-only hotspot" mode. 61 * 62 * @hide 63 */ 64 public class TetherInterfaceStateMachine extends StateMachine { 65 private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64"); 66 67 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129"; 68 private static final int USB_PREFIX_LENGTH = 24; 69 private static final String WIFI_HOST_IFACE_ADDR = "192.168.43.1"; 70 private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24; 71 72 private final static String TAG = "TetherInterfaceSM"; 73 private final static boolean DBG = false; 74 private final static boolean VDBG = false; 75 private static final Class[] messageClasses = { 76 TetherInterfaceStateMachine.class 77 }; 78 private static final SparseArray<String> sMagicDecoderRing = 79 MessageUtils.findMessageNames(messageClasses); 80 81 private static final int BASE_IFACE = Protocol.BASE_TETHERING + 100; 82 // request from the user that it wants to tether 83 public static final int CMD_TETHER_REQUESTED = BASE_IFACE + 2; 84 // request from the user that it wants to untether 85 public static final int CMD_TETHER_UNREQUESTED = BASE_IFACE + 3; 86 // notification that this interface is down 87 public static final int CMD_INTERFACE_DOWN = BASE_IFACE + 4; 88 // notification from the master SM that it had trouble enabling IP Forwarding 89 public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IFACE + 7; 90 // notification from the master SM that it had trouble disabling IP Forwarding 91 public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IFACE + 8; 92 // notification from the master SM that it had trouble starting tethering 93 public static final int CMD_START_TETHERING_ERROR = BASE_IFACE + 9; 94 // notification from the master SM that it had trouble stopping tethering 95 public static final int CMD_STOP_TETHERING_ERROR = BASE_IFACE + 10; 96 // notification from the master SM that it had trouble setting the DNS forwarders 97 public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IFACE + 11; 98 // the upstream connection has changed 99 public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IFACE + 12; 100 // new IPv6 tethering parameters need to be processed 101 public static final int CMD_IPV6_TETHER_UPDATE = BASE_IFACE + 13; 102 103 private final State mInitialState; 104 private final State mLocalHotspotState; 105 private final State mTetheredState; 106 private final State mUnavailableState; 107 108 private final SharedLog mLog; 109 private final INetworkManagementService mNMService; 110 private final INetworkStatsService mStatsService; 111 private final IControlsTethering mTetherController; 112 113 private final String mIfaceName; 114 private final int mInterfaceType; 115 private final LinkProperties mLinkProperties; 116 117 private int mLastError; 118 private int mServingMode; 119 private String mMyUpstreamIfaceName; // may change over time 120 private NetworkInterface mNetworkInterface; 121 private byte[] mHwAddr; 122 // TODO: De-duplicate this with mLinkProperties above. Currently, these link 123 // properties are those selected by the IPv6TetheringCoordinator and relayed 124 // to us. By comparison, mLinkProperties contains the addresses and directly 125 // connected routes that have been formed from these properties iff. we have 126 // succeeded in configuring them and are able to announce them within Router 127 // Advertisements (otherwise, we do not add them to mLinkProperties at all). 128 private LinkProperties mLastIPv6LinkProperties; 129 private RouterAdvertisementDaemon mRaDaemon; 130 private RaParams mLastRaParams; 131 132 public TetherInterfaceStateMachine( 133 String ifaceName, Looper looper, int interfaceType, SharedLog log, 134 INetworkManagementService nMService, INetworkStatsService statsService, 135 IControlsTethering tetherController) { 136 super(ifaceName, looper); 137 mLog = log.forSubComponent(ifaceName); 138 mNMService = nMService; 139 mStatsService = statsService; 140 mTetherController = tetherController; 141 mIfaceName = ifaceName; 142 mInterfaceType = interfaceType; 143 mLinkProperties = new LinkProperties(); 144 resetLinkProperties(); 145 mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR; 146 mServingMode = IControlsTethering.STATE_AVAILABLE; 147 148 mInitialState = new InitialState(); 149 mLocalHotspotState = new LocalHotspotState(); 150 mTetheredState = new TetheredState(); 151 mUnavailableState = new UnavailableState(); 152 addState(mInitialState); 153 addState(mLocalHotspotState); 154 addState(mTetheredState); 155 addState(mUnavailableState); 156 157 setInitialState(mInitialState); 158 } 159 160 public String interfaceName() { return mIfaceName; } 161 162 public int interfaceType() { return mInterfaceType; } 163 164 public int lastError() { return mLastError; } 165 166 public int servingMode() { return mServingMode; } 167 168 public LinkProperties linkProperties() { return new LinkProperties(mLinkProperties); } 169 170 public void stop() { sendMessage(CMD_INTERFACE_DOWN); } 171 172 public void unwanted() { sendMessage(CMD_TETHER_UNREQUESTED); } 173 174 /** 175 * Internals. 176 */ 177 178 private boolean startIPv4() { return configureIPv4(true); } 179 180 private void stopIPv4() { configureIPv4(false); } 181 182 private boolean configureIPv4(boolean enabled) { 183 if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")"); 184 185 // TODO: Replace this hard-coded information with dynamically selected 186 // config passed down to us by a higher layer IP-coordinating element. 187 String ipAsString = null; 188 int prefixLen = 0; 189 if (mInterfaceType == ConnectivityManager.TETHERING_USB) { 190 ipAsString = USB_NEAR_IFACE_ADDR; 191 prefixLen = USB_PREFIX_LENGTH; 192 } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { 193 ipAsString = WIFI_HOST_IFACE_ADDR; 194 prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH; 195 } else { 196 // Nothing to do, BT does this elsewhere. 197 return true; 198 } 199 200 final LinkAddress linkAddr; 201 try { 202 final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName); 203 if (ifcg == null) { 204 mLog.e("Received null interface config"); 205 return false; 206 } 207 208 InetAddress addr = NetworkUtils.numericToInetAddress(ipAsString); 209 linkAddr = new LinkAddress(addr, prefixLen); 210 ifcg.setLinkAddress(linkAddr); 211 if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { 212 // The WiFi stack has ownership of the interface up/down state. 213 // It is unclear whether the Bluetooth or USB stacks will manage their own 214 // state. 215 ifcg.ignoreInterfaceUpDownStatus(); 216 } else { 217 if (enabled) { 218 ifcg.setInterfaceUp(); 219 } else { 220 ifcg.setInterfaceDown(); 221 } 222 } 223 ifcg.clearFlag("running"); 224 mNMService.setInterfaceConfig(mIfaceName, ifcg); 225 } catch (Exception e) { 226 mLog.e("Error configuring interface " + e); 227 return false; 228 } 229 230 // Directly-connected route. 231 final RouteInfo route = new RouteInfo(linkAddr); 232 if (enabled) { 233 mLinkProperties.addLinkAddress(linkAddr); 234 mLinkProperties.addRoute(route); 235 } else { 236 mLinkProperties.removeLinkAddress(linkAddr); 237 mLinkProperties.removeRoute(route); 238 } 239 return true; 240 } 241 242 private boolean startIPv6() { 243 // TODO: Refactor for testability (perhaps passing an android.system.Os 244 // instance and calling getifaddrs() directly). 245 try { 246 mNetworkInterface = NetworkInterface.getByName(mIfaceName); 247 } catch (SocketException e) { 248 mLog.e("Error looking up NetworkInterfaces: " + e); 249 stopIPv6(); 250 return false; 251 } 252 if (mNetworkInterface == null) { 253 mLog.e("Failed to find NetworkInterface"); 254 stopIPv6(); 255 return false; 256 } 257 258 try { 259 mHwAddr = mNetworkInterface.getHardwareAddress(); 260 } catch (SocketException e) { 261 mLog.e("Failed to find hardware address: " + e); 262 stopIPv6(); 263 return false; 264 } 265 266 final int ifindex = mNetworkInterface.getIndex(); 267 mRaDaemon = new RouterAdvertisementDaemon(mIfaceName, ifindex, mHwAddr); 268 if (!mRaDaemon.start()) { 269 stopIPv6(); 270 return false; 271 } 272 273 return true; 274 } 275 276 private void stopIPv6() { 277 mNetworkInterface = null; 278 mHwAddr = null; 279 setRaParams(null); 280 281 if (mRaDaemon != null) { 282 mRaDaemon.stop(); 283 mRaDaemon = null; 284 } 285 } 286 287 // IPv6TetheringCoordinator sends updates with carefully curated IPv6-only 288 // LinkProperties. These have extraneous data filtered out and only the 289 // necessary prefixes included (per its prefix distribution policy). 290 // 291 // TODO: Evaluate using a data structure than is more directly suited to 292 // communicating only the relevant information. 293 private void updateUpstreamIPv6LinkProperties(LinkProperties v6only) { 294 if (mRaDaemon == null) return; 295 296 // Avoid unnecessary work on spurious updates. 297 if (Objects.equals(mLastIPv6LinkProperties, v6only)) { 298 return; 299 } 300 301 RaParams params = null; 302 303 if (v6only != null) { 304 params = new RaParams(); 305 params.mtu = v6only.getMtu(); 306 params.hasDefaultRoute = v6only.hasIPv6DefaultRoute(); 307 308 for (LinkAddress linkAddr : v6only.getLinkAddresses()) { 309 if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue; 310 311 final IpPrefix prefix = new IpPrefix( 312 linkAddr.getAddress(), linkAddr.getPrefixLength()); 313 params.prefixes.add(prefix); 314 315 final Inet6Address dnsServer = getLocalDnsIpFor(prefix); 316 if (dnsServer != null) { 317 params.dnses.add(dnsServer); 318 } 319 } 320 } 321 // If v6only is null, we pass in null to setRaParams(), which handles 322 // deprecation of any existing RA data. 323 324 setRaParams(params); 325 mLastIPv6LinkProperties = v6only; 326 } 327 328 private void configureLocalIPv6Routes( 329 HashSet<IpPrefix> deprecatedPrefixes, HashSet<IpPrefix> newPrefixes) { 330 // [1] Remove the routes that are deprecated. 331 if (!deprecatedPrefixes.isEmpty()) { 332 final ArrayList<RouteInfo> toBeRemoved = 333 getLocalRoutesFor(mIfaceName, deprecatedPrefixes); 334 try { 335 final int removalFailures = mNMService.removeRoutesFromLocalNetwork(toBeRemoved); 336 if (removalFailures > 0) { 337 mLog.e(String.format("Failed to remove %d IPv6 routes from local table.", 338 removalFailures)); 339 } 340 } catch (RemoteException e) { 341 mLog.e("Failed to remove IPv6 routes from local table: " + e); 342 } 343 344 for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route); 345 } 346 347 // [2] Add only the routes that have not previously been added. 348 if (newPrefixes != null && !newPrefixes.isEmpty()) { 349 HashSet<IpPrefix> addedPrefixes = (HashSet) newPrefixes.clone(); 350 if (mLastRaParams != null) { 351 addedPrefixes.removeAll(mLastRaParams.prefixes); 352 } 353 354 if (mLastRaParams == null || mLastRaParams.prefixes.isEmpty()) { 355 // We need to be able to send unicast RAs, and clients might 356 // like to ping the default router's link-local address. Note 357 // that we never remove the link-local route from the network 358 // until Tethering disables tethering on the interface. We 359 // only need to add the link-local prefix once, but in the 360 // event we add it more than once netd silently ignores EEXIST. 361 addedPrefixes.add(LINK_LOCAL_PREFIX); 362 } 363 364 if (!addedPrefixes.isEmpty()) { 365 final ArrayList<RouteInfo> toBeAdded = 366 getLocalRoutesFor(mIfaceName, addedPrefixes); 367 try { 368 // It's safe to call addInterfaceToLocalNetwork() even if 369 // the interface is already in the local_network. Note also 370 // that adding routes that already exist does not cause an 371 // error (EEXIST is silently ignored). 372 mNMService.addInterfaceToLocalNetwork(mIfaceName, toBeAdded); 373 } catch (RemoteException e) { 374 mLog.e("Failed to add IPv6 routes to local table: " + e); 375 } 376 377 for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route); 378 } 379 } 380 } 381 382 private void configureLocalIPv6Dns( 383 HashSet<Inet6Address> deprecatedDnses, HashSet<Inet6Address> newDnses) { 384 final INetd netd = NetdService.getInstance(); 385 if (netd == null) { 386 if (newDnses != null) newDnses.clear(); 387 mLog.e("No netd service instance available; not setting local IPv6 addresses"); 388 return; 389 } 390 391 // [1] Remove deprecated local DNS IP addresses. 392 if (!deprecatedDnses.isEmpty()) { 393 for (Inet6Address dns : deprecatedDnses) { 394 final String dnsString = dns.getHostAddress(); 395 try { 396 netd.interfaceDelAddress(mIfaceName, dnsString, RFC7421_PREFIX_LENGTH); 397 } catch (ServiceSpecificException | RemoteException e) { 398 mLog.e("Failed to remove local dns IP " + dnsString + ": " + e); 399 } 400 401 mLinkProperties.removeLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH)); 402 } 403 } 404 405 // [2] Add only the local DNS IP addresses that have not previously been added. 406 if (newDnses != null && !newDnses.isEmpty()) { 407 final HashSet<Inet6Address> addedDnses = (HashSet) newDnses.clone(); 408 if (mLastRaParams != null) { 409 addedDnses.removeAll(mLastRaParams.dnses); 410 } 411 412 for (Inet6Address dns : addedDnses) { 413 final String dnsString = dns.getHostAddress(); 414 try { 415 netd.interfaceAddAddress(mIfaceName, dnsString, RFC7421_PREFIX_LENGTH); 416 } catch (ServiceSpecificException | RemoteException e) { 417 mLog.e("Failed to add local dns IP " + dnsString + ": " + e); 418 newDnses.remove(dns); 419 } 420 421 mLinkProperties.addLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH)); 422 } 423 } 424 425 try { 426 netd.tetherApplyDnsInterfaces(); 427 } catch (ServiceSpecificException | RemoteException e) { 428 mLog.e("Failed to update local DNS caching server"); 429 if (newDnses != null) newDnses.clear(); 430 } 431 } 432 433 private void setRaParams(RaParams newParams) { 434 if (mRaDaemon != null) { 435 final RaParams deprecatedParams = 436 RaParams.getDeprecatedRaParams(mLastRaParams, newParams); 437 438 configureLocalIPv6Routes(deprecatedParams.prefixes, 439 (newParams != null) ? newParams.prefixes : null); 440 441 configureLocalIPv6Dns(deprecatedParams.dnses, 442 (newParams != null) ? newParams.dnses : null); 443 444 mRaDaemon.buildNewRa(deprecatedParams, newParams); 445 } 446 447 mLastRaParams = newParams; 448 } 449 450 private void logMessage(State state, int what) { 451 mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what))); 452 } 453 454 private void sendInterfaceState(int newInterfaceState) { 455 mServingMode = newInterfaceState; 456 mTetherController.updateInterfaceState( 457 TetherInterfaceStateMachine.this, newInterfaceState, mLastError); 458 sendLinkProperties(); 459 } 460 461 private void sendLinkProperties() { 462 mTetherController.updateLinkProperties( 463 TetherInterfaceStateMachine.this, new LinkProperties(mLinkProperties)); 464 } 465 466 private void resetLinkProperties() { 467 mLinkProperties.clear(); 468 mLinkProperties.setInterfaceName(mIfaceName); 469 } 470 471 class InitialState extends State { 472 @Override 473 public void enter() { 474 sendInterfaceState(IControlsTethering.STATE_AVAILABLE); 475 } 476 477 @Override 478 public boolean processMessage(Message message) { 479 logMessage(this, message.what); 480 switch (message.what) { 481 case CMD_TETHER_REQUESTED: 482 mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR; 483 switch (message.arg1) { 484 case IControlsTethering.STATE_LOCAL_ONLY: 485 transitionTo(mLocalHotspotState); 486 break; 487 case IControlsTethering.STATE_TETHERED: 488 transitionTo(mTetheredState); 489 break; 490 default: 491 mLog.e("Invalid tethering interface serving state specified."); 492 } 493 break; 494 case CMD_INTERFACE_DOWN: 495 transitionTo(mUnavailableState); 496 break; 497 case CMD_IPV6_TETHER_UPDATE: 498 updateUpstreamIPv6LinkProperties((LinkProperties) message.obj); 499 break; 500 default: 501 return NOT_HANDLED; 502 } 503 return HANDLED; 504 } 505 } 506 507 class BaseServingState extends State { 508 @Override 509 public void enter() { 510 if (!startIPv4()) { 511 mLastError = ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR; 512 return; 513 } 514 515 try { 516 mNMService.tetherInterface(mIfaceName); 517 } catch (Exception e) { 518 mLog.e("Error Tethering: " + e); 519 mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR; 520 return; 521 } 522 523 if (!startIPv6()) { 524 mLog.e("Failed to startIPv6"); 525 // TODO: Make this a fatal error once Bluetooth IPv6 is sorted. 526 return; 527 } 528 } 529 530 @Override 531 public void exit() { 532 // Note that at this point, we're leaving the tethered state. We can fail any 533 // of these operations, but it doesn't really change that we have to try them 534 // all in sequence. 535 stopIPv6(); 536 537 try { 538 mNMService.untetherInterface(mIfaceName); 539 } catch (Exception e) { 540 mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR; 541 mLog.e("Failed to untether interface: " + e); 542 } 543 544 stopIPv4(); 545 546 resetLinkProperties(); 547 } 548 549 @Override 550 public boolean processMessage(Message message) { 551 logMessage(this, message.what); 552 switch (message.what) { 553 case CMD_TETHER_UNREQUESTED: 554 transitionTo(mInitialState); 555 if (DBG) Log.d(TAG, "Untethered (unrequested)" + mIfaceName); 556 break; 557 case CMD_INTERFACE_DOWN: 558 transitionTo(mUnavailableState); 559 if (DBG) Log.d(TAG, "Untethered (ifdown)" + mIfaceName); 560 break; 561 case CMD_IPV6_TETHER_UPDATE: 562 updateUpstreamIPv6LinkProperties((LinkProperties) message.obj); 563 sendLinkProperties(); 564 break; 565 case CMD_IP_FORWARDING_ENABLE_ERROR: 566 case CMD_IP_FORWARDING_DISABLE_ERROR: 567 case CMD_START_TETHERING_ERROR: 568 case CMD_STOP_TETHERING_ERROR: 569 case CMD_SET_DNS_FORWARDERS_ERROR: 570 mLastError = ConnectivityManager.TETHER_ERROR_MASTER_ERROR; 571 transitionTo(mInitialState); 572 break; 573 default: 574 return false; 575 } 576 return true; 577 } 578 } 579 580 // Handling errors in BaseServingState.enter() by transitioning is 581 // problematic because transitioning during a multi-state jump yields 582 // a Log.wtf(). Ultimately, there should be only one ServingState, 583 // and forwarding and NAT rules should be handled by a coordinating 584 // functional element outside of TetherInterfaceStateMachine. 585 class LocalHotspotState extends BaseServingState { 586 @Override 587 public void enter() { 588 super.enter(); 589 if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) { 590 transitionTo(mInitialState); 591 } 592 593 if (DBG) Log.d(TAG, "Local hotspot " + mIfaceName); 594 sendInterfaceState(IControlsTethering.STATE_LOCAL_ONLY); 595 } 596 597 @Override 598 public boolean processMessage(Message message) { 599 if (super.processMessage(message)) return true; 600 601 logMessage(this, message.what); 602 switch (message.what) { 603 case CMD_TETHER_REQUESTED: 604 mLog.e("CMD_TETHER_REQUESTED while in local-only hotspot mode."); 605 break; 606 case CMD_TETHER_CONNECTION_CHANGED: 607 // Ignored in local hotspot state. 608 break; 609 default: 610 return false; 611 } 612 return true; 613 } 614 } 615 616 // Handling errors in BaseServingState.enter() by transitioning is 617 // problematic because transitioning during a multi-state jump yields 618 // a Log.wtf(). Ultimately, there should be only one ServingState, 619 // and forwarding and NAT rules should be handled by a coordinating 620 // functional element outside of TetherInterfaceStateMachine. 621 class TetheredState extends BaseServingState { 622 @Override 623 public void enter() { 624 super.enter(); 625 if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) { 626 transitionTo(mInitialState); 627 } 628 629 if (DBG) Log.d(TAG, "Tethered " + mIfaceName); 630 sendInterfaceState(IControlsTethering.STATE_TETHERED); 631 } 632 633 @Override 634 public void exit() { 635 cleanupUpstream(); 636 super.exit(); 637 } 638 639 private void cleanupUpstream() { 640 if (mMyUpstreamIfaceName == null) return; 641 642 cleanupUpstreamInterface(mMyUpstreamIfaceName); 643 mMyUpstreamIfaceName = null; 644 } 645 646 private void cleanupUpstreamInterface(String upstreamIface) { 647 // Note that we don't care about errors here. 648 // Sometimes interfaces are gone before we get 649 // to remove their rules, which generates errors. 650 // Just do the best we can. 651 try { 652 // About to tear down NAT; gather remaining statistics. 653 mStatsService.forceUpdate(); 654 } catch (Exception e) { 655 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString()); 656 } 657 try { 658 mNMService.stopInterfaceForwarding(mIfaceName, upstreamIface); 659 } catch (Exception e) { 660 if (VDBG) Log.e(TAG, "Exception in removeInterfaceForward: " + e.toString()); 661 } 662 try { 663 mNMService.disableNat(mIfaceName, upstreamIface); 664 } catch (Exception e) { 665 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString()); 666 } 667 } 668 669 @Override 670 public boolean processMessage(Message message) { 671 if (super.processMessage(message)) return true; 672 673 logMessage(this, message.what); 674 switch (message.what) { 675 case CMD_TETHER_REQUESTED: 676 mLog.e("CMD_TETHER_REQUESTED while already tethering."); 677 break; 678 case CMD_TETHER_CONNECTION_CHANGED: 679 String newUpstreamIfaceName = (String)(message.obj); 680 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) || 681 (mMyUpstreamIfaceName != null && 682 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) { 683 if (VDBG) Log.d(TAG, "Connection changed noop - dropping"); 684 break; 685 } 686 cleanupUpstream(); 687 if (newUpstreamIfaceName != null) { 688 try { 689 mNMService.enableNat(mIfaceName, newUpstreamIfaceName); 690 mNMService.startInterfaceForwarding(mIfaceName, 691 newUpstreamIfaceName); 692 } catch (Exception e) { 693 mLog.e("Exception enabling NAT: " + e); 694 cleanupUpstreamInterface(newUpstreamIfaceName); 695 mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR; 696 transitionTo(mInitialState); 697 return true; 698 } 699 } 700 mMyUpstreamIfaceName = newUpstreamIfaceName; 701 break; 702 default: 703 return false; 704 } 705 return true; 706 } 707 } 708 709 /** 710 * This state is terminal for the per interface state machine. At this 711 * point, the master state machine should have removed this interface 712 * specific state machine from its list of possible recipients of 713 * tethering requests. The state machine itself will hang around until 714 * the garbage collector finds it. 715 */ 716 class UnavailableState extends State { 717 @Override 718 public void enter() { 719 mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR; 720 sendInterfaceState(IControlsTethering.STATE_UNAVAILABLE); 721 } 722 } 723 724 // Accumulate routes representing "prefixes to be assigned to the local 725 // interface", for subsequent modification of local_network routing. 726 private static ArrayList<RouteInfo> getLocalRoutesFor( 727 String ifname, HashSet<IpPrefix> prefixes) { 728 final ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>(); 729 for (IpPrefix ipp : prefixes) { 730 localRoutes.add(new RouteInfo(ipp, null, ifname)); 731 } 732 return localRoutes; 733 } 734 735 // Given a prefix like 2001:db8::/64 return an address like 2001:db8::1. 736 private static Inet6Address getLocalDnsIpFor(IpPrefix localPrefix) { 737 final byte[] dnsBytes = localPrefix.getRawAddress(); 738 dnsBytes[dnsBytes.length - 1] = getRandomNonZeroByte(); 739 try { 740 return Inet6Address.getByAddress(null, dnsBytes, 0); 741 } catch (UnknownHostException e) { 742 Slog.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix); 743 return null; 744 } 745 } 746 747 private static byte getRandomNonZeroByte() { 748 final byte random = (byte) (new Random()).nextInt(); 749 // Don't pick the subnet-router anycast address, since that might be 750 // in use on the upstream already. 751 return (random != 0) ? random : 0x1; 752 } 753 } 754