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