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