1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.ip;
18 
19 import static android.net.INetd.IF_STATE_DOWN;
20 import static android.net.INetd.IF_STATE_UP;
21 import static android.net.RouteInfo.RTN_UNICAST;
22 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL;
23 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
24 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
25 import static android.net.TetheringManager.TETHERING_NCM;
26 import static android.net.TetheringManager.TETHERING_USB;
27 import static android.net.TetheringManager.TETHERING_WIFI;
28 import static android.net.TetheringManager.TETHERING_WIFI_P2P;
29 import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
30 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
31 import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
32 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
33 import static android.net.ip.IpServer.STATE_AVAILABLE;
34 import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
35 import static android.net.ip.IpServer.STATE_TETHERED;
36 import static android.net.ip.IpServer.STATE_UNAVAILABLE;
37 import static android.net.ip.IpServer.getTetherableIpv6Prefixes;
38 
39 import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
40 import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
41 
42 import static org.junit.Assert.assertEquals;
43 import static org.junit.Assert.assertFalse;
44 import static org.junit.Assert.assertNotEquals;
45 import static org.junit.Assert.assertNotNull;
46 import static org.junit.Assert.assertTrue;
47 import static org.junit.Assert.fail;
48 import static org.mockito.ArgumentMatchers.anyInt;
49 import static org.mockito.ArgumentMatchers.argThat;
50 import static org.mockito.Matchers.any;
51 import static org.mockito.Matchers.anyBoolean;
52 import static org.mockito.Matchers.anyString;
53 import static org.mockito.Matchers.eq;
54 import static org.mockito.Mockito.doAnswer;
55 import static org.mockito.Mockito.doNothing;
56 import static org.mockito.Mockito.doReturn;
57 import static org.mockito.Mockito.doThrow;
58 import static org.mockito.Mockito.inOrder;
59 import static org.mockito.Mockito.mock;
60 import static org.mockito.Mockito.never;
61 import static org.mockito.Mockito.reset;
62 import static org.mockito.Mockito.timeout;
63 import static org.mockito.Mockito.times;
64 import static org.mockito.Mockito.verify;
65 import static org.mockito.Mockito.verifyNoMoreInteractions;
66 import static org.mockito.Mockito.when;
67 
68 import android.app.usage.NetworkStatsManager;
69 import android.net.INetd;
70 import android.net.InetAddresses;
71 import android.net.InterfaceConfigurationParcel;
72 import android.net.IpPrefix;
73 import android.net.LinkAddress;
74 import android.net.LinkProperties;
75 import android.net.MacAddress;
76 import android.net.RouteInfo;
77 import android.net.RoutingCoordinatorManager;
78 import android.net.dhcp.DhcpServerCallbacks;
79 import android.net.dhcp.DhcpServingParamsParcel;
80 import android.net.dhcp.IDhcpEventCallbacks;
81 import android.net.dhcp.IDhcpServer;
82 import android.net.dhcp.IDhcpServerCallbacks;
83 import android.net.ip.RouterAdvertisementDaemon.RaParams;
84 import android.os.Build;
85 import android.os.Handler;
86 import android.os.RemoteException;
87 import android.os.test.TestLooper;
88 import android.text.TextUtils;
89 
90 import androidx.test.filters.SmallTest;
91 import androidx.test.runner.AndroidJUnit4;
92 
93 import com.android.modules.utils.build.SdkLevel;
94 import com.android.net.module.util.InterfaceParams;
95 import com.android.net.module.util.SdkUtil.LateSdk;
96 import com.android.net.module.util.SharedLog;
97 import com.android.net.module.util.ip.IpNeighborMonitor;
98 import com.android.networkstack.tethering.BpfCoordinator;
99 import com.android.networkstack.tethering.PrivateAddressCoordinator;
100 import com.android.networkstack.tethering.TetheringConfiguration;
101 import com.android.networkstack.tethering.metrics.TetheringMetrics;
102 import com.android.networkstack.tethering.util.InterfaceSet;
103 import com.android.networkstack.tethering.util.PrefixUtils;
104 import com.android.testutils.DevSdkIgnoreRule;
105 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
106 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
107 
108 import org.junit.Before;
109 import org.junit.Rule;
110 import org.junit.Test;
111 import org.junit.runner.RunWith;
112 import org.mockito.ArgumentCaptor;
113 import org.mockito.Captor;
114 import org.mockito.InOrder;
115 import org.mockito.Mock;
116 import org.mockito.MockitoAnnotations;
117 
118 import java.net.Inet4Address;
119 import java.net.InetAddress;
120 import java.util.List;
121 import java.util.Set;
122 
123 @RunWith(AndroidJUnit4.class)
124 @SmallTest
125 public class IpServerTest {
126     @Rule
127     public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
128 
129     private static final String IFACE_NAME = "testnet1";
130     private static final String UPSTREAM_IFACE = "upstream0";
131     private static final String UPSTREAM_IFACE2 = "upstream1";
132     private static final String IPSEC_IFACE = "ipsec0";
133     private static final int NO_UPSTREAM = 0;
134     private static final int UPSTREAM_IFINDEX = 101;
135     private static final int UPSTREAM_IFINDEX2 = 102;
136     private static final int IPSEC_IFINDEX = 103;
137     private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
138     private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
139     private static final int DHCP_LEASE_TIME_SECS = 3600;
140     private static final boolean DEFAULT_USING_BPF_OFFLOAD = true;
141     private static final int DEFAULT_SUBNET_PREFIX_LENGTH = 0;
142     private static final int P2P_SUBNET_PREFIX_LENGTH = 25;
143 
144     private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
145             IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
146     private static final InterfaceParams UPSTREAM_IFACE_PARAMS = new InterfaceParams(
147             UPSTREAM_IFACE, UPSTREAM_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
148     private static final InterfaceParams UPSTREAM_IFACE_PARAMS2 = new InterfaceParams(
149             UPSTREAM_IFACE2, UPSTREAM_IFINDEX2, MacAddress.ALL_ZEROS_ADDRESS,
150             1500 /* defaultMtu */);
151     private static final InterfaceParams IPSEC_IFACE_PARAMS = new InterfaceParams(
152             IPSEC_IFACE, IPSEC_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
153 
154     private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000;
155 
156     private final LinkAddress mTestAddress = new LinkAddress("192.168.42.5/24");
157     private final IpPrefix mBluetoothPrefix = new IpPrefix("192.168.44.0/24");
158 
159     private static final Set<LinkAddress> NO_ADDRESSES = Set.of();
160     private static final Set<IpPrefix> NO_PREFIXES = Set.of();
161     private static final Set<LinkAddress> UPSTREAM_ADDRESSES =
162             Set.of(new LinkAddress("2001:db8:0:1234::168/64"));
163     private static final Set<IpPrefix> UPSTREAM_PREFIXES =
164             Set.of(new IpPrefix("2001:db8:0:1234::/64"));
165     private static final Set<LinkAddress> UPSTREAM_ADDRESSES2 = Set.of(
166             new LinkAddress("2001:db8:0:1234::168/64"),
167             new LinkAddress("2001:db8:0:abcd::168/64"));
168     private static final Set<IpPrefix> UPSTREAM_PREFIXES2 = Set.of(
169             new IpPrefix("2001:db8:0:1234::/64"), new IpPrefix("2001:db8:0:abcd::/64"));
170 
171     @Mock private INetd mNetd;
172     @Mock private IpServer.Callback mCallback;
173     @Mock private SharedLog mSharedLog;
174     @Mock private IDhcpServer mDhcpServer;
175     @Mock private DadProxy mDadProxy;
176     @Mock private RouterAdvertisementDaemon mRaDaemon;
177     @Mock private IpNeighborMonitor mIpNeighborMonitor;
178     @Mock private IpServer.Dependencies mDependencies;
179     @Mock private PrivateAddressCoordinator mAddressCoordinator;
180     private final LateSdk<RoutingCoordinatorManager> mRoutingCoordinatorManager =
181             new LateSdk<>(SdkLevel.isAtLeastS() ? mock(RoutingCoordinatorManager.class) : null);
182     @Mock private NetworkStatsManager mStatsManager;
183     @Mock private TetheringConfiguration mTetherConfig;
184     @Mock private TetheringMetrics mTetheringMetrics;
185     @Mock private BpfCoordinator mBpfCoordinator;
186 
187     @Captor private ArgumentCaptor<DhcpServingParamsParcel> mDhcpParamsCaptor;
188 
189     private TestLooper mLooper;
190     private Handler mHandler;
191     private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
192             ArgumentCaptor.forClass(LinkProperties.class);
193     private IpServer mIpServer;
194     private InterfaceConfigurationParcel mInterfaceConfiguration;
195 
initStateMachine(int interfaceType)196     private void initStateMachine(int interfaceType) throws Exception {
197         initStateMachine(interfaceType, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
198     }
199 
initStateMachine(int interfaceType, boolean usingLegacyDhcp, boolean usingBpfOffload)200     private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
201             boolean usingBpfOffload) throws Exception {
202         when(mDependencies.getDadProxy(any(), any())).thenReturn(mDadProxy);
203         when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
204         when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
205         when(mDependencies.getInterfaceParams(UPSTREAM_IFACE)).thenReturn(UPSTREAM_IFACE_PARAMS);
206         when(mDependencies.getInterfaceParams(UPSTREAM_IFACE2)).thenReturn(UPSTREAM_IFACE_PARAMS2);
207         when(mDependencies.getInterfaceParams(IPSEC_IFACE)).thenReturn(IPSEC_IFACE_PARAMS);
208 
209         mInterfaceConfiguration = new InterfaceConfigurationParcel();
210         mInterfaceConfiguration.flags = new String[0];
211         if (interfaceType == TETHERING_BLUETOOTH) {
212             mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR;
213             mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH;
214         }
215 
216         doReturn(mIpNeighborMonitor).when(mDependencies).getIpNeighborMonitor(any(), any(), any());
217 
218         when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(usingBpfOffload);
219         when(mTetherConfig.useLegacyDhcpServer()).thenReturn(usingLegacyDhcp);
220         when(mTetherConfig.getP2pLeasesSubnetPrefixLength()).thenReturn(P2P_SUBNET_PREFIX_LENGTH);
221         when(mBpfCoordinator.isUsingBpfOffload()).thenReturn(usingBpfOffload);
222         mIpServer = createIpServer(interfaceType);
223         verify(mIpNeighborMonitor).start();
224         mIpServer.start();
225 
226         // Starting the state machine always puts us in a consistent state and notifies
227         // the rest of the world that we've changed from an unknown to available state.
228         mLooper.dispatchAll();
229         reset(mNetd, mCallback, mIpNeighborMonitor);
230 
231         when(mRaDaemon.start()).thenReturn(true);
232     }
233 
initTetheredStateMachine(int interfaceType, String upstreamIface)234     private void initTetheredStateMachine(int interfaceType, String upstreamIface)
235             throws Exception {
236         initTetheredStateMachine(interfaceType, upstreamIface, NO_ADDRESSES, false,
237                 DEFAULT_USING_BPF_OFFLOAD);
238     }
239 
initTetheredStateMachine(int interfaceType, String upstreamIface, Set<LinkAddress> upstreamAddresses, boolean usingLegacyDhcp, boolean usingBpfOffload)240     private void initTetheredStateMachine(int interfaceType, String upstreamIface,
241             Set<LinkAddress> upstreamAddresses, boolean usingLegacyDhcp, boolean usingBpfOffload)
242             throws Exception {
243         initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload);
244         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
245         if (upstreamIface != null) {
246             InterfaceParams interfaceParams = mDependencies.getInterfaceParams(upstreamIface);
247             assertNotNull("missing upstream interface: " + upstreamIface, interfaceParams);
248             LinkProperties lp = new LinkProperties();
249             lp.setInterfaceName(upstreamIface);
250             lp.setLinkAddresses(upstreamAddresses);
251             dispatchTetherConnectionChanged(upstreamIface, lp, 0);
252             Set<IpPrefix> upstreamPrefixes = getTetherableIpv6Prefixes(lp.getLinkAddresses());
253             verify(mBpfCoordinator).updateAllIpv6Rules(
254                     mIpServer, TEST_IFACE_PARAMS, interfaceParams.index, upstreamPrefixes);
255         }
256         reset(mNetd, mBpfCoordinator, mCallback, mAddressCoordinator);
257         when(mAddressCoordinator.requestDownstreamAddress(any(), anyInt(),
258                 anyBoolean())).thenReturn(mTestAddress);
259     }
260 
261     @SuppressWarnings("DoNotCall") // Ignore warning for synchronous to call to Thread.run()
setUpDhcpServer()262     private void setUpDhcpServer() throws Exception {
263         doAnswer(inv -> {
264             final IDhcpServerCallbacks cb = inv.getArgument(2);
265             new Thread(() -> {
266                 try {
267                     cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
268                 } catch (RemoteException e) {
269                     fail(e.getMessage());
270                 }
271             }).run();
272             return null;
273         }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
274     }
275 
setUp()276     @Before public void setUp() throws Exception {
277         MockitoAnnotations.initMocks(this);
278         when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
279         when(mAddressCoordinator.requestDownstreamAddress(any(), anyInt(),
280                 anyBoolean())).thenReturn(mTestAddress);
281         when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(DEFAULT_USING_BPF_OFFLOAD);
282         when(mTetherConfig.useLegacyDhcpServer()).thenReturn(false /* default value */);
283 
284         // Simulate the behavior of RoutingCoordinator
285         if (null != mRoutingCoordinatorManager.value) {
286             doAnswer(it -> {
287                 final String fromIface = (String) it.getArguments()[0];
288                 final String toIface = (String) it.getArguments()[1];
289                 mNetd.tetherAddForward(fromIface, toIface);
290                 mNetd.ipfwdAddInterfaceForward(fromIface, toIface);
291                 return null;
292             }).when(mRoutingCoordinatorManager.value).addInterfaceForward(any(), any());
293             doAnswer(it -> {
294                 final String fromIface = (String) it.getArguments()[0];
295                 final String toIface = (String) it.getArguments()[1];
296                 mNetd.ipfwdRemoveInterfaceForward(fromIface, toIface);
297                 mNetd.tetherRemoveForward(fromIface, toIface);
298                 return null;
299             }).when(mRoutingCoordinatorManager.value).removeInterfaceForward(any(), any());
300         }
301 
302         setUpDhcpServer();
303     }
304 
305     // In order to interact with syncSM from the test, IpServer must be created in test thread.
createIpServer(final int interfaceType)306     private IpServer createIpServer(final int interfaceType) {
307         mLooper = new TestLooper();
308         mHandler = new Handler(mLooper.getLooper());
309         return new IpServer(IFACE_NAME, mHandler, interfaceType, mSharedLog, mNetd, mBpfCoordinator,
310                 mRoutingCoordinatorManager, mCallback, mTetherConfig, mAddressCoordinator,
311                 mTetheringMetrics, mDependencies);
312 
313     }
314 
315     @Test
startsOutAvailable()316     public void startsOutAvailable() throws Exception {
317         when(mDependencies.getIpNeighborMonitor(any(), any(), any()))
318                 .thenReturn(mIpNeighborMonitor);
319         mIpServer = createIpServer(TETHERING_BLUETOOTH);
320         mIpServer.start();
321         mLooper.dispatchAll();
322         verify(mCallback).updateInterfaceState(
323                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
324         verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
325         verifyNoMoreInteractions(mCallback, mNetd);
326     }
327 
328     @Test
shouldDoNothingUntilRequested()329     public void shouldDoNothingUntilRequested() throws Exception {
330         initStateMachine(TETHERING_BLUETOOTH);
331         final int [] noOp_commands = {
332             IpServer.CMD_TETHER_UNREQUESTED,
333             IpServer.CMD_IP_FORWARDING_ENABLE_ERROR,
334             IpServer.CMD_IP_FORWARDING_DISABLE_ERROR,
335             IpServer.CMD_START_TETHERING_ERROR,
336             IpServer.CMD_STOP_TETHERING_ERROR,
337             IpServer.CMD_SET_DNS_FORWARDERS_ERROR,
338             IpServer.CMD_TETHER_CONNECTION_CHANGED
339         };
340         for (int command : noOp_commands) {
341             // None of these commands should trigger us to request action from
342             // the rest of the system.
343             dispatchCommand(command);
344             verifyNoMoreInteractions(mNetd, mCallback);
345         }
346     }
347 
348     @Test
handlesImmediateInterfaceDown()349     public void handlesImmediateInterfaceDown() throws Exception {
350         initStateMachine(TETHERING_BLUETOOTH);
351 
352         dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
353         verify(mCallback).updateInterfaceState(
354                 mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
355         verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
356         verifyNoMoreInteractions(mNetd, mCallback);
357     }
358 
359     @Test
canBeTetheredAsBluetooth()360     public void canBeTetheredAsBluetooth() throws Exception {
361         initStateMachine(TETHERING_BLUETOOTH);
362 
363         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
364         InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
365         if (isAtLeastT()) {
366             inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(),
367                     eq(CONNECTIVITY_SCOPE_GLOBAL), eq(true));
368             inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
369                     IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
370         }
371         inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
372         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
373         // One for ipv4 route, one for ipv6 link local route.
374         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
375                 any(), any());
376         inOrder.verify(mCallback).updateInterfaceState(
377                 mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
378         inOrder.verify(mCallback).updateLinkProperties(
379                 eq(mIpServer), any(LinkProperties.class));
380         verifyNoMoreInteractions(mNetd, mCallback);
381     }
382 
383     @Test
canUnrequestTethering()384     public void canUnrequestTethering() throws Exception {
385         initTetheredStateMachine(TETHERING_BLUETOOTH, null);
386 
387         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
388         InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
389         inOrder.verify(mNetd).tetherApplyDnsInterfaces();
390         inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
391         inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
392         // One is ipv4 address clear (set to 0.0.0.0), another is set interface down which only
393         // happen after T. Before T, the interface configuration control in bluetooth side.
394         if (isAtLeastT()) {
395             inOrder.verify(mNetd).interfaceSetCfg(
396                     argThat(cfg -> assertContainsFlag(cfg.flags, IF_STATE_DOWN)));
397         }
398         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> cfg.flags.length == 0));
399         inOrder.verify(mAddressCoordinator).releaseDownstream(any());
400         inOrder.verify(mCallback).updateInterfaceState(
401                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
402         inOrder.verify(mCallback).updateLinkProperties(
403                 eq(mIpServer), any(LinkProperties.class));
404         verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_BLUETOOTH),
405                 eq(TETHER_ERROR_NO_ERROR));
406         verify(mTetheringMetrics).sendReport(eq(TETHERING_BLUETOOTH));
407         verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
408     }
409 
410     @Test
canBeTetheredAsUsb()411     public void canBeTetheredAsUsb() throws Exception {
412         initStateMachine(TETHERING_USB);
413 
414         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
415         InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
416         inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(),
417                 eq(CONNECTIVITY_SCOPE_GLOBAL), eq(true));
418         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
419                 IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
420         inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
421         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
422         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
423                 any(), any());
424         inOrder.verify(mCallback).updateInterfaceState(
425                 mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
426         inOrder.verify(mCallback).updateLinkProperties(
427                 eq(mIpServer), mLinkPropertiesCaptor.capture());
428         assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
429         verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
430     }
431 
432     @Test
canBeTetheredAsWifiP2p()433     public void canBeTetheredAsWifiP2p() throws Exception {
434         initStateMachine(TETHERING_WIFI_P2P);
435 
436         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
437         InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
438         inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(),
439                 eq(CONNECTIVITY_SCOPE_LOCAL), eq(true));
440         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
441                   IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP)));
442         inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
443         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
444         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
445                 any(), any());
446         inOrder.verify(mCallback).updateInterfaceState(
447                 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
448         inOrder.verify(mCallback).updateLinkProperties(
449                 eq(mIpServer), mLinkPropertiesCaptor.capture());
450         assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
451         verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
452     }
453 
454     @Test
handlesFirstUpstreamChange()455     public void handlesFirstUpstreamChange() throws Exception {
456         initTetheredStateMachine(TETHERING_BLUETOOTH, null);
457 
458         // Telling the state machine about its upstream interface triggers
459         // a little more configuration.
460         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
461         InOrder inOrder = inOrder(mNetd, mBpfCoordinator);
462 
463         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
464         inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX,
465                 UPSTREAM_IFACE);
466         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE);
467         inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
468         inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
469 
470         verifyNoMoreInteractions(mNetd, mCallback, mBpfCoordinator);
471     }
472 
473     @Test
handlesChangingUpstream()474     public void handlesChangingUpstream() throws Exception {
475         initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
476 
477         dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
478         InOrder inOrder = inOrder(mNetd, mBpfCoordinator);
479 
480         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
481         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
482         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
483         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
484 
485         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2>.
486         inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX2,
487                 UPSTREAM_IFACE2);
488         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
489         inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
490         inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
491 
492         verifyNoMoreInteractions(mNetd, mCallback, mBpfCoordinator);
493     }
494 
495     @Test
handlesChangingUpstreamNatFailure()496     public void handlesChangingUpstreamNatFailure() throws Exception {
497         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
498 
499         doThrow(RemoteException.class).when(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
500 
501         dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
502         InOrder inOrder = inOrder(mNetd, mBpfCoordinator);
503 
504         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
505         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
506         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
507         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
508 
509         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on
510         // tetherAddForward.
511         inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX2,
512                 UPSTREAM_IFACE2);
513         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
514         inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
515 
516         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> to fallback.
517         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE2);
518         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
519         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
520     }
521 
522     @Test
handlesChangingUpstreamInterfaceForwardingFailure()523     public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception {
524         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
525 
526         doThrow(RemoteException.class).when(mNetd).ipfwdAddInterfaceForward(
527                 IFACE_NAME, UPSTREAM_IFACE2);
528 
529         dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
530         InOrder inOrder = inOrder(mNetd, mBpfCoordinator);
531 
532         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
533         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
534         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
535         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
536 
537         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on
538         // ipfwdAddInterfaceForward.
539         inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX2,
540                 UPSTREAM_IFACE2);
541         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
542         inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
543         inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
544 
545         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> to fallback.
546         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE2);
547         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
548         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
549     }
550 
551     @Test
canUnrequestTetheringWithUpstream()552     public void canUnrequestTetheringWithUpstream() throws Exception {
553         initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
554 
555         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
556         InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator, mBpfCoordinator);
557         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
558         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
559         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
560         inOrder.verify(mBpfCoordinator).updateAllIpv6Rules(
561                 mIpServer, TEST_IFACE_PARAMS, NO_UPSTREAM, NO_PREFIXES);
562         // When tethering stops, upstream interface is set to zero and thus clearing all upstream
563         // rules. Downstream rules are needed to be cleared explicitly by calling
564         // BpfCoordinator#clearAllIpv6Rules in TetheredState#exit.
565         inOrder.verify(mBpfCoordinator).clearAllIpv6Rules(mIpServer);
566         inOrder.verify(mNetd).tetherApplyDnsInterfaces();
567         inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
568         inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
569         inOrder.verify(mNetd, times(isAtLeastT() ? 2 : 1)).interfaceSetCfg(
570                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
571         inOrder.verify(mAddressCoordinator).releaseDownstream(any());
572         inOrder.verify(mBpfCoordinator).tetherOffloadClientClear(mIpServer);
573         inOrder.verify(mBpfCoordinator).stopMonitoring(mIpServer);
574         inOrder.verify(mCallback).updateInterfaceState(
575                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
576         inOrder.verify(mCallback).updateLinkProperties(
577                 eq(mIpServer), any(LinkProperties.class));
578         verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator, mBpfCoordinator);
579     }
580 
581     @Test
interfaceDownLeadsToUnavailable()582     public void interfaceDownLeadsToUnavailable() throws Exception {
583         for (boolean shouldThrow : new boolean[]{true, false}) {
584             initTetheredStateMachine(TETHERING_USB, null);
585 
586             if (shouldThrow) {
587                 doThrow(RemoteException.class).when(mNetd).tetherInterfaceRemove(IFACE_NAME);
588             }
589             dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
590             InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
591             // Currently IpServer interfaceSetCfg twice to stop IPv4. One just set interface down
592             // Another one is set IPv4 to 0.0.0.0/0 as clearng ipv4 address.
593             usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
594                     argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
595             usbTeardownOrder.verify(mCallback).updateInterfaceState(
596                     mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
597             usbTeardownOrder.verify(mCallback).updateLinkProperties(
598                     eq(mIpServer), mLinkPropertiesCaptor.capture());
599             assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
600         }
601     }
602 
603     @Test
usbShouldBeTornDownOnTetherError()604     public void usbShouldBeTornDownOnTetherError() throws Exception {
605         initStateMachine(TETHERING_USB);
606 
607         doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME);
608         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
609         InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
610         usbTeardownOrder.verify(mNetd).interfaceSetCfg(
611                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
612         usbTeardownOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
613 
614         usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
615                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
616         usbTeardownOrder.verify(mCallback).updateInterfaceState(
617                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
618         usbTeardownOrder.verify(mCallback).updateLinkProperties(
619                 eq(mIpServer), mLinkPropertiesCaptor.capture());
620         assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
621         verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_USB),
622                 eq(TETHER_ERROR_TETHER_IFACE_ERROR));
623         verify(mTetheringMetrics).sendReport(eq(TETHERING_USB));
624     }
625 
626     @Test
shouldTearDownUsbOnUpstreamError()627     public void shouldTearDownUsbOnUpstreamError() throws Exception {
628         initTetheredStateMachine(TETHERING_USB, null);
629 
630         doThrow(RemoteException.class).when(mNetd).tetherAddForward(anyString(), anyString());
631         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
632         InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
633         usbTeardownOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
634 
635         usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
636                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
637         usbTeardownOrder.verify(mCallback).updateInterfaceState(
638                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_FORWARDING_ERROR);
639         usbTeardownOrder.verify(mCallback).updateLinkProperties(
640                 eq(mIpServer), mLinkPropertiesCaptor.capture());
641         assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
642         verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_USB),
643                 eq(TETHER_ERROR_ENABLE_FORWARDING_ERROR));
644         verify(mTetheringMetrics).sendReport(eq(TETHERING_USB));
645     }
646 
647     @Test
ignoresDuplicateUpstreamNotifications()648     public void ignoresDuplicateUpstreamNotifications() throws Exception {
649         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
650 
651         verifyNoMoreInteractions(mNetd, mCallback);
652 
653         for (int i = 0; i < 5; i++) {
654             dispatchTetherConnectionChanged(UPSTREAM_IFACE);
655             verifyNoMoreInteractions(mNetd, mCallback);
656         }
657     }
658 
659     @Test
startsDhcpServer()660     public void startsDhcpServer() throws Exception {
661         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
662         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
663 
664         assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress));
665     }
666 
667     @Test
startsDhcpServerOnBluetooth()668     public void startsDhcpServerOnBluetooth() throws Exception {
669         initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
670         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
671 
672         if (isAtLeastT()) {
673             assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress));
674         } else {
675             assertDhcpStarted(mBluetoothPrefix);
676         }
677     }
678 
679     @Test
startsDhcpServerOnWifiP2p()680     public void startsDhcpServerOnWifiP2p() throws Exception {
681         initTetheredStateMachine(TETHERING_WIFI_P2P, UPSTREAM_IFACE);
682         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
683 
684         assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress));
685     }
686 
687     @Test
startsDhcpServerOnNcm()688     public void startsDhcpServerOnNcm() throws Exception {
689         initStateMachine(TETHERING_NCM);
690         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
691         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
692 
693         assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
694     }
695 
696     @Test
testOnNewPrefixRequest()697     public void testOnNewPrefixRequest() throws Exception {
698         initStateMachine(TETHERING_NCM);
699         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
700 
701         final IDhcpEventCallbacks eventCallbacks;
702         final ArgumentCaptor<IDhcpEventCallbacks> dhcpEventCbsCaptor =
703                  ArgumentCaptor.forClass(IDhcpEventCallbacks.class);
704         verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
705                 any(), dhcpEventCbsCaptor.capture());
706         eventCallbacks = dhcpEventCbsCaptor.getValue();
707         assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
708 
709         final ArgumentCaptor<LinkProperties> lpCaptor =
710                 ArgumentCaptor.forClass(LinkProperties.class);
711         InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator);
712         inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(),
713                 eq(CONNECTIVITY_SCOPE_LOCAL), eq(true));
714         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
715         // One for ipv4 route, one for ipv6 link local route.
716         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
717                 any(), any());
718         inOrder.verify(mCallback).updateInterfaceState(
719                 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
720         inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
721         verifyNoMoreInteractions(mCallback, mAddressCoordinator);
722 
723         // Simulate the DHCP server receives DHCPDECLINE on MirrorLink and then signals
724         // onNewPrefixRequest callback.
725         final LinkAddress newAddress = new LinkAddress("192.168.100.125/24");
726         when(mAddressCoordinator.requestDownstreamAddress(any(), anyInt(),
727                 anyBoolean())).thenReturn(newAddress);
728         eventCallbacks.onNewPrefixRequest(new IpPrefix("192.168.42.0/24"));
729         mLooper.dispatchAll();
730 
731         inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(),
732                 eq(CONNECTIVITY_SCOPE_LOCAL), eq(false));
733         inOrder.verify(mNetd).tetherApplyDnsInterfaces();
734         inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
735         verifyNoMoreInteractions(mCallback);
736 
737         final LinkProperties linkProperties = lpCaptor.getValue();
738         final List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses();
739         assertEquals(1, linkProperties.getLinkAddresses().size());
740         assertEquals(1, linkProperties.getRoutes().size());
741         final IpPrefix prefix = new IpPrefix(linkAddresses.get(0).getAddress(),
742                 linkAddresses.get(0).getPrefixLength());
743         assertNotEquals(prefix, new IpPrefix("192.168.42.0/24"));
744 
745         verify(mDhcpServer).updateParams(mDhcpParamsCaptor.capture(), any());
746         assertDhcpServingParams(mDhcpParamsCaptor.getValue(), prefix);
747     }
748 
749     @Test
doesNotStartDhcpServerIfDisabled()750     public void doesNotStartDhcpServerIfDisabled() throws Exception {
751         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, NO_ADDRESSES,
752                 true /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
753         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
754 
755         verify(mDependencies, never()).makeDhcpServer(any(), any(), any());
756     }
757 
758     @Test
ipv6UpstreamInterfaceChanges()759     public void ipv6UpstreamInterfaceChanges() throws Exception {
760         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, UPSTREAM_ADDRESSES,
761                 false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
762 
763         // Upstream interface changes result in updating the rules.
764         LinkProperties lp = new LinkProperties();
765         lp.setInterfaceName(UPSTREAM_IFACE2);
766         lp.setLinkAddresses(UPSTREAM_ADDRESSES);
767         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1);
768         verify(mBpfCoordinator).updateAllIpv6Rules(
769                 mIpServer, TEST_IFACE_PARAMS, UPSTREAM_IFINDEX2, UPSTREAM_PREFIXES);
770         reset(mBpfCoordinator);
771 
772         // Upstream link addresses change result in updating the rules.
773         LinkProperties lp2 = new LinkProperties();
774         lp2.setInterfaceName(UPSTREAM_IFACE2);
775         lp2.setLinkAddresses(UPSTREAM_ADDRESSES2);
776         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp2, -1);
777         verify(mBpfCoordinator).updateAllIpv6Rules(
778                 mIpServer, TEST_IFACE_PARAMS, UPSTREAM_IFINDEX2, UPSTREAM_PREFIXES2);
779         reset(mBpfCoordinator);
780 
781         // When the upstream is lost, rules are removed.
782         dispatchTetherConnectionChanged(null, null, 0);
783         // Upstream clear function is called two times by:
784         // - processMessage CMD_TETHER_CONNECTION_CHANGED for the upstream is lost.
785         // - processMessage CMD_IPV6_TETHER_UPDATE for the IPv6 upstream is lost.
786         // See dispatchTetherConnectionChanged.
787         verify(mBpfCoordinator, times(2)).updateAllIpv6Rules(
788                 mIpServer, TEST_IFACE_PARAMS, NO_UPSTREAM, NO_PREFIXES);
789         reset(mBpfCoordinator);
790 
791         // If the upstream is IPv4-only, no rules are added.
792         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
793         verify(mBpfCoordinator, never()).updateAllIpv6Rules(
794                 mIpServer, TEST_IFACE_PARAMS, NO_UPSTREAM, NO_PREFIXES);
795         reset(mBpfCoordinator);
796 
797         // Rules are added again once upstream IPv6 connectivity is available.
798         lp.setInterfaceName(UPSTREAM_IFACE);
799         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
800         verify(mBpfCoordinator).updateAllIpv6Rules(
801                 mIpServer, TEST_IFACE_PARAMS, UPSTREAM_IFINDEX, UPSTREAM_PREFIXES);
802         reset(mBpfCoordinator);
803 
804         // If upstream IPv6 connectivity is lost, rules are removed.
805         dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
806         verify(mBpfCoordinator).updateAllIpv6Rules(
807                 mIpServer, TEST_IFACE_PARAMS, NO_UPSTREAM, NO_PREFIXES);
808         reset(mBpfCoordinator);
809 
810         // When upstream IPv6 connectivity comes back, rules are added.
811         lp.setInterfaceName(UPSTREAM_IFACE);
812         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
813         verify(mBpfCoordinator).updateAllIpv6Rules(
814                 mIpServer, TEST_IFACE_PARAMS, UPSTREAM_IFINDEX, UPSTREAM_PREFIXES);
815         reset(mBpfCoordinator);
816 
817         // When the downstream interface goes down, rules are removed.
818         mIpServer.stop();
819         mLooper.dispatchAll();
820         verify(mBpfCoordinator).clearAllIpv6Rules(mIpServer);
821         verify(mBpfCoordinator).updateAllIpv6Rules(
822                 mIpServer, TEST_IFACE_PARAMS, NO_UPSTREAM, NO_PREFIXES);
823         reset(mBpfCoordinator);
824     }
825 
826     @Test
stopNeighborMonitoringWhenInterfaceDown()827     public void stopNeighborMonitoringWhenInterfaceDown() throws Exception {
828         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, UPSTREAM_ADDRESSES,
829                 false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
830 
831         mIpServer.stop();
832         mLooper.dispatchAll();
833         verify(mIpNeighborMonitor).stop();
834     }
835 
buildIpv6OnlyLinkProperties(final String iface)836     private LinkProperties buildIpv6OnlyLinkProperties(final String iface) {
837         final LinkProperties linkProp = new LinkProperties();
838         linkProp.setInterfaceName(iface);
839         linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
840         linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST));
841         final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888");
842         linkProp.addDnsServer(dns);
843 
844         return linkProp;
845     }
846 
847     @Test
testAdjustTtlValue()848     public void testAdjustTtlValue() throws Exception {
849         final ArgumentCaptor<RaParams> raParamsCaptor =
850                 ArgumentCaptor.forClass(RaParams.class);
851         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
852         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
853         final RaParams noV6Params = raParamsCaptor.getValue();
854         assertEquals(65, noV6Params.hopLimit);
855         reset(mRaDaemon);
856 
857         when(mNetd.getProcSysNet(
858                 INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64");
859         final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE);
860         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1);
861         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
862         final RaParams nonCellularParams = raParamsCaptor.getValue();
863         assertEquals(65, nonCellularParams.hopLimit);
864         reset(mRaDaemon);
865 
866         dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
867         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
868         final RaParams noUpstream = raParamsCaptor.getValue();
869         assertEquals(65, nonCellularParams.hopLimit);
870         reset(mRaDaemon);
871 
872         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
873         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
874         final RaParams cellularParams = raParamsCaptor.getValue();
875         assertEquals(63, cellularParams.hopLimit);
876         reset(mRaDaemon);
877     }
878 
879     @Test
testStopObsoleteDhcpServer()880     public void testStopObsoleteDhcpServer() throws Exception {
881         final ArgumentCaptor<DhcpServerCallbacks> cbCaptor =
882                 ArgumentCaptor.forClass(DhcpServerCallbacks.class);
883         doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(),
884                 cbCaptor.capture());
885         initStateMachine(TETHERING_WIFI);
886         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
887         verify(mDhcpServer, never()).startWithCallbacks(any(), any());
888 
889         // No stop dhcp server because dhcp server is not created yet.
890         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
891         verify(mDhcpServer, never()).stop(any());
892 
893         // Stop obsolete dhcp server.
894         try {
895             final DhcpServerCallbacks cb = cbCaptor.getValue();
896             cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
897             mLooper.dispatchAll();
898         } catch (RemoteException e) {
899             fail(e.getMessage());
900         }
901         verify(mDhcpServer).stop(any());
902     }
903 
assertDhcpServingParams(final DhcpServingParamsParcel params, final IpPrefix prefix)904     private void assertDhcpServingParams(final DhcpServingParamsParcel params,
905             final IpPrefix prefix) {
906         // Last address byte is random
907         assertTrue(prefix.contains(intToInet4AddressHTH(params.serverAddr)));
908         assertEquals(prefix.getPrefixLength(), params.serverAddrPrefixLength);
909         assertEquals(1, params.defaultRouters.length);
910         assertEquals(params.serverAddr, params.defaultRouters[0]);
911         assertEquals(1, params.dnsServers.length);
912         assertEquals(params.serverAddr, params.dnsServers[0]);
913         assertEquals(DHCP_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs);
914         if (mIpServer.interfaceType() == TETHERING_NCM) {
915             assertTrue(params.changePrefixOnDecline);
916         }
917 
918         if (mIpServer.interfaceType() == TETHERING_WIFI_P2P) {
919             assertEquals(P2P_SUBNET_PREFIX_LENGTH, params.leasesSubnetPrefixLength);
920         } else {
921             assertEquals(DEFAULT_SUBNET_PREFIX_LENGTH, params.leasesSubnetPrefixLength);
922         }
923     }
924 
assertDhcpStarted(IpPrefix expectedPrefix)925     private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {
926         verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any());
927         verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
928                 any(), any());
929         assertDhcpServingParams(mDhcpParamsCaptor.getValue(), expectedPrefix);
930     }
931 
932     /**
933      * Send a command to the state machine under test, and run the event loop to idle.
934      *
935      * @param command One of the IpServer.CMD_* constants.
936      * @param arg1 An additional argument to pass.
937      */
dispatchCommand(int command, int arg1)938     private void dispatchCommand(int command, int arg1) {
939         mIpServer.sendMessage(command, arg1);
940         mLooper.dispatchAll();
941     }
942 
943     /**
944      * Send a command to the state machine under test, and run the event loop to idle.
945      *
946      * @param command One of the IpServer.CMD_* constants.
947      */
dispatchCommand(int command)948     private void dispatchCommand(int command) {
949         mIpServer.sendMessage(command);
950         mLooper.dispatchAll();
951     }
952 
953     /**
954      * Special override to tell the state machine that the upstream interface has changed.
955      *
956      * @see #dispatchCommand(int)
957      * @param upstreamIface String name of upstream interface (or null)
958      * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream.
959      */
dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, int ttlAdjustment)960     private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp,
961             int ttlAdjustment) {
962         dispatchTetherConnectionChanged(upstreamIface);
963         mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp);
964         mLooper.dispatchAll();
965     }
966 
dispatchTetherConnectionChanged(String upstreamIface)967     private void dispatchTetherConnectionChanged(String upstreamIface) {
968         final InterfaceSet ifs = (upstreamIface != null) ? new InterfaceSet(upstreamIface) : null;
969         mIpServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifs);
970         mLooper.dispatchAll();
971     }
972 
assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp)973     private void assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp) {
974         // Find the first IPv4 LinkAddress.
975         LinkAddress addr4 = null;
976         for (LinkAddress addr : lp.getLinkAddresses()) {
977             if (!(addr.getAddress() instanceof Inet4Address)) continue;
978             addr4 = addr;
979             break;
980         }
981         assertNotNull("missing IPv4 address", addr4);
982 
983         final IpPrefix destination = new IpPrefix(addr4.getAddress(), addr4.getPrefixLength());
984         // Assert the presence of the associated directly connected route.
985         final RouteInfo directlyConnected = new RouteInfo(destination, null, lp.getInterfaceName(),
986                 RouteInfo.RTN_UNICAST);
987         assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'",
988                    lp.getRoutes().contains(directlyConnected));
989     }
990 
assertNoAddressesNorRoutes(LinkProperties lp)991     private void assertNoAddressesNorRoutes(LinkProperties lp) {
992         assertTrue(lp.getLinkAddresses().isEmpty());
993         assertTrue(lp.getRoutes().isEmpty());
994         // We also check that interface name is non-empty, because we should
995         // never see an empty interface name in any LinkProperties update.
996         assertFalse(TextUtils.isEmpty(lp.getInterfaceName()));
997     }
998 
assertContainsFlag(String[] flags, String match)999     private boolean assertContainsFlag(String[] flags, String match) {
1000         for (String flag : flags) {
1001             if (flag.equals(match)) return true;
1002         }
1003         return false;
1004     }
1005 
assertNotContainsFlag(String[] flags, String match)1006     private boolean assertNotContainsFlag(String[] flags, String match) {
1007         for (String flag : flags) {
1008             if (flag.equals(match)) {
1009                 fail("Unexpected flag: " + match);
1010                 return false;
1011             }
1012         }
1013         return true;
1014     }
1015 
1016     @Test @IgnoreUpTo(Build.VERSION_CODES.R)
dadProxyUpdates()1017     public void dadProxyUpdates() throws Exception {
1018         InOrder inOrder = inOrder(mDadProxy);
1019         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
1020         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1021 
1022         // Add an upstream without IPv6.
1023         dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
1024         inOrder.verify(mDadProxy).setUpstreamIface(null);
1025 
1026         // Add IPv6 to the upstream.
1027         LinkProperties lp = new LinkProperties();
1028         lp.setInterfaceName(UPSTREAM_IFACE);
1029         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
1030         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1031 
1032         // Change upstream.
1033         // New linkproperties is needed, otherwise changing the iface has no impact.
1034         LinkProperties lp2 = new LinkProperties();
1035         lp2.setInterfaceName(UPSTREAM_IFACE2);
1036         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp2, 0);
1037         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS2);
1038 
1039         // Lose IPv6 on the upstream...
1040         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, null, 0);
1041         inOrder.verify(mDadProxy).setUpstreamIface(null);
1042 
1043         // ... and regain it on a different upstream.
1044         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
1045         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1046 
1047         // Lose upstream.
1048         dispatchTetherConnectionChanged(null, null, 0);
1049         inOrder.verify(mDadProxy).setUpstreamIface(null);
1050 
1051         // Regain upstream.
1052         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
1053         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1054 
1055         // Stop tethering.
1056         mIpServer.stop();
1057         mLooper.dispatchAll();
1058     }
1059 
checkDadProxyEnabled(boolean expectEnabled)1060     private void checkDadProxyEnabled(boolean expectEnabled) throws Exception {
1061         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
1062         InOrder inOrder = inOrder(mDadProxy);
1063         // Add IPv6 to the upstream.
1064         LinkProperties lp = new LinkProperties();
1065         lp.setInterfaceName(UPSTREAM_IFACE);
1066         if (expectEnabled) {
1067             inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1068         } else {
1069             inOrder.verifyNoMoreInteractions();
1070         }
1071         // Stop tethering.
1072         mIpServer.stop();
1073         mLooper.dispatchAll();
1074         if (expectEnabled) {
1075             inOrder.verify(mDadProxy).stop();
1076         }
1077         else {
1078             verify(mDependencies, never()).getDadProxy(any(), any());
1079         }
1080     }
1081     @Test @IgnoreAfter(Build.VERSION_CODES.R)
testDadProxyUpdates_DisabledUpToR()1082     public void testDadProxyUpdates_DisabledUpToR() throws Exception {
1083         checkDadProxyEnabled(false);
1084     }
1085     @Test @IgnoreUpTo(Build.VERSION_CODES.R)
testDadProxyUpdates_EnabledAfterR()1086     public void testDadProxyUpdates_EnabledAfterR() throws Exception {
1087         checkDadProxyEnabled(true);
1088     }
1089 }
1090