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