blob: 5ed14a07cb6cc1768aa5bf374212c1d23ebb2686 [file] [log] [blame]
Christopher Wileyd2896662016-05-19 11:54:54 -07001/*
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
17package com.android.server.connectivity.tethering;
18
Erik Kline94ae4c92017-06-13 21:32:10 +090019import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
20
Christopher Wileyd2896662016-05-19 11:54:54 -070021import android.net.ConnectivityManager;
Erik Kline94ae4c92017-06-13 21:32:10 +090022import android.net.INetd;
Christopher Wileyd2896662016-05-19 11:54:54 -070023import android.net.INetworkStatsService;
24import android.net.InterfaceConfiguration;
Erik Kline94ae4c92017-06-13 21:32:10 +090025import android.net.IpPrefix;
Christopher Wileyd2896662016-05-19 11:54:54 -070026import android.net.LinkAddress;
Erik Kline1eb8c692016-07-08 17:21:26 +090027import android.net.LinkProperties;
Christopher Wileyd2896662016-05-19 11:54:54 -070028import android.net.NetworkUtils;
Erik Kline94ae4c92017-06-13 21:32:10 +090029import android.net.RouteInfo;
Erik Klined3c0b5e2017-09-03 20:38:29 +090030import android.net.ip.InterfaceController;
Erik Kline94ae4c92017-06-13 21:32:10 +090031import android.net.ip.RouterAdvertisementDaemon;
32import android.net.ip.RouterAdvertisementDaemon.RaParams;
Erik Kline8bd00d52017-12-08 17:47:50 +090033import android.net.util.InterfaceParams;
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +090034import android.net.util.InterfaceSet;
Erik Kline7747fd42017-05-12 16:52:48 +090035import android.net.util.SharedLog;
Christopher Wileyd2896662016-05-19 11:54:54 -070036import android.os.INetworkManagementService;
37import android.os.Looper;
38import android.os.Message;
Erik Kline94ae4c92017-06-13 21:32:10 +090039import android.os.RemoteException;
40import android.os.ServiceSpecificException;
Christopher Wileyd2896662016-05-19 11:54:54 -070041import android.util.Log;
Erik Kline94ae4c92017-06-13 21:32:10 +090042import android.util.Slog;
Christopher Wileyd2896662016-05-19 11:54:54 -070043import android.util.SparseArray;
44
Christopher Wileyd2896662016-05-19 11:54:54 -070045import com.android.internal.util.MessageUtils;
46import com.android.internal.util.Protocol;
47import com.android.internal.util.State;
48import com.android.internal.util.StateMachine;
49
Erik Kline94ae4c92017-06-13 21:32:10 +090050import java.net.Inet6Address;
Christopher Wileyd2896662016-05-19 11:54:54 -070051import java.net.InetAddress;
Erik Kline94ae4c92017-06-13 21:32:10 +090052import java.net.UnknownHostException;
53import java.util.ArrayList;
54import java.util.HashSet;
55import java.util.Objects;
56import java.util.Random;
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +090057import java.util.Set;
Christopher Wileyd2896662016-05-19 11:54:54 -070058
59/**
Erik Klinedd4d5822017-06-12 18:20:08 +090060 * Provides the interface to IP-layer serving functionality for a given network
61 * interface, e.g. for tethering or "local-only hotspot" mode.
Christopher Wileyd2896662016-05-19 11:54:54 -070062 *
Erik Klinedd4d5822017-06-12 18:20:08 +090063 * @hide
Christopher Wileyd2896662016-05-19 11:54:54 -070064 */
Mitchell Wills7040b4e2016-05-23 16:40:10 -070065public class TetherInterfaceStateMachine extends StateMachine {
Erik Kline94ae4c92017-06-13 21:32:10 +090066 private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
67
Christopher Wileyd2896662016-05-19 11:54:54 -070068 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
69 private static final int USB_PREFIX_LENGTH = 24;
Christopher Wiley5c0b10a2016-05-31 14:43:08 -070070 private static final String WIFI_HOST_IFACE_ADDR = "192.168.43.1";
71 private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24;
Christopher Wileyd2896662016-05-19 11:54:54 -070072
73 private final static String TAG = "TetherInterfaceSM";
74 private final static boolean DBG = false;
75 private final static boolean VDBG = false;
76 private static final Class[] messageClasses = {
Mitchell Wills7040b4e2016-05-23 16:40:10 -070077 TetherInterfaceStateMachine.class
Christopher Wileyd2896662016-05-19 11:54:54 -070078 };
79 private static final SparseArray<String> sMagicDecoderRing =
80 MessageUtils.findMessageNames(messageClasses);
81
82 private static final int BASE_IFACE = Protocol.BASE_TETHERING + 100;
Christopher Wileyd2896662016-05-19 11:54:54 -070083 // request from the user that it wants to tether
84 public static final int CMD_TETHER_REQUESTED = BASE_IFACE + 2;
85 // request from the user that it wants to untether
86 public static final int CMD_TETHER_UNREQUESTED = BASE_IFACE + 3;
87 // notification that this interface is down
88 public static final int CMD_INTERFACE_DOWN = BASE_IFACE + 4;
Christopher Wileyd2896662016-05-19 11:54:54 -070089 // notification from the master SM that it had trouble enabling IP Forwarding
90 public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IFACE + 7;
91 // notification from the master SM that it had trouble disabling IP Forwarding
92 public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IFACE + 8;
93 // notification from the master SM that it had trouble starting tethering
94 public static final int CMD_START_TETHERING_ERROR = BASE_IFACE + 9;
95 // notification from the master SM that it had trouble stopping tethering
96 public static final int CMD_STOP_TETHERING_ERROR = BASE_IFACE + 10;
97 // notification from the master SM that it had trouble setting the DNS forwarders
98 public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IFACE + 11;
99 // the upstream connection has changed
100 public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IFACE + 12;
Erik Kline1eb8c692016-07-08 17:21:26 +0900101 // new IPv6 tethering parameters need to be processed
102 public static final int CMD_IPV6_TETHER_UPDATE = BASE_IFACE + 13;
Christopher Wileyd2896662016-05-19 11:54:54 -0700103
104 private final State mInitialState;
Erik Klineea9cc482017-03-10 19:35:34 +0900105 private final State mLocalHotspotState;
Christopher Wileyd2896662016-05-19 11:54:54 -0700106 private final State mTetheredState;
107 private final State mUnavailableState;
108
Erik Kline7747fd42017-05-12 16:52:48 +0900109 private final SharedLog mLog;
Christopher Wileyd2896662016-05-19 11:54:54 -0700110 private final INetworkManagementService mNMService;
Erik Klined3c0b5e2017-09-03 20:38:29 +0900111 private final INetd mNetd;
Christopher Wileyd2896662016-05-19 11:54:54 -0700112 private final INetworkStatsService mStatsService;
113 private final IControlsTethering mTetherController;
Erik Klined3c0b5e2017-09-03 20:38:29 +0900114 private final InterfaceController mInterfaceCtrl;
Christopher Wileyd2896662016-05-19 11:54:54 -0700115
Christopher Wileyd2896662016-05-19 11:54:54 -0700116 private final String mIfaceName;
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700117 private final int mInterfaceType;
Erik Klineab6439b2017-06-06 19:24:21 +0900118 private final LinkProperties mLinkProperties;
Christopher Wileyd2896662016-05-19 11:54:54 -0700119
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900120 private final TetheringDependencies mDeps;
121
Christopher Wileyd2896662016-05-19 11:54:54 -0700122 private int mLastError;
Erik Klineb3bb26e2017-07-06 19:49:35 +0900123 private int mServingMode;
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900124 private InterfaceSet mUpstreamIfaceSet; // may change over time
Erik Kline8bd00d52017-12-08 17:47:50 +0900125 private InterfaceParams mInterfaceParams;
Erik Klinedd4d5822017-06-12 18:20:08 +0900126 // TODO: De-duplicate this with mLinkProperties above. Currently, these link
127 // properties are those selected by the IPv6TetheringCoordinator and relayed
128 // to us. By comparison, mLinkProperties contains the addresses and directly
129 // connected routes that have been formed from these properties iff. we have
130 // succeeded in configuring them and are able to announce them within Router
131 // Advertisements (otherwise, we do not add them to mLinkProperties at all).
Erik Kline94ae4c92017-06-13 21:32:10 +0900132 private LinkProperties mLastIPv6LinkProperties;
133 private RouterAdvertisementDaemon mRaDaemon;
134 private RaParams mLastRaParams;
Christopher Wileyd2896662016-05-19 11:54:54 -0700135
Erik Kline7747fd42017-05-12 16:52:48 +0900136 public TetherInterfaceStateMachine(
137 String ifaceName, Looper looper, int interfaceType, SharedLog log,
138 INetworkManagementService nMService, INetworkStatsService statsService,
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900139 IControlsTethering tetherController,
140 TetheringDependencies deps) {
Christopher Wileyd2896662016-05-19 11:54:54 -0700141 super(ifaceName, looper);
Erik Kline7747fd42017-05-12 16:52:48 +0900142 mLog = log.forSubComponent(ifaceName);
Christopher Wileyd2896662016-05-19 11:54:54 -0700143 mNMService = nMService;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900144 mNetd = deps.getNetdService();
Christopher Wileyd2896662016-05-19 11:54:54 -0700145 mStatsService = statsService;
146 mTetherController = tetherController;
Erik Klined3c0b5e2017-09-03 20:38:29 +0900147 mInterfaceCtrl = new InterfaceController(ifaceName, nMService, mNetd, mLog);
Christopher Wileyd2896662016-05-19 11:54:54 -0700148 mIfaceName = ifaceName;
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700149 mInterfaceType = interfaceType;
Erik Klineab6439b2017-06-06 19:24:21 +0900150 mLinkProperties = new LinkProperties();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900151 mDeps = deps;
Erik Klinedd4d5822017-06-12 18:20:08 +0900152 resetLinkProperties();
Christopher Wileyd985dde2016-05-31 10:44:35 -0700153 mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
Erik Klineb3bb26e2017-07-06 19:49:35 +0900154 mServingMode = IControlsTethering.STATE_AVAILABLE;
Christopher Wileyd2896662016-05-19 11:54:54 -0700155
156 mInitialState = new InitialState();
Erik Klineea9cc482017-03-10 19:35:34 +0900157 mLocalHotspotState = new LocalHotspotState();
Christopher Wileyd2896662016-05-19 11:54:54 -0700158 mTetheredState = new TetheredState();
Christopher Wileyd2896662016-05-19 11:54:54 -0700159 mUnavailableState = new UnavailableState();
Erik Klineea9cc482017-03-10 19:35:34 +0900160 addState(mInitialState);
Erik Klinef79a34d2017-04-13 22:54:34 +0900161 addState(mLocalHotspotState);
162 addState(mTetheredState);
Christopher Wileyd2896662016-05-19 11:54:54 -0700163 addState(mUnavailableState);
164
165 setInitialState(mInitialState);
166 }
167
Erik Kline216af6d2017-04-27 20:57:23 +0900168 public String interfaceName() { return mIfaceName; }
169
170 public int interfaceType() { return mInterfaceType; }
171
172 public int lastError() { return mLastError; }
Erik Kline1eb8c692016-07-08 17:21:26 +0900173
Erik Klineb3bb26e2017-07-06 19:49:35 +0900174 public int servingMode() { return mServingMode; }
175
Erik Kline5acb4e32017-07-04 18:28:11 +0900176 public LinkProperties linkProperties() { return new LinkProperties(mLinkProperties); }
177
Erik Klineab6439b2017-06-06 19:24:21 +0900178 public void stop() { sendMessage(CMD_INTERFACE_DOWN); }
179
Erik Kline218c2262017-06-09 16:36:29 +0900180 public void unwanted() { sendMessage(CMD_TETHER_UNREQUESTED); }
181
Erik Kline94ae4c92017-06-13 21:32:10 +0900182 /**
183 * Internals.
184 */
185
Erik Klinedd4d5822017-06-12 18:20:08 +0900186 private boolean startIPv4() { return configureIPv4(true); }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700187
Erik Klinedd4d5822017-06-12 18:20:08 +0900188 private void stopIPv4() { configureIPv4(false); }
189
Erik Klined3c0b5e2017-09-03 20:38:29 +0900190 // TODO: Refactor this in terms of calls to InterfaceController.
Erik Klinedd4d5822017-06-12 18:20:08 +0900191 private boolean configureIPv4(boolean enabled) {
192 if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");
193
194 // TODO: Replace this hard-coded information with dynamically selected
195 // config passed down to us by a higher layer IP-coordinating element.
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700196 String ipAsString = null;
197 int prefixLen = 0;
198 if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
199 ipAsString = USB_NEAR_IFACE_ADDR;
200 prefixLen = USB_PREFIX_LENGTH;
201 } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
202 ipAsString = WIFI_HOST_IFACE_ADDR;
203 prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
204 } else {
205 // Nothing to do, BT does this elsewhere.
206 return true;
207 }
Christopher Wileyd2896662016-05-19 11:54:54 -0700208
Erik Klinedd4d5822017-06-12 18:20:08 +0900209 final LinkAddress linkAddr;
Christopher Wileyd2896662016-05-19 11:54:54 -0700210 try {
Erik Klinedd4d5822017-06-12 18:20:08 +0900211 final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName);
212 if (ifcg == null) {
213 mLog.e("Received null interface config");
214 return false;
Christopher Wileyd2896662016-05-19 11:54:54 -0700215 }
Erik Klinedd4d5822017-06-12 18:20:08 +0900216
217 InetAddress addr = NetworkUtils.numericToInetAddress(ipAsString);
218 linkAddr = new LinkAddress(addr, prefixLen);
219 ifcg.setLinkAddress(linkAddr);
220 if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
221 // The WiFi stack has ownership of the interface up/down state.
222 // It is unclear whether the Bluetooth or USB stacks will manage their own
223 // state.
224 ifcg.ignoreInterfaceUpDownStatus();
225 } else {
226 if (enabled) {
227 ifcg.setInterfaceUp();
228 } else {
229 ifcg.setInterfaceDown();
230 }
231 }
232 ifcg.clearFlag("running");
233 mNMService.setInterfaceConfig(mIfaceName, ifcg);
Christopher Wileyd2896662016-05-19 11:54:54 -0700234 } catch (Exception e) {
Erik Kline7747fd42017-05-12 16:52:48 +0900235 mLog.e("Error configuring interface " + e);
Christopher Wileyd2896662016-05-19 11:54:54 -0700236 return false;
237 }
238
Erik Klinedd4d5822017-06-12 18:20:08 +0900239 // Directly-connected route.
240 final RouteInfo route = new RouteInfo(linkAddr);
241 if (enabled) {
242 mLinkProperties.addLinkAddress(linkAddr);
243 mLinkProperties.addRoute(route);
244 } else {
245 mLinkProperties.removeLinkAddress(linkAddr);
246 mLinkProperties.removeRoute(route);
247 }
Christopher Wileyd2896662016-05-19 11:54:54 -0700248 return true;
249 }
250
Erik Kline94ae4c92017-06-13 21:32:10 +0900251 private boolean startIPv6() {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900252 mInterfaceParams = mDeps.getInterfaceParams(mIfaceName);
Erik Kline8bd00d52017-12-08 17:47:50 +0900253 if (mInterfaceParams == null) {
254 mLog.e("Failed to find InterfaceParams");
Erik Kline94ae4c92017-06-13 21:32:10 +0900255 stopIPv6();
256 return false;
257 }
258
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900259 mRaDaemon = mDeps.getRouterAdvertisementDaemon(mInterfaceParams);
Erik Kline94ae4c92017-06-13 21:32:10 +0900260 if (!mRaDaemon.start()) {
261 stopIPv6();
262 return false;
263 }
264
265 return true;
266 }
267
268 private void stopIPv6() {
Erik Kline8bd00d52017-12-08 17:47:50 +0900269 mInterfaceParams = null;
Erik Kline94ae4c92017-06-13 21:32:10 +0900270 setRaParams(null);
271
272 if (mRaDaemon != null) {
273 mRaDaemon.stop();
274 mRaDaemon = null;
275 }
276 }
277
278 // IPv6TetheringCoordinator sends updates with carefully curated IPv6-only
279 // LinkProperties. These have extraneous data filtered out and only the
280 // necessary prefixes included (per its prefix distribution policy).
281 //
282 // TODO: Evaluate using a data structure than is more directly suited to
283 // communicating only the relevant information.
284 private void updateUpstreamIPv6LinkProperties(LinkProperties v6only) {
285 if (mRaDaemon == null) return;
286
287 // Avoid unnecessary work on spurious updates.
288 if (Objects.equals(mLastIPv6LinkProperties, v6only)) {
289 return;
290 }
291
292 RaParams params = null;
293
294 if (v6only != null) {
295 params = new RaParams();
296 params.mtu = v6only.getMtu();
297 params.hasDefaultRoute = v6only.hasIPv6DefaultRoute();
298
299 for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
300 if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue;
301
302 final IpPrefix prefix = new IpPrefix(
303 linkAddr.getAddress(), linkAddr.getPrefixLength());
304 params.prefixes.add(prefix);
305
306 final Inet6Address dnsServer = getLocalDnsIpFor(prefix);
307 if (dnsServer != null) {
308 params.dnses.add(dnsServer);
309 }
310 }
311 }
312 // If v6only is null, we pass in null to setRaParams(), which handles
313 // deprecation of any existing RA data.
314
315 setRaParams(params);
316 mLastIPv6LinkProperties = v6only;
317 }
318
Erik Klinedd4d5822017-06-12 18:20:08 +0900319 private void configureLocalIPv6Routes(
Erik Kline94ae4c92017-06-13 21:32:10 +0900320 HashSet<IpPrefix> deprecatedPrefixes, HashSet<IpPrefix> newPrefixes) {
321 // [1] Remove the routes that are deprecated.
322 if (!deprecatedPrefixes.isEmpty()) {
323 final ArrayList<RouteInfo> toBeRemoved =
324 getLocalRoutesFor(mIfaceName, deprecatedPrefixes);
325 try {
326 final int removalFailures = mNMService.removeRoutesFromLocalNetwork(toBeRemoved);
327 if (removalFailures > 0) {
328 mLog.e(String.format("Failed to remove %d IPv6 routes from local table.",
329 removalFailures));
330 }
331 } catch (RemoteException e) {
332 mLog.e("Failed to remove IPv6 routes from local table: " + e);
333 }
Erik Klinedd4d5822017-06-12 18:20:08 +0900334
335 for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route);
Erik Kline94ae4c92017-06-13 21:32:10 +0900336 }
337
338 // [2] Add only the routes that have not previously been added.
339 if (newPrefixes != null && !newPrefixes.isEmpty()) {
340 HashSet<IpPrefix> addedPrefixes = (HashSet) newPrefixes.clone();
341 if (mLastRaParams != null) {
342 addedPrefixes.removeAll(mLastRaParams.prefixes);
343 }
344
345 if (mLastRaParams == null || mLastRaParams.prefixes.isEmpty()) {
346 // We need to be able to send unicast RAs, and clients might
347 // like to ping the default router's link-local address. Note
348 // that we never remove the link-local route from the network
349 // until Tethering disables tethering on the interface. We
350 // only need to add the link-local prefix once, but in the
351 // event we add it more than once netd silently ignores EEXIST.
352 addedPrefixes.add(LINK_LOCAL_PREFIX);
353 }
354
355 if (!addedPrefixes.isEmpty()) {
356 final ArrayList<RouteInfo> toBeAdded =
357 getLocalRoutesFor(mIfaceName, addedPrefixes);
358 try {
359 // It's safe to call addInterfaceToLocalNetwork() even if
360 // the interface is already in the local_network. Note also
361 // that adding routes that already exist does not cause an
362 // error (EEXIST is silently ignored).
363 mNMService.addInterfaceToLocalNetwork(mIfaceName, toBeAdded);
364 } catch (RemoteException e) {
365 mLog.e("Failed to add IPv6 routes to local table: " + e);
366 }
Erik Klinedd4d5822017-06-12 18:20:08 +0900367
368 for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route);
Erik Kline94ae4c92017-06-13 21:32:10 +0900369 }
370 }
371 }
372
Erik Klinedd4d5822017-06-12 18:20:08 +0900373 private void configureLocalIPv6Dns(
Erik Kline94ae4c92017-06-13 21:32:10 +0900374 HashSet<Inet6Address> deprecatedDnses, HashSet<Inet6Address> newDnses) {
Erik Klined3c0b5e2017-09-03 20:38:29 +0900375 // TODO: Is this really necessary? Can we not fail earlier if INetd cannot be located?
376 if (mNetd == null) {
Erik Kline94ae4c92017-06-13 21:32:10 +0900377 if (newDnses != null) newDnses.clear();
378 mLog.e("No netd service instance available; not setting local IPv6 addresses");
379 return;
380 }
381
382 // [1] Remove deprecated local DNS IP addresses.
383 if (!deprecatedDnses.isEmpty()) {
384 for (Inet6Address dns : deprecatedDnses) {
Erik Klined3c0b5e2017-09-03 20:38:29 +0900385 if (!mInterfaceCtrl.removeAddress(dns, RFC7421_PREFIX_LENGTH)) {
386 mLog.e("Failed to remove local dns IP " + dns);
Erik Kline94ae4c92017-06-13 21:32:10 +0900387 }
Erik Klinedd4d5822017-06-12 18:20:08 +0900388
389 mLinkProperties.removeLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH));
Erik Kline94ae4c92017-06-13 21:32:10 +0900390 }
391 }
392
393 // [2] Add only the local DNS IP addresses that have not previously been added.
394 if (newDnses != null && !newDnses.isEmpty()) {
395 final HashSet<Inet6Address> addedDnses = (HashSet) newDnses.clone();
396 if (mLastRaParams != null) {
397 addedDnses.removeAll(mLastRaParams.dnses);
398 }
399
400 for (Inet6Address dns : addedDnses) {
Erik Klined3c0b5e2017-09-03 20:38:29 +0900401 if (!mInterfaceCtrl.addAddress(dns, RFC7421_PREFIX_LENGTH)) {
402 mLog.e("Failed to add local dns IP " + dns);
Erik Kline94ae4c92017-06-13 21:32:10 +0900403 newDnses.remove(dns);
404 }
Erik Klinedd4d5822017-06-12 18:20:08 +0900405
406 mLinkProperties.addLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH));
Erik Kline94ae4c92017-06-13 21:32:10 +0900407 }
408 }
409
410 try {
Erik Klined3c0b5e2017-09-03 20:38:29 +0900411 mNetd.tetherApplyDnsInterfaces();
Erik Kline94ae4c92017-06-13 21:32:10 +0900412 } catch (ServiceSpecificException | RemoteException e) {
413 mLog.e("Failed to update local DNS caching server");
414 if (newDnses != null) newDnses.clear();
415 }
416 }
417
418 private void setRaParams(RaParams newParams) {
419 if (mRaDaemon != null) {
420 final RaParams deprecatedParams =
421 RaParams.getDeprecatedRaParams(mLastRaParams, newParams);
422
Erik Klinedd4d5822017-06-12 18:20:08 +0900423 configureLocalIPv6Routes(deprecatedParams.prefixes,
Erik Kline94ae4c92017-06-13 21:32:10 +0900424 (newParams != null) ? newParams.prefixes : null);
425
Erik Klinedd4d5822017-06-12 18:20:08 +0900426 configureLocalIPv6Dns(deprecatedParams.dnses,
Erik Kline94ae4c92017-06-13 21:32:10 +0900427 (newParams != null) ? newParams.dnses : null);
428
429 mRaDaemon.buildNewRa(deprecatedParams, newParams);
430 }
431
432 mLastRaParams = newParams;
433 }
434
Erik Klineb4df3f42017-07-06 16:40:06 +0900435 private void logMessage(State state, int what) {
436 mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what)));
Christopher Wileyd2896662016-05-19 11:54:54 -0700437 }
438
Erik Klineea9cc482017-03-10 19:35:34 +0900439 private void sendInterfaceState(int newInterfaceState) {
Erik Klineb3bb26e2017-07-06 19:49:35 +0900440 mServingMode = newInterfaceState;
Erik Klineab6439b2017-06-06 19:24:21 +0900441 mTetherController.updateInterfaceState(
442 TetherInterfaceStateMachine.this, newInterfaceState, mLastError);
Erik Klinedd4d5822017-06-12 18:20:08 +0900443 sendLinkProperties();
444 }
445
446 private void sendLinkProperties() {
Erik Klineab6439b2017-06-06 19:24:21 +0900447 mTetherController.updateLinkProperties(
448 TetherInterfaceStateMachine.this, new LinkProperties(mLinkProperties));
Erik Klineea9cc482017-03-10 19:35:34 +0900449 }
450
Erik Klinedd4d5822017-06-12 18:20:08 +0900451 private void resetLinkProperties() {
452 mLinkProperties.clear();
453 mLinkProperties.setInterfaceName(mIfaceName);
454 }
455
Christopher Wileyd2896662016-05-19 11:54:54 -0700456 class InitialState extends State {
457 @Override
458 public void enter() {
Erik Klineea9cc482017-03-10 19:35:34 +0900459 sendInterfaceState(IControlsTethering.STATE_AVAILABLE);
Christopher Wileyd2896662016-05-19 11:54:54 -0700460 }
461
462 @Override
463 public boolean processMessage(Message message) {
Erik Klineb4df3f42017-07-06 16:40:06 +0900464 logMessage(this, message.what);
Christopher Wileyd2896662016-05-19 11:54:54 -0700465 switch (message.what) {
466 case CMD_TETHER_REQUESTED:
Christopher Wileyd985dde2016-05-31 10:44:35 -0700467 mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
Erik Klineea9cc482017-03-10 19:35:34 +0900468 switch (message.arg1) {
Erik Klineca41be72017-04-20 22:59:16 +0900469 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Klineea9cc482017-03-10 19:35:34 +0900470 transitionTo(mLocalHotspotState);
471 break;
472 case IControlsTethering.STATE_TETHERED:
473 transitionTo(mTetheredState);
474 break;
475 default:
Erik Kline7747fd42017-05-12 16:52:48 +0900476 mLog.e("Invalid tethering interface serving state specified.");
Erik Klineea9cc482017-03-10 19:35:34 +0900477 }
Christopher Wileyd2896662016-05-19 11:54:54 -0700478 break;
479 case CMD_INTERFACE_DOWN:
480 transitionTo(mUnavailableState);
481 break;
Erik Kline1eb8c692016-07-08 17:21:26 +0900482 case CMD_IPV6_TETHER_UPDATE:
Erik Kline94ae4c92017-06-13 21:32:10 +0900483 updateUpstreamIPv6LinkProperties((LinkProperties) message.obj);
Erik Kline1eb8c692016-07-08 17:21:26 +0900484 break;
Christopher Wileyd2896662016-05-19 11:54:54 -0700485 default:
Erik Klineab6439b2017-06-06 19:24:21 +0900486 return NOT_HANDLED;
Christopher Wileyd2896662016-05-19 11:54:54 -0700487 }
Erik Klineab6439b2017-06-06 19:24:21 +0900488 return HANDLED;
Christopher Wileyd2896662016-05-19 11:54:54 -0700489 }
490 }
491
Erik Klinef79a34d2017-04-13 22:54:34 +0900492 class BaseServingState extends State {
Christopher Wileyd2896662016-05-19 11:54:54 -0700493 @Override
494 public void enter() {
Erik Klinedd4d5822017-06-12 18:20:08 +0900495 if (!startIPv4()) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700496 mLastError = ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR;
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700497 return;
Christopher Wileyd2896662016-05-19 11:54:54 -0700498 }
Christopher Wileyd2896662016-05-19 11:54:54 -0700499
Christopher Wileyd2896662016-05-19 11:54:54 -0700500 try {
501 mNMService.tetherInterface(mIfaceName);
502 } catch (Exception e) {
Erik Kline7747fd42017-05-12 16:52:48 +0900503 mLog.e("Error Tethering: " + e);
Christopher Wileyd985dde2016-05-31 10:44:35 -0700504 mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
Christopher Wileyd2896662016-05-19 11:54:54 -0700505 return;
506 }
Erik Kline1eb8c692016-07-08 17:21:26 +0900507
Erik Kline94ae4c92017-06-13 21:32:10 +0900508 if (!startIPv6()) {
509 mLog.e("Failed to startIPv6");
Erik Klinef79a34d2017-04-13 22:54:34 +0900510 // TODO: Make this a fatal error once Bluetooth IPv6 is sorted.
511 return;
Erik Kline1eb8c692016-07-08 17:21:26 +0900512 }
Christopher Wileyd2896662016-05-19 11:54:54 -0700513 }
514
Christopher Wileye10bfc02016-05-23 16:17:30 -0700515 @Override
516 public void exit() {
Christopher Wileye10bfc02016-05-23 16:17:30 -0700517 // Note that at this point, we're leaving the tethered state. We can fail any
518 // of these operations, but it doesn't really change that we have to try them
519 // all in sequence.
Erik Kline94ae4c92017-06-13 21:32:10 +0900520 stopIPv6();
Christopher Wileye10bfc02016-05-23 16:17:30 -0700521
522 try {
523 mNMService.untetherInterface(mIfaceName);
Erik Klinef79a34d2017-04-13 22:54:34 +0900524 } catch (Exception e) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700525 mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
Erik Kline7747fd42017-05-12 16:52:48 +0900526 mLog.e("Failed to untether interface: " + e);
Christopher Wileye10bfc02016-05-23 16:17:30 -0700527 }
528
Erik Klinedd4d5822017-06-12 18:20:08 +0900529 stopIPv4();
530
531 resetLinkProperties();
Christopher Wileye10bfc02016-05-23 16:17:30 -0700532 }
533
Erik Klineea9cc482017-03-10 19:35:34 +0900534 @Override
535 public boolean processMessage(Message message) {
Erik Klineb4df3f42017-07-06 16:40:06 +0900536 logMessage(this, message.what);
Erik Klineea9cc482017-03-10 19:35:34 +0900537 switch (message.what) {
538 case CMD_TETHER_UNREQUESTED:
539 transitionTo(mInitialState);
540 if (DBG) Log.d(TAG, "Untethered (unrequested)" + mIfaceName);
541 break;
542 case CMD_INTERFACE_DOWN:
543 transitionTo(mUnavailableState);
544 if (DBG) Log.d(TAG, "Untethered (ifdown)" + mIfaceName);
545 break;
546 case CMD_IPV6_TETHER_UPDATE:
Erik Kline94ae4c92017-06-13 21:32:10 +0900547 updateUpstreamIPv6LinkProperties((LinkProperties) message.obj);
Erik Klinedd4d5822017-06-12 18:20:08 +0900548 sendLinkProperties();
Erik Klineea9cc482017-03-10 19:35:34 +0900549 break;
550 case CMD_IP_FORWARDING_ENABLE_ERROR:
551 case CMD_IP_FORWARDING_DISABLE_ERROR:
552 case CMD_START_TETHERING_ERROR:
553 case CMD_STOP_TETHERING_ERROR:
554 case CMD_SET_DNS_FORWARDERS_ERROR:
555 mLastError = ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
556 transitionTo(mInitialState);
557 break;
558 default:
559 return false;
560 }
561 return true;
562 }
563 }
564
Erik Klinef79a34d2017-04-13 22:54:34 +0900565 // Handling errors in BaseServingState.enter() by transitioning is
566 // problematic because transitioning during a multi-state jump yields
567 // a Log.wtf(). Ultimately, there should be only one ServingState,
568 // and forwarding and NAT rules should be handled by a coordinating
569 // functional element outside of TetherInterfaceStateMachine.
570 class LocalHotspotState extends BaseServingState {
Erik Klineea9cc482017-03-10 19:35:34 +0900571 @Override
572 public void enter() {
Erik Klinef79a34d2017-04-13 22:54:34 +0900573 super.enter();
574 if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
575 transitionTo(mInitialState);
576 }
577
Erik Klineea9cc482017-03-10 19:35:34 +0900578 if (DBG) Log.d(TAG, "Local hotspot " + mIfaceName);
Erik Klineca41be72017-04-20 22:59:16 +0900579 sendInterfaceState(IControlsTethering.STATE_LOCAL_ONLY);
Erik Klineea9cc482017-03-10 19:35:34 +0900580 }
581
582 @Override
583 public boolean processMessage(Message message) {
Erik Klinef79a34d2017-04-13 22:54:34 +0900584 if (super.processMessage(message)) return true;
585
Erik Klineb4df3f42017-07-06 16:40:06 +0900586 logMessage(this, message.what);
Erik Klineea9cc482017-03-10 19:35:34 +0900587 switch (message.what) {
588 case CMD_TETHER_REQUESTED:
Erik Kline7747fd42017-05-12 16:52:48 +0900589 mLog.e("CMD_TETHER_REQUESTED while in local-only hotspot mode.");
Erik Klineea9cc482017-03-10 19:35:34 +0900590 break;
591 case CMD_TETHER_CONNECTION_CHANGED:
592 // Ignored in local hotspot state.
593 break;
594 default:
595 return false;
596 }
597 return true;
598 }
599 }
600
Erik Klinef79a34d2017-04-13 22:54:34 +0900601 // Handling errors in BaseServingState.enter() by transitioning is
602 // problematic because transitioning during a multi-state jump yields
603 // a Log.wtf(). Ultimately, there should be only one ServingState,
604 // and forwarding and NAT rules should be handled by a coordinating
605 // functional element outside of TetherInterfaceStateMachine.
606 class TetheredState extends BaseServingState {
Erik Klineea9cc482017-03-10 19:35:34 +0900607 @Override
608 public void enter() {
Erik Klinef79a34d2017-04-13 22:54:34 +0900609 super.enter();
610 if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
611 transitionTo(mInitialState);
612 }
613
Erik Klineea9cc482017-03-10 19:35:34 +0900614 if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
615 sendInterfaceState(IControlsTethering.STATE_TETHERED);
616 }
617
618 @Override
619 public void exit() {
620 cleanupUpstream();
Erik Klinef79a34d2017-04-13 22:54:34 +0900621 super.exit();
Erik Klineea9cc482017-03-10 19:35:34 +0900622 }
623
Christopher Wileyd2896662016-05-19 11:54:54 -0700624 private void cleanupUpstream() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900625 if (mUpstreamIfaceSet == null) return;
Erik Kline8ea45482017-02-13 17:28:53 +0900626
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900627 for (String ifname : mUpstreamIfaceSet.ifnames) cleanupUpstreamInterface(ifname);
628 mUpstreamIfaceSet = null;
Erik Kline8ea45482017-02-13 17:28:53 +0900629 }
630
631 private void cleanupUpstreamInterface(String upstreamIface) {
632 // Note that we don't care about errors here.
633 // Sometimes interfaces are gone before we get
634 // to remove their rules, which generates errors.
635 // Just do the best we can.
636 try {
637 // About to tear down NAT; gather remaining statistics.
638 mStatsService.forceUpdate();
639 } catch (Exception e) {
640 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
Christopher Wileyd2896662016-05-19 11:54:54 -0700641 }
Erik Kline8ea45482017-02-13 17:28:53 +0900642 try {
643 mNMService.stopInterfaceForwarding(mIfaceName, upstreamIface);
644 } catch (Exception e) {
645 if (VDBG) Log.e(TAG, "Exception in removeInterfaceForward: " + e.toString());
646 }
647 try {
648 mNMService.disableNat(mIfaceName, upstreamIface);
649 } catch (Exception e) {
650 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
651 }
Christopher Wileyd2896662016-05-19 11:54:54 -0700652 }
653
654 @Override
655 public boolean processMessage(Message message) {
Erik Klinef79a34d2017-04-13 22:54:34 +0900656 if (super.processMessage(message)) return true;
657
Erik Klineb4df3f42017-07-06 16:40:06 +0900658 logMessage(this, message.what);
Christopher Wileyd2896662016-05-19 11:54:54 -0700659 switch (message.what) {
Erik Klineea9cc482017-03-10 19:35:34 +0900660 case CMD_TETHER_REQUESTED:
Erik Kline7747fd42017-05-12 16:52:48 +0900661 mLog.e("CMD_TETHER_REQUESTED while already tethering.");
Christopher Wileyd2896662016-05-19 11:54:54 -0700662 break;
663 case CMD_TETHER_CONNECTION_CHANGED:
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900664 final InterfaceSet newUpstreamIfaceSet = (InterfaceSet) message.obj;
665 if (noChangeInUpstreamIfaceSet(newUpstreamIfaceSet)) {
Christopher Wileyd2896662016-05-19 11:54:54 -0700666 if (VDBG) Log.d(TAG, "Connection changed noop - dropping");
667 break;
668 }
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900669
670 if (newUpstreamIfaceSet == null) {
671 cleanupUpstream();
672 break;
673 }
674
675 for (String removed : upstreamInterfacesRemoved(newUpstreamIfaceSet)) {
676 cleanupUpstreamInterface(removed);
677 }
678
679 final Set<String> added = upstreamInterfacesAdd(newUpstreamIfaceSet);
680 // This makes the call to cleanupUpstream() in the error
681 // path for any interface neatly cleanup all the interfaces.
682 mUpstreamIfaceSet = newUpstreamIfaceSet;
683
684 for (String ifname : added) {
Christopher Wileyd2896662016-05-19 11:54:54 -0700685 try {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900686 mNMService.enableNat(mIfaceName, ifname);
687 mNMService.startInterfaceForwarding(mIfaceName, ifname);
Christopher Wileyd2896662016-05-19 11:54:54 -0700688 } catch (Exception e) {
Erik Kline7747fd42017-05-12 16:52:48 +0900689 mLog.e("Exception enabling NAT: " + e);
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900690 cleanupUpstream();
Christopher Wileyd985dde2016-05-31 10:44:35 -0700691 mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
Christopher Wileyd2896662016-05-19 11:54:54 -0700692 transitionTo(mInitialState);
693 return true;
694 }
695 }
Christopher Wileyd2896662016-05-19 11:54:54 -0700696 break;
Christopher Wileyd2896662016-05-19 11:54:54 -0700697 default:
Erik Klinedd4d5822017-06-12 18:20:08 +0900698 return false;
Christopher Wileyd2896662016-05-19 11:54:54 -0700699 }
Erik Klinedd4d5822017-06-12 18:20:08 +0900700 return true;
Christopher Wileyd2896662016-05-19 11:54:54 -0700701 }
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900702
703 private boolean noChangeInUpstreamIfaceSet(InterfaceSet newIfaces) {
704 if (mUpstreamIfaceSet == null && newIfaces == null) return true;
705 if (mUpstreamIfaceSet != null && newIfaces != null) {
706 return mUpstreamIfaceSet.equals(newIfaces);
707 }
708 return false;
709 }
710
711 private Set<String> upstreamInterfacesRemoved(InterfaceSet newIfaces) {
712 if (mUpstreamIfaceSet == null) return new HashSet<>();
713
714 final HashSet<String> removed = new HashSet<>(mUpstreamIfaceSet.ifnames);
715 removed.removeAll(newIfaces.ifnames);
716 return removed;
717 }
718
719 private Set<String> upstreamInterfacesAdd(InterfaceSet newIfaces) {
720 final HashSet<String> added = new HashSet<>(newIfaces.ifnames);
721 if (mUpstreamIfaceSet != null) added.removeAll(mUpstreamIfaceSet.ifnames);
722 return added;
723 }
Christopher Wileyd2896662016-05-19 11:54:54 -0700724 }
725
Christopher Wiley9ad83ab2016-05-20 17:51:27 -0700726 /**
727 * This state is terminal for the per interface state machine. At this
728 * point, the master state machine should have removed this interface
729 * specific state machine from its list of possible recipients of
730 * tethering requests. The state machine itself will hang around until
731 * the garbage collector finds it.
732 */
Christopher Wileyd2896662016-05-19 11:54:54 -0700733 class UnavailableState extends State {
734 @Override
735 public void enter() {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700736 mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
Erik Klineea9cc482017-03-10 19:35:34 +0900737 sendInterfaceState(IControlsTethering.STATE_UNAVAILABLE);
Christopher Wileyd2896662016-05-19 11:54:54 -0700738 }
Christopher Wileyd2896662016-05-19 11:54:54 -0700739 }
Erik Kline94ae4c92017-06-13 21:32:10 +0900740
741 // Accumulate routes representing "prefixes to be assigned to the local
742 // interface", for subsequent modification of local_network routing.
743 private static ArrayList<RouteInfo> getLocalRoutesFor(
744 String ifname, HashSet<IpPrefix> prefixes) {
745 final ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>();
746 for (IpPrefix ipp : prefixes) {
747 localRoutes.add(new RouteInfo(ipp, null, ifname));
748 }
749 return localRoutes;
750 }
751
752 // Given a prefix like 2001:db8::/64 return an address like 2001:db8::1.
753 private static Inet6Address getLocalDnsIpFor(IpPrefix localPrefix) {
754 final byte[] dnsBytes = localPrefix.getRawAddress();
755 dnsBytes[dnsBytes.length - 1] = getRandomNonZeroByte();
756 try {
757 return Inet6Address.getByAddress(null, dnsBytes, 0);
758 } catch (UnknownHostException e) {
759 Slog.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix);
760 return null;
761 }
762 }
763
764 private static byte getRandomNonZeroByte() {
765 final byte random = (byte) (new Random()).nextInt();
766 // Don't pick the subnet-router anycast address, since that might be
767 // in use on the upstream already.
768 return (random != 0) ? random : 0x1;
769 }
Christopher Wileyd2896662016-05-19 11:54:54 -0700770}