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_UP;
20 import static android.net.RouteInfo.RTN_UNICAST;
21 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
22 import static android.net.TetheringManager.TETHERING_NCM;
23 import static android.net.TetheringManager.TETHERING_USB;
24 import static android.net.TetheringManager.TETHERING_WIFI;
25 import static android.net.TetheringManager.TETHERING_WIFI_P2P;
26 import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
27 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
28 import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
29 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
30 import static android.net.ip.IpServer.STATE_AVAILABLE;
31 import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
32 import static android.net.ip.IpServer.STATE_TETHERED;
33 import static android.net.ip.IpServer.STATE_UNAVAILABLE;
34 import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
35 import static android.net.netlink.NetlinkConstants.RTM_NEWNEIGH;
36 import static android.net.netlink.StructNdMsg.NUD_FAILED;
37 import static android.net.netlink.StructNdMsg.NUD_REACHABLE;
38 import static android.net.netlink.StructNdMsg.NUD_STALE;
39 import static android.system.OsConstants.ETH_P_IPV6;
40 
41 import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
42 
43 import static org.junit.Assert.assertEquals;
44 import static org.junit.Assert.assertFalse;
45 import static org.junit.Assert.assertNotEquals;
46 import static org.junit.Assert.assertNotNull;
47 import static org.junit.Assert.assertTrue;
48 import static org.junit.Assert.fail;
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.never;
60 import static org.mockito.Mockito.reset;
61 import static org.mockito.Mockito.spy;
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.TetherOffloadRuleParcel;
78 import android.net.TetherStatsParcel;
79 import android.net.dhcp.DhcpServerCallbacks;
80 import android.net.dhcp.DhcpServingParamsParcel;
81 import android.net.dhcp.IDhcpEventCallbacks;
82 import android.net.dhcp.IDhcpServer;
83 import android.net.dhcp.IDhcpServerCallbacks;
84 import android.net.ip.IpNeighborMonitor.NeighborEvent;
85 import android.net.ip.IpNeighborMonitor.NeighborEventConsumer;
86 import android.net.ip.RouterAdvertisementDaemon.RaParams;
87 import android.net.util.InterfaceParams;
88 import android.net.util.InterfaceSet;
89 import android.net.util.PrefixUtils;
90 import android.net.util.SharedLog;
91 import android.os.Build;
92 import android.os.Handler;
93 import android.os.RemoteException;
94 import android.os.test.TestLooper;
95 import android.text.TextUtils;
96 
97 import androidx.annotation.NonNull;
98 import androidx.annotation.Nullable;
99 import androidx.test.filters.SmallTest;
100 import androidx.test.runner.AndroidJUnit4;
101 
102 import com.android.net.module.util.NetworkStackConstants;
103 import com.android.networkstack.tethering.BpfCoordinator;
104 import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
105 import com.android.networkstack.tethering.BpfMap;
106 import com.android.networkstack.tethering.PrivateAddressCoordinator;
107 import com.android.networkstack.tethering.Tether4Key;
108 import com.android.networkstack.tethering.Tether4Value;
109 import com.android.networkstack.tethering.Tether6Value;
110 import com.android.networkstack.tethering.TetherDevKey;
111 import com.android.networkstack.tethering.TetherDevValue;
112 import com.android.networkstack.tethering.TetherDownstream6Key;
113 import com.android.networkstack.tethering.TetherLimitKey;
114 import com.android.networkstack.tethering.TetherLimitValue;
115 import com.android.networkstack.tethering.TetherStatsKey;
116 import com.android.networkstack.tethering.TetherStatsValue;
117 import com.android.networkstack.tethering.TetherUpstream6Key;
118 import com.android.networkstack.tethering.TetheringConfiguration;
119 import com.android.testutils.DevSdkIgnoreRule;
120 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
121 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
122 
123 import org.junit.Before;
124 import org.junit.Rule;
125 import org.junit.Test;
126 import org.junit.runner.RunWith;
127 import org.mockito.ArgumentCaptor;
128 import org.mockito.ArgumentMatcher;
129 import org.mockito.Captor;
130 import org.mockito.InOrder;
131 import org.mockito.Mock;
132 import org.mockito.MockitoAnnotations;
133 
134 import java.net.Inet4Address;
135 import java.net.Inet6Address;
136 import java.net.InetAddress;
137 import java.util.Arrays;
138 import java.util.List;
139 
140 @RunWith(AndroidJUnit4.class)
141 @SmallTest
142 public class IpServerTest {
143     @Rule
144     public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
145 
146     private static final String IFACE_NAME = "testnet1";
147     private static final String UPSTREAM_IFACE = "upstream0";
148     private static final String UPSTREAM_IFACE2 = "upstream1";
149     private static final String IPSEC_IFACE = "ipsec0";
150     private static final int UPSTREAM_IFINDEX = 101;
151     private static final int UPSTREAM_IFINDEX2 = 102;
152     private static final int IPSEC_IFINDEX = 103;
153     private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
154     private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
155     private static final int DHCP_LEASE_TIME_SECS = 3600;
156     private static final boolean DEFAULT_USING_BPF_OFFLOAD = true;
157 
158     private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
159             IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
160     private static final InterfaceParams UPSTREAM_IFACE_PARAMS = new InterfaceParams(
161             UPSTREAM_IFACE, UPSTREAM_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
162     private static final InterfaceParams UPSTREAM_IFACE_PARAMS2 = new InterfaceParams(
163             UPSTREAM_IFACE2, UPSTREAM_IFINDEX2, MacAddress.ALL_ZEROS_ADDRESS,
164             1500 /* defaultMtu */);
165     private static final InterfaceParams IPSEC_IFACE_PARAMS = new InterfaceParams(
166             IPSEC_IFACE, IPSEC_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
167 
168     private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000;
169 
170     private final LinkAddress mTestAddress = new LinkAddress("192.168.42.5/24");
171     private final IpPrefix mBluetoothPrefix = new IpPrefix("192.168.44.0/24");
172 
173     @Mock private INetd mNetd;
174     @Mock private IpServer.Callback mCallback;
175     @Mock private SharedLog mSharedLog;
176     @Mock private IDhcpServer mDhcpServer;
177     @Mock private DadProxy mDadProxy;
178     @Mock private RouterAdvertisementDaemon mRaDaemon;
179     @Mock private IpNeighborMonitor mIpNeighborMonitor;
180     @Mock private IpServer.Dependencies mDependencies;
181     @Mock private PrivateAddressCoordinator mAddressCoordinator;
182     @Mock private NetworkStatsManager mStatsManager;
183     @Mock private TetheringConfiguration mTetherConfig;
184     @Mock private ConntrackMonitor mConntrackMonitor;
185     @Mock private BpfMap<Tether4Key, Tether4Value> mBpfDownstream4Map;
186     @Mock private BpfMap<Tether4Key, Tether4Value> mBpfUpstream4Map;
187     @Mock private BpfMap<TetherDownstream6Key, Tether6Value> mBpfDownstream6Map;
188     @Mock private BpfMap<TetherUpstream6Key, Tether6Value> mBpfUpstream6Map;
189     @Mock private BpfMap<TetherStatsKey, TetherStatsValue> mBpfStatsMap;
190     @Mock private BpfMap<TetherLimitKey, TetherLimitValue> mBpfLimitMap;
191     @Mock private BpfMap<TetherDevKey, TetherDevValue> mBpfDevMap;
192 
193     @Captor private ArgumentCaptor<DhcpServingParamsParcel> mDhcpParamsCaptor;
194 
195     private final TestLooper mLooper = new TestLooper();
196     private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
197             ArgumentCaptor.forClass(LinkProperties.class);
198     private IpServer mIpServer;
199     private InterfaceConfigurationParcel mInterfaceConfiguration;
200     private NeighborEventConsumer mNeighborEventConsumer;
201     private BpfCoordinator mBpfCoordinator;
202     private BpfCoordinator.Dependencies mBpfDeps;
203 
initStateMachine(int interfaceType)204     private void initStateMachine(int interfaceType) throws Exception {
205         initStateMachine(interfaceType, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
206     }
207 
initStateMachine(int interfaceType, boolean usingLegacyDhcp, boolean usingBpfOffload)208     private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
209             boolean usingBpfOffload) throws Exception {
210         when(mDependencies.getDadProxy(any(), any())).thenReturn(mDadProxy);
211         when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
212         when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
213         when(mDependencies.getInterfaceParams(UPSTREAM_IFACE)).thenReturn(UPSTREAM_IFACE_PARAMS);
214         when(mDependencies.getInterfaceParams(UPSTREAM_IFACE2)).thenReturn(UPSTREAM_IFACE_PARAMS2);
215         when(mDependencies.getInterfaceParams(IPSEC_IFACE)).thenReturn(IPSEC_IFACE_PARAMS);
216 
217         mInterfaceConfiguration = new InterfaceConfigurationParcel();
218         mInterfaceConfiguration.flags = new String[0];
219         if (interfaceType == TETHERING_BLUETOOTH) {
220             mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR;
221             mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH;
222         }
223 
224         ArgumentCaptor<NeighborEventConsumer> neighborCaptor =
225                 ArgumentCaptor.forClass(NeighborEventConsumer.class);
226         doReturn(mIpNeighborMonitor).when(mDependencies).getIpNeighborMonitor(any(), any(),
227                 neighborCaptor.capture());
228 
229         mIpServer = new IpServer(
230                 IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd, mBpfCoordinator,
231                 mCallback, usingLegacyDhcp, usingBpfOffload, mAddressCoordinator, mDependencies);
232         mIpServer.start();
233         mNeighborEventConsumer = neighborCaptor.getValue();
234 
235         // Starting the state machine always puts us in a consistent state and notifies
236         // the rest of the world that we've changed from an unknown to available state.
237         mLooper.dispatchAll();
238         reset(mNetd, mCallback);
239 
240         when(mRaDaemon.start()).thenReturn(true);
241     }
242 
initTetheredStateMachine(int interfaceType, String upstreamIface)243     private void initTetheredStateMachine(int interfaceType, String upstreamIface)
244             throws Exception {
245         initTetheredStateMachine(interfaceType, upstreamIface, false,
246                 DEFAULT_USING_BPF_OFFLOAD);
247     }
248 
initTetheredStateMachine(int interfaceType, String upstreamIface, boolean usingLegacyDhcp, boolean usingBpfOffload)249     private void initTetheredStateMachine(int interfaceType, String upstreamIface,
250             boolean usingLegacyDhcp, boolean usingBpfOffload) throws Exception {
251         initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload);
252         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
253         if (upstreamIface != null) {
254             LinkProperties lp = new LinkProperties();
255             lp.setInterfaceName(upstreamIface);
256             dispatchTetherConnectionChanged(upstreamIface, lp, 0);
257         }
258         reset(mNetd, mCallback, mAddressCoordinator, mBpfCoordinator);
259         when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn(
260                 mTestAddress);
261     }
262 
setUpDhcpServer()263     private void setUpDhcpServer() throws Exception {
264         doAnswer(inv -> {
265             final IDhcpServerCallbacks cb = inv.getArgument(2);
266             new Thread(() -> {
267                 try {
268                     cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
269                 } catch (RemoteException e) {
270                     fail(e.getMessage());
271                 }
272             }).run();
273             return null;
274         }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
275     }
276 
setUp()277     @Before public void setUp() throws Exception {
278         MockitoAnnotations.initMocks(this);
279         when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
280         when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn(
281                 mTestAddress);
282         when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(true /* default value */);
283 
284         mBpfDeps = new BpfCoordinator.Dependencies() {
285                     @NonNull
286                     public Handler getHandler() {
287                         return new Handler(mLooper.getLooper());
288                     }
289 
290                     @NonNull
291                     public INetd getNetd() {
292                         return mNetd;
293                     }
294 
295                     @NonNull
296                     public NetworkStatsManager getNetworkStatsManager() {
297                         return mStatsManager;
298                     }
299 
300                     @NonNull
301                     public SharedLog getSharedLog() {
302                         return mSharedLog;
303                     }
304 
305                     @Nullable
306                     public TetheringConfiguration getTetherConfig() {
307                         return mTetherConfig;
308                     }
309 
310                     @NonNull
311                     public ConntrackMonitor getConntrackMonitor(
312                             ConntrackMonitor.ConntrackEventConsumer consumer) {
313                         return mConntrackMonitor;
314                     }
315 
316                     @Nullable
317                     public BpfMap<Tether4Key, Tether4Value> getBpfDownstream4Map() {
318                         return mBpfDownstream4Map;
319                     }
320 
321                     @Nullable
322                     public BpfMap<Tether4Key, Tether4Value> getBpfUpstream4Map() {
323                         return mBpfUpstream4Map;
324                     }
325 
326                     @Nullable
327                     public BpfMap<TetherDownstream6Key, Tether6Value> getBpfDownstream6Map() {
328                         return mBpfDownstream6Map;
329                     }
330 
331                     @Nullable
332                     public BpfMap<TetherUpstream6Key, Tether6Value> getBpfUpstream6Map() {
333                         return mBpfUpstream6Map;
334                     }
335 
336                     @Nullable
337                     public BpfMap<TetherStatsKey, TetherStatsValue> getBpfStatsMap() {
338                         return mBpfStatsMap;
339                     }
340 
341                     @Nullable
342                     public BpfMap<TetherLimitKey, TetherLimitValue> getBpfLimitMap() {
343                         return mBpfLimitMap;
344                     }
345 
346                     @Nullable
347                     public BpfMap<TetherDevKey, TetherDevValue> getBpfDevMap() {
348                         return mBpfDevMap;
349                     }
350                 };
351         mBpfCoordinator = spy(new BpfCoordinator(mBpfDeps));
352 
353         setUpDhcpServer();
354     }
355 
356     @Test
startsOutAvailable()357     public void startsOutAvailable() {
358         when(mDependencies.getIpNeighborMonitor(any(), any(), any()))
359                 .thenReturn(mIpNeighborMonitor);
360         mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
361                 mNetd, mBpfCoordinator, mCallback, false /* usingLegacyDhcp */,
362                 DEFAULT_USING_BPF_OFFLOAD, mAddressCoordinator, mDependencies);
363         mIpServer.start();
364         mLooper.dispatchAll();
365         verify(mCallback).updateInterfaceState(
366                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
367         verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
368         verifyNoMoreInteractions(mCallback, mNetd);
369     }
370 
371     @Test
shouldDoNothingUntilRequested()372     public void shouldDoNothingUntilRequested() throws Exception {
373         initStateMachine(TETHERING_BLUETOOTH);
374         final int [] noOp_commands = {
375             IpServer.CMD_TETHER_UNREQUESTED,
376             IpServer.CMD_IP_FORWARDING_ENABLE_ERROR,
377             IpServer.CMD_IP_FORWARDING_DISABLE_ERROR,
378             IpServer.CMD_START_TETHERING_ERROR,
379             IpServer.CMD_STOP_TETHERING_ERROR,
380             IpServer.CMD_SET_DNS_FORWARDERS_ERROR,
381             IpServer.CMD_TETHER_CONNECTION_CHANGED
382         };
383         for (int command : noOp_commands) {
384             // None of these commands should trigger us to request action from
385             // the rest of the system.
386             dispatchCommand(command);
387             verifyNoMoreInteractions(mNetd, mCallback);
388         }
389     }
390 
391     @Test
handlesImmediateInterfaceDown()392     public void handlesImmediateInterfaceDown() throws Exception {
393         initStateMachine(TETHERING_BLUETOOTH);
394 
395         dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
396         verify(mCallback).updateInterfaceState(
397                 mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
398         verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
399         verifyNoMoreInteractions(mNetd, mCallback);
400     }
401 
402     @Test
canBeTethered()403     public void canBeTethered() throws Exception {
404         initStateMachine(TETHERING_BLUETOOTH);
405 
406         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
407         InOrder inOrder = inOrder(mCallback, mNetd);
408         inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
409         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
410         // One for ipv4 route, one for ipv6 link local route.
411         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
412                 any(), any());
413         inOrder.verify(mCallback).updateInterfaceState(
414                 mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
415         inOrder.verify(mCallback).updateLinkProperties(
416                 eq(mIpServer), any(LinkProperties.class));
417         verifyNoMoreInteractions(mNetd, mCallback);
418     }
419 
420     @Test
canUnrequestTethering()421     public void canUnrequestTethering() throws Exception {
422         initTetheredStateMachine(TETHERING_BLUETOOTH, null);
423 
424         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
425         InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
426         inOrder.verify(mNetd).tetherApplyDnsInterfaces();
427         inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
428         inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
429         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
430         inOrder.verify(mAddressCoordinator).releaseDownstream(any());
431         inOrder.verify(mCallback).updateInterfaceState(
432                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
433         inOrder.verify(mCallback).updateLinkProperties(
434                 eq(mIpServer), any(LinkProperties.class));
435         verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
436     }
437 
438     @Test
canBeTetheredAsUsb()439     public void canBeTetheredAsUsb() throws Exception {
440         initStateMachine(TETHERING_USB);
441 
442         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
443         InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
444         inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true));
445         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
446                   IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
447         inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
448         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
449         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
450                 any(), any());
451         inOrder.verify(mCallback).updateInterfaceState(
452                 mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
453         inOrder.verify(mCallback).updateLinkProperties(
454                 eq(mIpServer), mLinkPropertiesCaptor.capture());
455         assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
456         verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
457     }
458 
459     @Test
canBeTetheredAsWifiP2p()460     public void canBeTetheredAsWifiP2p() throws Exception {
461         initStateMachine(TETHERING_WIFI_P2P);
462 
463         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
464         InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
465         inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true));
466         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
467                   IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP)));
468         inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
469         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
470         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
471                 any(), any());
472         inOrder.verify(mCallback).updateInterfaceState(
473                 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
474         inOrder.verify(mCallback).updateLinkProperties(
475                 eq(mIpServer), mLinkPropertiesCaptor.capture());
476         assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
477         verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
478     }
479 
480     @Test
handlesFirstUpstreamChange()481     public void handlesFirstUpstreamChange() throws Exception {
482         initTetheredStateMachine(TETHERING_BLUETOOTH, null);
483 
484         // Telling the state machine about its upstream interface triggers
485         // a little more configuration.
486         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
487         InOrder inOrder = inOrder(mNetd, mBpfCoordinator);
488 
489         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
490         inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX,
491                 UPSTREAM_IFACE);
492         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE);
493         inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
494         inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
495 
496         verifyNoMoreInteractions(mNetd, mCallback, mBpfCoordinator);
497     }
498 
499     @Test
handlesChangingUpstream()500     public void handlesChangingUpstream() throws Exception {
501         initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
502 
503         dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
504         InOrder inOrder = inOrder(mNetd, mBpfCoordinator);
505 
506         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
507         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
508         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
509         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
510 
511         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2>.
512         inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2,
513                 UPSTREAM_IFACE2);
514         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
515         inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
516         inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
517 
518         verifyNoMoreInteractions(mNetd, mCallback, mBpfCoordinator);
519     }
520 
521     @Test
handlesChangingUpstreamNatFailure()522     public void handlesChangingUpstreamNatFailure() throws Exception {
523         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
524 
525         doThrow(RemoteException.class).when(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
526 
527         dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
528         InOrder inOrder = inOrder(mNetd, mBpfCoordinator);
529 
530         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
531         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
532         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
533         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
534 
535         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on
536         // tetherAddForward.
537         inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2,
538                 UPSTREAM_IFACE2);
539         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
540         inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
541 
542         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> to fallback.
543         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE2);
544         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
545         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
546     }
547 
548     @Test
handlesChangingUpstreamInterfaceForwardingFailure()549     public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception {
550         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
551 
552         doThrow(RemoteException.class).when(mNetd).ipfwdAddInterfaceForward(
553                 IFACE_NAME, UPSTREAM_IFACE2);
554 
555         dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
556         InOrder inOrder = inOrder(mNetd, mBpfCoordinator);
557 
558         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
559         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
560         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
561         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
562 
563         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on
564         // ipfwdAddInterfaceForward.
565         inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2,
566                 UPSTREAM_IFACE2);
567         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
568         inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
569         inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
570 
571         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> to fallback.
572         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE2);
573         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
574         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
575     }
576 
577     @Test
canUnrequestTetheringWithUpstream()578     public void canUnrequestTetheringWithUpstream() throws Exception {
579         initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
580 
581         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
582         InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator, mBpfCoordinator);
583         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
584         inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
585         inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
586         inOrder.verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
587         inOrder.verify(mNetd).tetherApplyDnsInterfaces();
588         inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
589         inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
590         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
591         inOrder.verify(mAddressCoordinator).releaseDownstream(any());
592         inOrder.verify(mBpfCoordinator).tetherOffloadClientClear(mIpServer);
593         inOrder.verify(mBpfCoordinator).stopMonitoring(mIpServer);
594         inOrder.verify(mCallback).updateInterfaceState(
595                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
596         inOrder.verify(mCallback).updateLinkProperties(
597                 eq(mIpServer), any(LinkProperties.class));
598         verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator, mBpfCoordinator);
599     }
600 
601     @Test
interfaceDownLeadsToUnavailable()602     public void interfaceDownLeadsToUnavailable() throws Exception {
603         for (boolean shouldThrow : new boolean[]{true, false}) {
604             initTetheredStateMachine(TETHERING_USB, null);
605 
606             if (shouldThrow) {
607                 doThrow(RemoteException.class).when(mNetd).tetherInterfaceRemove(IFACE_NAME);
608             }
609             dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
610             InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
611             // Currently IpServer interfaceSetCfg twice to stop IPv4. One just set interface down
612             // Another one is set IPv4 to 0.0.0.0/0 as clearng ipv4 address.
613             usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
614                     argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
615             usbTeardownOrder.verify(mCallback).updateInterfaceState(
616                     mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
617             usbTeardownOrder.verify(mCallback).updateLinkProperties(
618                     eq(mIpServer), mLinkPropertiesCaptor.capture());
619             assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
620         }
621     }
622 
623     @Test
usbShouldBeTornDownOnTetherError()624     public void usbShouldBeTornDownOnTetherError() throws Exception {
625         initStateMachine(TETHERING_USB);
626 
627         doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME);
628         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
629         InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
630         usbTeardownOrder.verify(mNetd).interfaceSetCfg(
631                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
632         usbTeardownOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
633 
634         usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
635                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
636         usbTeardownOrder.verify(mCallback).updateInterfaceState(
637                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
638         usbTeardownOrder.verify(mCallback).updateLinkProperties(
639                 eq(mIpServer), mLinkPropertiesCaptor.capture());
640         assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
641     }
642 
643     @Test
shouldTearDownUsbOnUpstreamError()644     public void shouldTearDownUsbOnUpstreamError() throws Exception {
645         initTetheredStateMachine(TETHERING_USB, null);
646 
647         doThrow(RemoteException.class).when(mNetd).tetherAddForward(anyString(), anyString());
648         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
649         InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
650         usbTeardownOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
651 
652         usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
653                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
654         usbTeardownOrder.verify(mCallback).updateInterfaceState(
655                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_FORWARDING_ERROR);
656         usbTeardownOrder.verify(mCallback).updateLinkProperties(
657                 eq(mIpServer), mLinkPropertiesCaptor.capture());
658         assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
659     }
660 
661     @Test
ignoresDuplicateUpstreamNotifications()662     public void ignoresDuplicateUpstreamNotifications() throws Exception {
663         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
664 
665         verifyNoMoreInteractions(mNetd, mCallback);
666 
667         for (int i = 0; i < 5; i++) {
668             dispatchTetherConnectionChanged(UPSTREAM_IFACE);
669             verifyNoMoreInteractions(mNetd, mCallback);
670         }
671     }
672 
673     @Test
startsDhcpServer()674     public void startsDhcpServer() throws Exception {
675         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
676         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
677 
678         assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress));
679     }
680 
681     @Test
startsDhcpServerOnBluetooth()682     public void startsDhcpServerOnBluetooth() throws Exception {
683         initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
684         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
685 
686         assertDhcpStarted(mBluetoothPrefix);
687     }
688 
689     @Test
startsDhcpServerOnWifiP2p()690     public void startsDhcpServerOnWifiP2p() throws Exception {
691         initTetheredStateMachine(TETHERING_WIFI_P2P, UPSTREAM_IFACE);
692         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
693 
694         assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress));
695     }
696 
697     @Test
startsDhcpServerOnNcm()698     public void startsDhcpServerOnNcm() throws Exception {
699         initStateMachine(TETHERING_NCM);
700         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
701         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
702 
703         assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
704     }
705 
706     @Test
testOnNewPrefixRequest()707     public void testOnNewPrefixRequest() throws Exception {
708         initStateMachine(TETHERING_NCM);
709         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
710 
711         final IDhcpEventCallbacks eventCallbacks;
712         final ArgumentCaptor<IDhcpEventCallbacks> dhcpEventCbsCaptor =
713                  ArgumentCaptor.forClass(IDhcpEventCallbacks.class);
714         verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
715                 any(), dhcpEventCbsCaptor.capture());
716         eventCallbacks = dhcpEventCbsCaptor.getValue();
717         assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
718 
719         final ArgumentCaptor<LinkProperties> lpCaptor =
720                 ArgumentCaptor.forClass(LinkProperties.class);
721         InOrder inOrder = inOrder(mNetd, mCallback, mAddressCoordinator);
722         inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(true));
723         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
724         // One for ipv4 route, one for ipv6 link local route.
725         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
726                 any(), any());
727         inOrder.verify(mCallback).updateInterfaceState(
728                 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
729         inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
730         verifyNoMoreInteractions(mCallback, mAddressCoordinator);
731 
732         // Simulate the DHCP server receives DHCPDECLINE on MirrorLink and then signals
733         // onNewPrefixRequest callback.
734         final LinkAddress newAddress = new LinkAddress("192.168.100.125/24");
735         when(mAddressCoordinator.requestDownstreamAddress(any(), anyBoolean())).thenReturn(
736                 newAddress);
737         eventCallbacks.onNewPrefixRequest(new IpPrefix("192.168.42.0/24"));
738         mLooper.dispatchAll();
739 
740         inOrder.verify(mAddressCoordinator).requestDownstreamAddress(any(), eq(false));
741         inOrder.verify(mNetd).tetherApplyDnsInterfaces();
742         inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
743         verifyNoMoreInteractions(mCallback);
744 
745         final LinkProperties linkProperties = lpCaptor.getValue();
746         final List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses();
747         assertEquals(1, linkProperties.getLinkAddresses().size());
748         assertEquals(1, linkProperties.getRoutes().size());
749         final IpPrefix prefix = new IpPrefix(linkAddresses.get(0).getAddress(),
750                 linkAddresses.get(0).getPrefixLength());
751         assertNotEquals(prefix, new IpPrefix("192.168.42.0/24"));
752 
753         verify(mDhcpServer).updateParams(mDhcpParamsCaptor.capture(), any());
754         assertDhcpServingParams(mDhcpParamsCaptor.getValue(), prefix);
755     }
756 
757     @Test
doesNotStartDhcpServerIfDisabled()758     public void doesNotStartDhcpServerIfDisabled() throws Exception {
759         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */,
760                 DEFAULT_USING_BPF_OFFLOAD);
761         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
762 
763         verify(mDependencies, never()).makeDhcpServer(any(), any(), any());
764     }
765 
addr(String addr)766     private InetAddress addr(String addr) throws Exception {
767         return InetAddresses.parseNumericAddress(addr);
768     }
769 
recvNewNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac)770     private void recvNewNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) {
771         mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_NEWNEIGH, ifindex, addr,
772                 nudState, mac));
773         mLooper.dispatchAll();
774     }
775 
recvDelNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac)776     private void recvDelNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) {
777         mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_DELNEIGH, ifindex, addr,
778                 nudState, mac));
779         mLooper.dispatchAll();
780     }
781 
782     /**
783      * Custom ArgumentMatcher for TetherOffloadRuleParcel. This is needed because generated stable
784      * AIDL classes don't have equals(), so we cannot just use eq(). A custom assert, such as:
785      *
786      * private void checkFooCalled(StableParcelable p, ...) {
787      *     ArgumentCaptor<FooParam> captor = ArgumentCaptor.forClass(FooParam.class);
788      *     verify(mMock).foo(captor.capture());
789      *     Foo foo = captor.getValue();
790      *     assertFooMatchesExpectations(foo);
791      * }
792      *
793      * almost works, but not quite. This is because if the code under test calls foo() twice, the
794      * first call to checkFooCalled() matches both the calls, putting both calls into the captor,
795      * and then fails with TooManyActualInvocations. It also makes it harder to use other mockito
796      * features such as never(), inOrder(), etc.
797      *
798      * This approach isn't great because if the match fails, the error message is unhelpful
799      * (actual: "android.net.TetherOffloadRuleParcel@8c827b0" or some such), but at least it does
800      * work.
801      *
802      * TODO: consider making the error message more readable by adding a method that catching the
803      * AssertionFailedError and throwing a new assertion with more details. See
804      * NetworkMonitorTest#verifyNetworkTested.
805      *
806      * See ConnectivityServiceTest#assertRoutesAdded for an alternative approach which solves the
807      * TooManyActualInvocations problem described above by forcing the caller of the custom assert
808      * method to specify all expected invocations in one call. This is useful when the stable
809      * parcelable class being asserted on has a corresponding Java object (eg., RouteInfo and
810      * RouteInfoParcelable), and the caller can just pass in a list of them. It not useful here
811      * because there is no such object.
812      */
813     private static class TetherOffloadRuleParcelMatcher implements
814             ArgumentMatcher<TetherOffloadRuleParcel> {
815         public final int upstreamIfindex;
816         public final InetAddress dst;
817         public final MacAddress dstMac;
818 
TetherOffloadRuleParcelMatcher(int upstreamIfindex, InetAddress dst, MacAddress dstMac)819         TetherOffloadRuleParcelMatcher(int upstreamIfindex, InetAddress dst, MacAddress dstMac) {
820             this.upstreamIfindex = upstreamIfindex;
821             this.dst = dst;
822             this.dstMac = dstMac;
823         }
824 
matches(TetherOffloadRuleParcel parcel)825         public boolean matches(TetherOffloadRuleParcel parcel) {
826             return upstreamIfindex == parcel.inputInterfaceIndex
827                     && (TEST_IFACE_PARAMS.index == parcel.outputInterfaceIndex)
828                     && Arrays.equals(dst.getAddress(), parcel.destination)
829                     && (128 == parcel.prefixLength)
830                     && Arrays.equals(TEST_IFACE_PARAMS.macAddr.toByteArray(), parcel.srcL2Address)
831                     && Arrays.equals(dstMac.toByteArray(), parcel.dstL2Address);
832         }
833 
toString()834         public String toString() {
835             return String.format("TetherOffloadRuleParcelMatcher(%d, %s, %s",
836                     upstreamIfindex, dst.getHostAddress(), dstMac);
837         }
838     }
839 
840     @NonNull
matches( int upstreamIfindex, InetAddress dst, MacAddress dstMac)841     private static TetherOffloadRuleParcel matches(
842             int upstreamIfindex, InetAddress dst, MacAddress dstMac) {
843         return argThat(new TetherOffloadRuleParcelMatcher(upstreamIfindex, dst, dstMac));
844     }
845 
846     @NonNull
makeForwardingRule( int upstreamIfindex, @NonNull InetAddress dst, @NonNull MacAddress dstMac)847     private static Ipv6ForwardingRule makeForwardingRule(
848             int upstreamIfindex, @NonNull InetAddress dst, @NonNull MacAddress dstMac) {
849         return new Ipv6ForwardingRule(upstreamIfindex, TEST_IFACE_PARAMS.index,
850                 (Inet6Address) dst, TEST_IFACE_PARAMS.macAddr, dstMac);
851     }
852 
853     @NonNull
makeDownstream6Key(int upstreamIfindex, @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst)854     private static TetherDownstream6Key makeDownstream6Key(int upstreamIfindex,
855             @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst) {
856         return new TetherDownstream6Key(upstreamIfindex, upstreamMac, dst.getAddress());
857     }
858 
859     @NonNull
makeDownstream6Value(@onNull final MacAddress dstMac)860     private static Tether6Value makeDownstream6Value(@NonNull final MacAddress dstMac) {
861         return new Tether6Value(TEST_IFACE_PARAMS.index, dstMac,
862                 TEST_IFACE_PARAMS.macAddr, ETH_P_IPV6, NetworkStackConstants.ETHER_MTU);
863     }
864 
verifyWithOrder(@ullable InOrder inOrder, @NonNull T t)865     private <T> T verifyWithOrder(@Nullable InOrder inOrder, @NonNull T t) {
866         if (inOrder != null) {
867             return inOrder.verify(t);
868         } else {
869             return verify(t);
870         }
871     }
872 
verifyTetherOffloadRuleAdd(@ullable InOrder inOrder, int upstreamIfindex, @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst, @NonNull final MacAddress dstMac)873     private void verifyTetherOffloadRuleAdd(@Nullable InOrder inOrder, int upstreamIfindex,
874             @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst,
875             @NonNull final MacAddress dstMac) throws Exception {
876         if (mBpfDeps.isAtLeastS()) {
877             verifyWithOrder(inOrder, mBpfDownstream6Map).updateEntry(
878                     makeDownstream6Key(upstreamIfindex, upstreamMac, dst),
879                     makeDownstream6Value(dstMac));
880         } else {
881             verifyWithOrder(inOrder, mNetd).tetherOffloadRuleAdd(matches(upstreamIfindex, dst,
882                     dstMac));
883         }
884     }
885 
verifyNeverTetherOffloadRuleAdd(int upstreamIfindex, @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst, @NonNull final MacAddress dstMac)886     private void verifyNeverTetherOffloadRuleAdd(int upstreamIfindex,
887             @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst,
888             @NonNull final MacAddress dstMac) throws Exception {
889         if (mBpfDeps.isAtLeastS()) {
890             verify(mBpfDownstream6Map, never()).updateEntry(
891                     makeDownstream6Key(upstreamIfindex, upstreamMac, dst),
892                     makeDownstream6Value(dstMac));
893         } else {
894             verify(mNetd, never()).tetherOffloadRuleAdd(matches(upstreamIfindex, dst, dstMac));
895         }
896     }
897 
verifyNeverTetherOffloadRuleAdd()898     private void verifyNeverTetherOffloadRuleAdd() throws Exception {
899         if (mBpfDeps.isAtLeastS()) {
900             verify(mBpfDownstream6Map, never()).updateEntry(any(), any());
901         } else {
902             verify(mNetd, never()).tetherOffloadRuleAdd(any());
903         }
904     }
905 
verifyTetherOffloadRuleRemove(@ullable InOrder inOrder, int upstreamIfindex, @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst, @NonNull final MacAddress dstMac)906     private void verifyTetherOffloadRuleRemove(@Nullable InOrder inOrder, int upstreamIfindex,
907             @NonNull MacAddress upstreamMac, @NonNull final InetAddress dst,
908             @NonNull final MacAddress dstMac) throws Exception {
909         if (mBpfDeps.isAtLeastS()) {
910             verifyWithOrder(inOrder, mBpfDownstream6Map).deleteEntry(makeDownstream6Key(
911                     upstreamIfindex, upstreamMac, dst));
912         } else {
913             // |dstMac| is not required for deleting rules. Used bacause tetherOffloadRuleRemove
914             // uses a whole rule to be a argument.
915             // See system/netd/server/TetherController.cpp/TetherController#removeOffloadRule.
916             verifyWithOrder(inOrder, mNetd).tetherOffloadRuleRemove(matches(upstreamIfindex, dst,
917                     dstMac));
918         }
919     }
920 
verifyNeverTetherOffloadRuleRemove()921     private void verifyNeverTetherOffloadRuleRemove() throws Exception {
922         if (mBpfDeps.isAtLeastS()) {
923             verify(mBpfDownstream6Map, never()).deleteEntry(any());
924         } else {
925             verify(mNetd, never()).tetherOffloadRuleRemove(any());
926         }
927     }
928 
verifyStartUpstreamIpv6Forwarding(@ullable InOrder inOrder, int upstreamIfindex)929     private void verifyStartUpstreamIpv6Forwarding(@Nullable InOrder inOrder, int upstreamIfindex)
930             throws Exception {
931         if (!mBpfDeps.isAtLeastS()) return;
932         final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index,
933                 TEST_IFACE_PARAMS.macAddr);
934         final Tether6Value value = new Tether6Value(upstreamIfindex,
935                 MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS,
936                 ETH_P_IPV6, NetworkStackConstants.ETHER_MTU);
937         verifyWithOrder(inOrder, mBpfUpstream6Map).insertEntry(key, value);
938     }
939 
verifyStopUpstreamIpv6Forwarding(@ullable InOrder inOrder)940     private void verifyStopUpstreamIpv6Forwarding(@Nullable InOrder inOrder)
941             throws Exception {
942         if (!mBpfDeps.isAtLeastS()) return;
943         final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index,
944                 TEST_IFACE_PARAMS.macAddr);
945         verifyWithOrder(inOrder, mBpfUpstream6Map).deleteEntry(key);
946     }
947 
verifyNoUpstreamIpv6ForwardingChange(@ullable InOrder inOrder)948     private void verifyNoUpstreamIpv6ForwardingChange(@Nullable InOrder inOrder) throws Exception {
949         if (!mBpfDeps.isAtLeastS()) return;
950         if (inOrder != null) {
951             inOrder.verify(mBpfUpstream6Map, never()).deleteEntry(any());
952             inOrder.verify(mBpfUpstream6Map, never()).insertEntry(any(), any());
953             inOrder.verify(mBpfUpstream6Map, never()).updateEntry(any(), any());
954         } else {
955             verify(mBpfUpstream6Map, never()).deleteEntry(any());
956             verify(mBpfUpstream6Map, never()).insertEntry(any(), any());
957             verify(mBpfUpstream6Map, never()).updateEntry(any(), any());
958         }
959     }
960 
961     @NonNull
buildEmptyTetherStatsParcel(int ifIndex)962     private static TetherStatsParcel buildEmptyTetherStatsParcel(int ifIndex) {
963         TetherStatsParcel parcel = new TetherStatsParcel();
964         parcel.ifIndex = ifIndex;
965         return parcel;
966     }
967 
resetNetdBpfMapAndCoordinator()968     private void resetNetdBpfMapAndCoordinator() throws Exception {
969         reset(mNetd, mBpfDownstream6Map, mBpfUpstream6Map, mBpfCoordinator);
970         // When the last rule is removed, tetherOffloadGetAndClearStats will log a WTF (and
971         // potentially crash the test) if the stats map is empty.
972         when(mNetd.tetherOffloadGetStats()).thenReturn(new TetherStatsParcel[0]);
973         when(mNetd.tetherOffloadGetAndClearStats(UPSTREAM_IFINDEX))
974                 .thenReturn(buildEmptyTetherStatsParcel(UPSTREAM_IFINDEX));
975         when(mNetd.tetherOffloadGetAndClearStats(UPSTREAM_IFINDEX2))
976                 .thenReturn(buildEmptyTetherStatsParcel(UPSTREAM_IFINDEX2));
977         // When the last rule is removed, tetherOffloadGetAndClearStats will log a WTF (and
978         // potentially crash the test) if the stats map is empty.
979         final TetherStatsValue allZeros = new TetherStatsValue(0, 0, 0, 0, 0, 0);
980         when(mBpfStatsMap.getValue(new TetherStatsKey(UPSTREAM_IFINDEX))).thenReturn(allZeros);
981         when(mBpfStatsMap.getValue(new TetherStatsKey(UPSTREAM_IFINDEX2))).thenReturn(allZeros);
982     }
983 
984     @Test
addRemoveipv6ForwardingRules()985     public void addRemoveipv6ForwardingRules() throws Exception {
986         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
987                 DEFAULT_USING_BPF_OFFLOAD);
988 
989         final int myIfindex = TEST_IFACE_PARAMS.index;
990         final int notMyIfindex = myIfindex - 1;
991 
992         final InetAddress neighA = InetAddresses.parseNumericAddress("2001:db8::1");
993         final InetAddress neighB = InetAddresses.parseNumericAddress("2001:db8::2");
994         final InetAddress neighLL = InetAddresses.parseNumericAddress("fe80::1");
995         final InetAddress neighMC = InetAddresses.parseNumericAddress("ff02::1234");
996         final MacAddress macNull = MacAddress.fromString("00:00:00:00:00:00");
997         final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a");
998         final MacAddress macB = MacAddress.fromString("11:22:33:00:00:0b");
999 
1000         resetNetdBpfMapAndCoordinator();
1001         verifyNoMoreInteractions(mBpfCoordinator, mNetd, mBpfDownstream6Map, mBpfUpstream6Map);
1002 
1003         // TODO: Perhaps verify the interaction of tetherOffloadSetInterfaceQuota and
1004         // tetherOffloadGetAndClearStats in netd while the rules are changed.
1005 
1006         // Events on other interfaces are ignored.
1007         recvNewNeigh(notMyIfindex, neighA, NUD_REACHABLE, macA);
1008         verifyNoMoreInteractions(mBpfCoordinator, mNetd, mBpfDownstream6Map, mBpfUpstream6Map);
1009 
1010         // Events on this interface are received and sent to netd.
1011         recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
1012         verify(mBpfCoordinator).tetherOffloadRuleAdd(
1013                 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
1014         verifyTetherOffloadRuleAdd(null,
1015                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
1016         verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX);
1017         resetNetdBpfMapAndCoordinator();
1018 
1019         recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
1020         verify(mBpfCoordinator).tetherOffloadRuleAdd(
1021                 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB));
1022         verifyTetherOffloadRuleAdd(null,
1023                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
1024         verifyNoUpstreamIpv6ForwardingChange(null);
1025         resetNetdBpfMapAndCoordinator();
1026 
1027         // Link-local and multicast neighbors are ignored.
1028         recvNewNeigh(myIfindex, neighLL, NUD_REACHABLE, macA);
1029         verifyNoMoreInteractions(mBpfCoordinator, mNetd, mBpfDownstream6Map, mBpfUpstream6Map);
1030         recvNewNeigh(myIfindex, neighMC, NUD_REACHABLE, macA);
1031         verifyNoMoreInteractions(mBpfCoordinator, mNetd, mBpfDownstream6Map, mBpfUpstream6Map);
1032 
1033         // A neighbor that is no longer valid causes the rule to be removed.
1034         // NUD_FAILED events do not have a MAC address.
1035         recvNewNeigh(myIfindex, neighA, NUD_FAILED, null);
1036         verify(mBpfCoordinator).tetherOffloadRuleRemove(
1037                 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macNull));
1038         verifyTetherOffloadRuleRemove(null,
1039                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macNull);
1040         verifyNoUpstreamIpv6ForwardingChange(null);
1041         resetNetdBpfMapAndCoordinator();
1042 
1043         // A neighbor that is deleted causes the rule to be removed.
1044         recvDelNeigh(myIfindex, neighB, NUD_STALE, macB);
1045         verify(mBpfCoordinator).tetherOffloadRuleRemove(
1046                 mIpServer,  makeForwardingRule(UPSTREAM_IFINDEX, neighB, macNull));
1047         verifyTetherOffloadRuleRemove(null,
1048                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macNull);
1049         verifyStopUpstreamIpv6Forwarding(null);
1050         resetNetdBpfMapAndCoordinator();
1051 
1052         // Upstream changes result in updating the rules.
1053         recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
1054         verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX);
1055         recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
1056         resetNetdBpfMapAndCoordinator();
1057 
1058         InOrder inOrder = inOrder(mNetd, mBpfDownstream6Map, mBpfUpstream6Map);
1059         LinkProperties lp = new LinkProperties();
1060         lp.setInterfaceName(UPSTREAM_IFACE2);
1061         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1);
1062         verify(mBpfCoordinator).tetherOffloadRuleUpdate(mIpServer, UPSTREAM_IFINDEX2);
1063         verifyTetherOffloadRuleRemove(inOrder,
1064                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
1065         verifyTetherOffloadRuleRemove(inOrder,
1066                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
1067         verifyStopUpstreamIpv6Forwarding(inOrder);
1068         verifyTetherOffloadRuleAdd(inOrder,
1069                 UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighA, macA);
1070         verifyStartUpstreamIpv6Forwarding(inOrder, UPSTREAM_IFINDEX2);
1071         verifyTetherOffloadRuleAdd(inOrder,
1072                 UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighB, macB);
1073         verifyNoUpstreamIpv6ForwardingChange(inOrder);
1074         resetNetdBpfMapAndCoordinator();
1075 
1076         // When the upstream is lost, rules are removed.
1077         dispatchTetherConnectionChanged(null, null, 0);
1078         // Clear function is called two times by:
1079         // - processMessage CMD_TETHER_CONNECTION_CHANGED for the upstream is lost.
1080         // - processMessage CMD_IPV6_TETHER_UPDATE for the IPv6 upstream is lost.
1081         // See dispatchTetherConnectionChanged.
1082         verify(mBpfCoordinator, times(2)).tetherOffloadRuleClear(mIpServer);
1083         verifyTetherOffloadRuleRemove(null,
1084                 UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighA, macA);
1085         verifyTetherOffloadRuleRemove(null,
1086                 UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighB, macB);
1087         verifyStopUpstreamIpv6Forwarding(inOrder);
1088         resetNetdBpfMapAndCoordinator();
1089 
1090         // If the upstream is IPv4-only, no rules are added.
1091         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
1092         resetNetdBpfMapAndCoordinator();
1093         recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
1094         // Clear function is called by #updateIpv6ForwardingRules for the IPv6 upstream is lost.
1095         verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
1096         verifyNoUpstreamIpv6ForwardingChange(null);
1097         verifyNoMoreInteractions(mBpfCoordinator, mNetd, mBpfDownstream6Map, mBpfUpstream6Map);
1098 
1099         // Rules can be added again once upstream IPv6 connectivity is available.
1100         lp.setInterfaceName(UPSTREAM_IFACE);
1101         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
1102         recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
1103         verify(mBpfCoordinator).tetherOffloadRuleAdd(
1104                 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB));
1105         verifyTetherOffloadRuleAdd(null,
1106                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
1107         verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX);
1108         verify(mBpfCoordinator, never()).tetherOffloadRuleAdd(
1109                 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
1110         verifyNeverTetherOffloadRuleAdd(
1111                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
1112 
1113         // If upstream IPv6 connectivity is lost, rules are removed.
1114         resetNetdBpfMapAndCoordinator();
1115         dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
1116         verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
1117         verifyTetherOffloadRuleRemove(null,
1118                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
1119         verifyStopUpstreamIpv6Forwarding(null);
1120 
1121         // When the interface goes down, rules are removed.
1122         lp.setInterfaceName(UPSTREAM_IFACE);
1123         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
1124         recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
1125         recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
1126         verify(mBpfCoordinator).tetherOffloadRuleAdd(
1127                 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
1128         verifyTetherOffloadRuleAdd(null,
1129                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
1130         verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX);
1131         verify(mBpfCoordinator).tetherOffloadRuleAdd(
1132                 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB));
1133         verifyTetherOffloadRuleAdd(null,
1134                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
1135         resetNetdBpfMapAndCoordinator();
1136 
1137         mIpServer.stop();
1138         mLooper.dispatchAll();
1139         verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
1140         verifyTetherOffloadRuleRemove(null,
1141                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
1142         verifyTetherOffloadRuleRemove(null,
1143                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
1144         verifyStopUpstreamIpv6Forwarding(null);
1145         verify(mIpNeighborMonitor).stop();
1146         resetNetdBpfMapAndCoordinator();
1147     }
1148 
1149     @Test
enableDisableUsingBpfOffload()1150     public void enableDisableUsingBpfOffload() throws Exception {
1151         final int myIfindex = TEST_IFACE_PARAMS.index;
1152         final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1");
1153         final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a");
1154         final MacAddress macNull = MacAddress.fromString("00:00:00:00:00:00");
1155 
1156         // Expect that rules can be only added/removed when the BPF offload config is enabled.
1157         // Note that the BPF offload disabled case is not a realistic test case. Because IP
1158         // neighbor monitor doesn't start if BPF offload is disabled, there should have no
1159         // neighbor event listening. This is used for testing the protection check just in case.
1160         // TODO: Perhaps remove the BPF offload disabled case test once this check isn't needed
1161         // anymore.
1162 
1163         // [1] Enable BPF offload.
1164         // A neighbor that is added or deleted causes the rule to be added or removed.
1165         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
1166                 true /* usingBpfOffload */);
1167         resetNetdBpfMapAndCoordinator();
1168 
1169         recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA);
1170         verify(mBpfCoordinator).tetherOffloadRuleAdd(
1171                 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macA));
1172         verifyTetherOffloadRuleAdd(null,
1173                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neigh, macA);
1174         verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX);
1175         resetNetdBpfMapAndCoordinator();
1176 
1177         recvDelNeigh(myIfindex, neigh, NUD_STALE, macA);
1178         verify(mBpfCoordinator).tetherOffloadRuleRemove(
1179                 mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macNull));
1180         verifyTetherOffloadRuleRemove(null,
1181                 UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neigh, macNull);
1182         verifyStopUpstreamIpv6Forwarding(null);
1183         resetNetdBpfMapAndCoordinator();
1184 
1185         // [2] Disable BPF offload.
1186         // A neighbor that is added or deleted doesn’t cause the rule to be added or removed.
1187         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
1188                 false /* usingBpfOffload */);
1189         resetNetdBpfMapAndCoordinator();
1190 
1191         recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA);
1192         verify(mBpfCoordinator, never()).tetherOffloadRuleAdd(any(), any());
1193         verifyNeverTetherOffloadRuleAdd();
1194         verifyNoUpstreamIpv6ForwardingChange(null);
1195         resetNetdBpfMapAndCoordinator();
1196 
1197         recvDelNeigh(myIfindex, neigh, NUD_STALE, macA);
1198         verify(mBpfCoordinator, never()).tetherOffloadRuleRemove(any(), any());
1199         verifyNeverTetherOffloadRuleRemove();
1200         verifyNoUpstreamIpv6ForwardingChange(null);
1201         resetNetdBpfMapAndCoordinator();
1202     }
1203 
1204     @Test
doesNotStartIpNeighborMonitorIfBpfOffloadDisabled()1205     public void doesNotStartIpNeighborMonitorIfBpfOffloadDisabled() throws Exception {
1206         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */,
1207                 false /* usingBpfOffload */);
1208 
1209         // IP neighbor monitor doesn't start if BPF offload is disabled.
1210         verify(mIpNeighborMonitor, never()).start();
1211     }
1212 
buildIpv6OnlyLinkProperties(final String iface)1213     private LinkProperties buildIpv6OnlyLinkProperties(final String iface) {
1214         final LinkProperties linkProp = new LinkProperties();
1215         linkProp.setInterfaceName(iface);
1216         linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
1217         linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST));
1218         final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888");
1219         linkProp.addDnsServer(dns);
1220 
1221         return linkProp;
1222     }
1223 
1224     @Test
testAdjustTtlValue()1225     public void testAdjustTtlValue() throws Exception {
1226         final ArgumentCaptor<RaParams> raParamsCaptor =
1227                 ArgumentCaptor.forClass(RaParams.class);
1228         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
1229         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
1230         final RaParams noV6Params = raParamsCaptor.getValue();
1231         assertEquals(65, noV6Params.hopLimit);
1232         reset(mRaDaemon);
1233 
1234         when(mNetd.getProcSysNet(
1235                 INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64");
1236         final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE);
1237         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1);
1238         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
1239         final RaParams nonCellularParams = raParamsCaptor.getValue();
1240         assertEquals(65, nonCellularParams.hopLimit);
1241         reset(mRaDaemon);
1242 
1243         dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
1244         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
1245         final RaParams noUpstream = raParamsCaptor.getValue();
1246         assertEquals(65, nonCellularParams.hopLimit);
1247         reset(mRaDaemon);
1248 
1249         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
1250         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
1251         final RaParams cellularParams = raParamsCaptor.getValue();
1252         assertEquals(63, cellularParams.hopLimit);
1253         reset(mRaDaemon);
1254     }
1255 
1256     @Test
testStopObsoleteDhcpServer()1257     public void testStopObsoleteDhcpServer() throws Exception {
1258         final ArgumentCaptor<DhcpServerCallbacks> cbCaptor =
1259                 ArgumentCaptor.forClass(DhcpServerCallbacks.class);
1260         doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(),
1261                 cbCaptor.capture());
1262         initStateMachine(TETHERING_WIFI);
1263         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
1264         verify(mDhcpServer, never()).startWithCallbacks(any(), any());
1265 
1266         // No stop dhcp server because dhcp server is not created yet.
1267         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
1268         verify(mDhcpServer, never()).stop(any());
1269 
1270         // Stop obsolete dhcp server.
1271         try {
1272             final DhcpServerCallbacks cb = cbCaptor.getValue();
1273             cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
1274             mLooper.dispatchAll();
1275         } catch (RemoteException e) {
1276             fail(e.getMessage());
1277         }
1278         verify(mDhcpServer).stop(any());
1279     }
1280 
assertDhcpServingParams(final DhcpServingParamsParcel params, final IpPrefix prefix)1281     private void assertDhcpServingParams(final DhcpServingParamsParcel params,
1282             final IpPrefix prefix) {
1283         // Last address byte is random
1284         assertTrue(prefix.contains(intToInet4AddressHTH(params.serverAddr)));
1285         assertEquals(prefix.getPrefixLength(), params.serverAddrPrefixLength);
1286         assertEquals(1, params.defaultRouters.length);
1287         assertEquals(params.serverAddr, params.defaultRouters[0]);
1288         assertEquals(1, params.dnsServers.length);
1289         assertEquals(params.serverAddr, params.dnsServers[0]);
1290         assertEquals(DHCP_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs);
1291         if (mIpServer.interfaceType() == TETHERING_NCM) {
1292             assertTrue(params.changePrefixOnDecline);
1293         }
1294     }
1295 
assertDhcpStarted(IpPrefix expectedPrefix)1296     private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {
1297         verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any());
1298         verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
1299                 any(), any());
1300         assertDhcpServingParams(mDhcpParamsCaptor.getValue(), expectedPrefix);
1301     }
1302 
1303     /**
1304      * Send a command to the state machine under test, and run the event loop to idle.
1305      *
1306      * @param command One of the IpServer.CMD_* constants.
1307      * @param arg1 An additional argument to pass.
1308      */
dispatchCommand(int command, int arg1)1309     private void dispatchCommand(int command, int arg1) {
1310         mIpServer.sendMessage(command, arg1);
1311         mLooper.dispatchAll();
1312     }
1313 
1314     /**
1315      * Send a command to the state machine under test, and run the event loop to idle.
1316      *
1317      * @param command One of the IpServer.CMD_* constants.
1318      */
dispatchCommand(int command)1319     private void dispatchCommand(int command) {
1320         mIpServer.sendMessage(command);
1321         mLooper.dispatchAll();
1322     }
1323 
1324     /**
1325      * Special override to tell the state machine that the upstream interface has changed.
1326      *
1327      * @see #dispatchCommand(int)
1328      * @param upstreamIface String name of upstream interface (or null)
1329      * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream.
1330      */
dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, int ttlAdjustment)1331     private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp,
1332             int ttlAdjustment) {
1333         dispatchTetherConnectionChanged(upstreamIface);
1334         mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp);
1335         mLooper.dispatchAll();
1336     }
1337 
dispatchTetherConnectionChanged(String upstreamIface)1338     private void dispatchTetherConnectionChanged(String upstreamIface) {
1339         final InterfaceSet ifs = (upstreamIface != null) ? new InterfaceSet(upstreamIface) : null;
1340         mIpServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifs);
1341         mLooper.dispatchAll();
1342     }
1343 
assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp)1344     private void assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp) {
1345         // Find the first IPv4 LinkAddress.
1346         LinkAddress addr4 = null;
1347         for (LinkAddress addr : lp.getLinkAddresses()) {
1348             if (!(addr.getAddress() instanceof Inet4Address)) continue;
1349             addr4 = addr;
1350             break;
1351         }
1352         assertNotNull("missing IPv4 address", addr4);
1353 
1354         final IpPrefix destination = new IpPrefix(addr4.getAddress(), addr4.getPrefixLength());
1355         // Assert the presence of the associated directly connected route.
1356         final RouteInfo directlyConnected = new RouteInfo(destination, null, lp.getInterfaceName(),
1357                 RouteInfo.RTN_UNICAST);
1358         assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'",
1359                    lp.getRoutes().contains(directlyConnected));
1360     }
1361 
assertNoAddressesNorRoutes(LinkProperties lp)1362     private void assertNoAddressesNorRoutes(LinkProperties lp) {
1363         assertTrue(lp.getLinkAddresses().isEmpty());
1364         assertTrue(lp.getRoutes().isEmpty());
1365         // We also check that interface name is non-empty, because we should
1366         // never see an empty interface name in any LinkProperties update.
1367         assertFalse(TextUtils.isEmpty(lp.getInterfaceName()));
1368     }
1369 
assertContainsFlag(String[] flags, String match)1370     private boolean assertContainsFlag(String[] flags, String match) {
1371         for (String flag : flags) {
1372             if (flag.equals(match)) return true;
1373         }
1374         fail("Missing flag: " + match);
1375         return false;
1376     }
1377 
assertNotContainsFlag(String[] flags, String match)1378     private boolean assertNotContainsFlag(String[] flags, String match) {
1379         for (String flag : flags) {
1380             if (flag.equals(match)) {
1381                 fail("Unexpected flag: " + match);
1382                 return false;
1383             }
1384         }
1385         return true;
1386     }
1387 
1388     @Test @IgnoreUpTo(Build.VERSION_CODES.R)
dadProxyUpdates()1389     public void dadProxyUpdates() throws Exception {
1390         InOrder inOrder = inOrder(mDadProxy);
1391         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
1392         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1393 
1394         // Add an upstream without IPv6.
1395         dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
1396         inOrder.verify(mDadProxy).setUpstreamIface(null);
1397 
1398         // Add IPv6 to the upstream.
1399         LinkProperties lp = new LinkProperties();
1400         lp.setInterfaceName(UPSTREAM_IFACE);
1401         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
1402         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1403 
1404         // Change upstream.
1405         // New linkproperties is needed, otherwise changing the iface has no impact.
1406         LinkProperties lp2 = new LinkProperties();
1407         lp2.setInterfaceName(UPSTREAM_IFACE2);
1408         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp2, 0);
1409         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS2);
1410 
1411         // Lose IPv6 on the upstream...
1412         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, null, 0);
1413         inOrder.verify(mDadProxy).setUpstreamIface(null);
1414 
1415         // ... and regain it on a different upstream.
1416         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
1417         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1418 
1419         // Lose upstream.
1420         dispatchTetherConnectionChanged(null, null, 0);
1421         inOrder.verify(mDadProxy).setUpstreamIface(null);
1422 
1423         // Regain upstream.
1424         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
1425         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1426 
1427         // Stop tethering.
1428         mIpServer.stop();
1429         mLooper.dispatchAll();
1430     }
1431 
checkDadProxyEnabled(boolean expectEnabled)1432     private void checkDadProxyEnabled(boolean expectEnabled) throws Exception {
1433         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
1434         InOrder inOrder = inOrder(mDadProxy);
1435         // Add IPv6 to the upstream.
1436         LinkProperties lp = new LinkProperties();
1437         lp.setInterfaceName(UPSTREAM_IFACE);
1438         if (expectEnabled) {
1439             inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1440         } else {
1441             inOrder.verifyNoMoreInteractions();
1442         }
1443         // Stop tethering.
1444         mIpServer.stop();
1445         mLooper.dispatchAll();
1446         if (expectEnabled) {
1447             inOrder.verify(mDadProxy).stop();
1448         }
1449         else {
1450             verify(mDependencies, never()).getDadProxy(any(), any());
1451         }
1452     }
1453     @Test @IgnoreAfter(Build.VERSION_CODES.R)
testDadProxyUpdates_DisabledUpToR()1454     public void testDadProxyUpdates_DisabledUpToR() throws Exception {
1455         checkDadProxyEnabled(false);
1456     }
1457     @Test @IgnoreUpTo(Build.VERSION_CODES.R)
testDadProxyUpdates_EnabledAfterR()1458     public void testDadProxyUpdates_EnabledAfterR() throws Exception {
1459         checkDadProxyEnabled(true);
1460     }
1461 
1462     @Test
testSkipVirtualNetworkInBpf()1463     public void testSkipVirtualNetworkInBpf() throws Exception {
1464         initTetheredStateMachine(TETHERING_BLUETOOTH, null);
1465         final LinkProperties v6Only = new LinkProperties();
1466         v6Only.setInterfaceName(IPSEC_IFACE);
1467         dispatchTetherConnectionChanged(IPSEC_IFACE, v6Only, 0);
1468 
1469         verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, IPSEC_IFACE);
1470         verify(mNetd).tetherAddForward(IFACE_NAME, IPSEC_IFACE);
1471         verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, IPSEC_IFACE);
1472 
1473         final int myIfindex = TEST_IFACE_PARAMS.index;
1474         final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1");
1475         final MacAddress mac = MacAddress.fromString("00:00:00:00:00:0a");
1476         recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, mac);
1477         verify(mBpfCoordinator, never()).tetherOffloadRuleAdd(
1478                 mIpServer, makeForwardingRule(IPSEC_IFINDEX, neigh, mac));
1479     }
1480 }
1481