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