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