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