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