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