1 /* 2 * Copyright (C) 2017 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.ip.IpClientLinkObserver.CONFIG_SOCKET_RECV_BUFSIZE; 20 import static android.net.ip.IpClientLinkObserver.SOCKET_RECV_BUFSIZE; 21 import static android.system.OsConstants.RT_SCOPE_UNIVERSE; 22 23 import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT; 24 import static com.android.net.module.util.netlink.NetlinkConstants.RTPROT_KERNEL; 25 import static com.android.net.module.util.netlink.NetlinkConstants.RTM_DELROUTE; 26 import static com.android.net.module.util.netlink.NetlinkConstants.RTM_NEWADDR; 27 import static com.android.net.module.util.netlink.NetlinkConstants.RTM_NEWNDUSEROPT; 28 import static com.android.net.module.util.netlink.NetlinkConstants.RTM_NEWROUTE; 29 import static com.android.net.module.util.netlink.NetlinkConstants.RTN_UNICAST; 30 import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_ACK; 31 import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST; 32 33 import static org.junit.Assert.assertArrayEquals; 34 import static org.junit.Assert.assertEquals; 35 import static org.junit.Assert.assertFalse; 36 import static org.junit.Assert.assertNotNull; 37 import static org.junit.Assert.assertNull; 38 import static org.junit.Assert.assertTrue; 39 import static org.junit.Assert.fail; 40 import static org.mockito.ArgumentMatchers.anyBoolean; 41 import static org.mockito.Mockito.any; 42 import static org.mockito.Mockito.anyInt; 43 import static org.mockito.Mockito.anyString; 44 import static org.mockito.Mockito.clearInvocations; 45 import static org.mockito.Mockito.doReturn; 46 import static org.mockito.Mockito.eq; 47 import static org.mockito.Mockito.never; 48 import static org.mockito.Mockito.reset; 49 import static org.mockito.Mockito.timeout; 50 import static org.mockito.Mockito.verify; 51 import static org.mockito.Mockito.verifyNoMoreInteractions; 52 import static org.mockito.Mockito.when; 53 54 import static java.util.Collections.emptySet; 55 56 import android.annotation.SuppressLint; 57 import android.app.AlarmManager; 58 import android.content.ContentResolver; 59 import android.content.Context; 60 import android.content.res.Resources; 61 import android.net.ConnectivityManager; 62 import android.net.INetd; 63 import android.net.InetAddresses; 64 import android.net.IpPrefix; 65 import android.net.LinkAddress; 66 import android.net.LinkProperties; 67 import android.net.MacAddress; 68 import android.net.NetworkStackIpMemoryStore; 69 import android.net.RouteInfo; 70 import android.net.apf.ApfCapabilities; 71 import android.net.apf.ApfFilter.ApfConfiguration; 72 import android.net.ip.IpClientLinkObserver.IpClientNetlinkMonitor; 73 import android.net.ip.IpClientLinkObserver.IpClientNetlinkMonitor.INetlinkMessageProcessor; 74 import android.net.ipmemorystore.NetworkAttributes; 75 import android.net.metrics.IpConnectivityLog; 76 import android.net.shared.InitialConfiguration; 77 import android.net.shared.Layer2Information; 78 import android.net.shared.ProvisioningConfiguration; 79 import android.net.shared.ProvisioningConfiguration.ScanResultInfo; 80 import android.os.Build; 81 import android.system.OsConstants; 82 83 import androidx.test.filters.SmallTest; 84 import androidx.test.runner.AndroidJUnit4; 85 86 import com.android.modules.utils.build.SdkLevel; 87 import com.android.net.module.util.InterfaceParams; 88 import com.android.net.module.util.netlink.NduseroptMessage; 89 import com.android.net.module.util.netlink.RtNetlinkAddressMessage; 90 import com.android.net.module.util.netlink.RtNetlinkRouteMessage; 91 import com.android.net.module.util.netlink.StructIfaddrMsg; 92 import com.android.net.module.util.netlink.StructNdOptRdnss; 93 import com.android.net.module.util.netlink.StructNlMsgHdr; 94 import com.android.net.module.util.netlink.StructRtMsg; 95 import com.android.networkstack.R; 96 import com.android.networkstack.ipmemorystore.IpMemoryStoreService; 97 import com.android.server.NetworkStackService; 98 import com.android.testutils.DevSdkIgnoreRule; 99 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; 100 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; 101 import com.android.testutils.HandlerUtils; 102 103 import org.junit.Before; 104 import org.junit.Rule; 105 import org.junit.Test; 106 import org.junit.runner.RunWith; 107 import org.mockito.ArgumentCaptor; 108 import org.mockito.Mock; 109 import org.mockito.MockitoAnnotations; 110 111 import java.io.FileDescriptor; 112 import java.io.PrintWriter; 113 import java.net.Inet4Address; 114 import java.net.Inet6Address; 115 import java.net.InetAddress; 116 import java.nio.ByteBuffer; 117 import java.util.Arrays; 118 import java.util.Collections; 119 import java.util.HashSet; 120 import java.util.List; 121 import java.util.Random; 122 import java.util.Set; 123 124 125 /** 126 * Tests for IpClient. 127 */ 128 @RunWith(AndroidJUnit4.class) 129 @SmallTest 130 public class IpClientTest { 131 @Rule 132 public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); 133 134 private static final String VALID = "VALID"; 135 private static final String INVALID = "INVALID"; 136 private static final String TEST_IFNAME = "test_wlan0"; 137 private static final int TEST_IFINDEX = 1001; 138 // See RFC 7042#section-2.1.2 for EUI-48 documentation values. 139 private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01"); 140 private static final int TEST_TIMEOUT_MS = 30_000; 141 private static final String TEST_L2KEY = "some l2key"; 142 private static final String TEST_CLUSTER = "some cluster"; 143 private static final String TEST_SSID = "test_ssid"; 144 private static final String TEST_BSSID = "00:11:22:33:44:55"; 145 private static final String TEST_BSSID2 = "00:1A:11:22:33:44"; 146 147 private static final String TEST_GLOBAL_ADDRESS = "1234:4321::548d:2db2:4fcf:ef75/64"; 148 private static final String[] TEST_LOCAL_ADDRESSES = { 149 "fe80::a4be:f92:e1f7:22d1/64", 150 "fe80::f04a:8f6:6a32:d756/64", 151 "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64" 152 }; 153 private static final String TEST_IPV4_LINKADDRESS = "192.168.42.24/24"; 154 private static final String[] TEST_PREFIXES = { "fe80::/64", "fd2c:4e57:8e3c::/64" }; 155 private static final String[] TEST_DNSES = { "fd2c:4e57:8e3c::42" }; 156 private static final String TEST_IPV6_GATEWAY = "fd2c:4e57:8e3c::43"; 157 private static final String TEST_IPV4_GATEWAY = "192.168.42.11"; 158 private static final long TEST_DNS_LIFETIME = 3600; 159 // `whenMs` param in processNetlinkMessage is only used to process PREF64 option in RA, which 160 // is not used for RTM_NEWADDR, RTM_NEWROUTE and RDNSS option. 161 private static final long TEST_UNUSED_REAL_TIME = 0; 162 163 @Mock private Context mContext; 164 @Mock private ConnectivityManager mCm; 165 @Mock private INetd mNetd; 166 @Mock private Resources mResources; 167 @Mock private IIpClientCallbacks mCb; 168 @Mock private AlarmManager mAlarm; 169 @Mock private IpClient.Dependencies mDependencies; 170 @Mock private ContentResolver mContentResolver; 171 @Mock private NetworkStackService.NetworkStackServiceManager mNetworkStackServiceManager; 172 @Mock private NetworkStackIpMemoryStore mIpMemoryStore; 173 @Mock private IpMemoryStoreService mIpMemoryStoreService; 174 @Mock private InterfaceParams mInterfaceParams; 175 @Mock private IpConnectivityLog mMetricsLog; 176 @Mock private FileDescriptor mFd; 177 @Mock private PrintWriter mWriter; 178 @Mock private IpClientNetlinkMonitor mNetlinkMonitor; 179 180 private InterfaceParams mIfParams; 181 private INetlinkMessageProcessor mNetlinkMessageProcessor; 182 183 @Before setUp()184 public void setUp() throws Exception { 185 MockitoAnnotations.initMocks(this); 186 187 when(mContext.getSystemService(eq(Context.ALARM_SERVICE))).thenReturn(mAlarm); 188 when(mContext.getSystemService(eq(ConnectivityManager.class))).thenReturn(mCm); 189 when(mContext.getResources()).thenReturn(mResources); 190 when(mDependencies.getNetd(any())).thenReturn(mNetd); 191 when(mCm.shouldAvoidBadWifi()).thenReturn(true); 192 when(mContext.getContentResolver()).thenReturn(mContentResolver); 193 when(mNetworkStackServiceManager.getIpMemoryStoreService()) 194 .thenReturn(mIpMemoryStoreService); 195 when(mDependencies.getInterfaceParams(any())).thenReturn(mInterfaceParams); 196 when(mDependencies.getIpMemoryStore(mContext, mNetworkStackServiceManager)) 197 .thenReturn(mIpMemoryStore); 198 when(mDependencies.getIpConnectivityLog()).thenReturn(mMetricsLog); 199 when(mDependencies.getDeviceConfigPropertyInt(eq(CONFIG_SOCKET_RECV_BUFSIZE), anyInt())) 200 .thenReturn(SOCKET_RECV_BUFSIZE); 201 when(mDependencies.makeIpClientNetlinkMonitor( 202 any(), any(), any(), anyInt(), any())).thenReturn(mNetlinkMonitor); 203 when(mNetlinkMonitor.start()).thenReturn(true); 204 205 mIfParams = null; 206 } 207 setTestInterfaceParams(String ifname)208 private void setTestInterfaceParams(String ifname) { 209 mIfParams = (ifname != null) 210 ? new InterfaceParams(ifname, TEST_IFINDEX, TEST_MAC) 211 : null; 212 when(mDependencies.getInterfaceParams(anyString())).thenReturn(mIfParams); 213 } 214 makeIpClient(String ifname)215 private IpClient makeIpClient(String ifname) throws Exception { 216 setTestInterfaceParams(ifname); 217 final IpClient ipc = 218 new IpClient(mContext, ifname, mCb, mNetworkStackServiceManager, mDependencies); 219 verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(ifname, false); 220 verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(ifname); 221 final ArgumentCaptor<INetlinkMessageProcessor> processorCaptor = 222 ArgumentCaptor.forClass(INetlinkMessageProcessor.class); 223 verify(mDependencies).makeIpClientNetlinkMonitor(any(), any(), any(), anyInt(), 224 processorCaptor.capture()); 225 mNetlinkMessageProcessor = processorCaptor.getValue(); 226 reset(mNetd); 227 // Verify IpClient doesn't call onLinkPropertiesChange() when it starts. 228 verify(mCb, never()).onLinkPropertiesChange(any()); 229 reset(mCb); 230 return ipc; 231 } 232 makeEmptyLinkProperties(String iface)233 private static LinkProperties makeEmptyLinkProperties(String iface) { 234 final LinkProperties empty = new LinkProperties(); 235 empty.setInterfaceName(iface); 236 return empty; 237 } 238 verifyNetworkAttributesStored(final String l2Key, final NetworkAttributes attributes)239 private void verifyNetworkAttributesStored(final String l2Key, 240 final NetworkAttributes attributes) { 241 // TODO : when storing is implemented, turn this on 242 // verify(mIpMemoryStore).storeNetworkAttributes(eq(l2Key), eq(attributes), any()); 243 } 244 makeNetlinkMessageHeader(short type, short flags)245 private static StructNlMsgHdr makeNetlinkMessageHeader(short type, short flags) { 246 final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr(); 247 nlmsghdr.nlmsg_type = type; 248 nlmsghdr.nlmsg_flags = flags; 249 nlmsghdr.nlmsg_seq = 1; 250 return nlmsghdr; 251 } 252 buildRtmAddressMessage(short type, final LinkAddress la, int ifindex, int flags)253 private static RtNetlinkAddressMessage buildRtmAddressMessage(short type, final LinkAddress la, 254 int ifindex, int flags) { 255 final StructNlMsgHdr nlmsghdr = 256 makeNetlinkMessageHeader(type, (short) (NLM_F_REQUEST | NLM_F_ACK)); 257 InetAddress ip = la.getAddress(); 258 final byte family = 259 (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET); 260 StructIfaddrMsg ifaddrMsg = new StructIfaddrMsg(family, 261 (short) la.getPrefixLength(), 262 (short) la.getFlags(), (short) la.getScope(), ifindex); 263 264 return new RtNetlinkAddressMessage(nlmsghdr, ifaddrMsg, ip, 265 null /* structIfacacheInfo */, flags); 266 } 267 buildRtmRouteMessage(short type, final RouteInfo route, int ifindex)268 private static RtNetlinkRouteMessage buildRtmRouteMessage(short type, final RouteInfo route, 269 int ifindex) { 270 final StructNlMsgHdr nlmsghdr = 271 makeNetlinkMessageHeader(type, (short) (NLM_F_REQUEST | NLM_F_ACK)); 272 final IpPrefix destination = route.getDestination(); 273 final byte family = (byte) ((destination.getAddress() instanceof Inet6Address) 274 ? OsConstants.AF_INET6 275 : OsConstants.AF_INET); 276 277 final StructRtMsg rtMsg = new StructRtMsg(family, 278 (short) destination.getPrefixLength() /* dstLen */, (short) 0 /* srcLen */, 279 (short) 0 /* tos */, (short) 0xfd /* main table */, RTPROT_KERNEL /* protocol */, 280 (short) RT_SCOPE_UNIVERSE /* scope */, RTN_UNICAST /* type */, 0 /* flags */); 281 return new RtNetlinkRouteMessage(nlmsghdr, rtMsg, null /* source */, route.getDestination(), 282 route.getGateway(), 0 /* iif */, ifindex /* oif */, null /* cacheInfo */); 283 } 284 buildNduseroptMessage(int ifindex, long lifetime, final String[] servers)285 private static NduseroptMessage buildNduseroptMessage(int ifindex, long lifetime, 286 final String[] servers) { 287 final StructNlMsgHdr nlmsghdr = 288 makeNetlinkMessageHeader(RTM_NEWNDUSEROPT, (short) (NLM_F_REQUEST | NLM_F_ACK)); 289 final Inet6Address[] serverArray = new Inet6Address[servers.length]; 290 for (int i = 0; i < servers.length; i++) { 291 serverArray[i] = (Inet6Address) InetAddresses.parseNumericAddress(servers[i]); 292 } 293 final StructNdOptRdnss option = new StructNdOptRdnss(serverArray, lifetime); 294 return new NduseroptMessage(nlmsghdr, (byte) OsConstants.AF_INET6 /* family */, 295 0 /* opts_len */, ifindex, (byte) ICMPV6_ROUTER_ADVERTISEMENT /* icmp_type */, 296 (byte) 0 /* icmp_code */, option, null /* srcaddr */); 297 } 298 onInterfaceAddressUpdated(final LinkAddress la, int flags)299 private void onInterfaceAddressUpdated(final LinkAddress la, int flags) { 300 final RtNetlinkAddressMessage msg = 301 buildRtmAddressMessage(RTM_NEWADDR, la, TEST_IFINDEX, flags); 302 mNetlinkMessageProcessor.processNetlinkMessage(msg, TEST_UNUSED_REAL_TIME /* whenMs */); 303 } 304 onRouteUpdated(final RouteInfo route)305 private void onRouteUpdated(final RouteInfo route) { 306 final RtNetlinkRouteMessage msg = buildRtmRouteMessage(RTM_NEWROUTE, route, TEST_IFINDEX); 307 mNetlinkMessageProcessor.processNetlinkMessage(msg, TEST_UNUSED_REAL_TIME /* whenMs */); 308 } 309 onRouteRemoved(final RouteInfo route)310 private void onRouteRemoved(final RouteInfo route) { 311 final RtNetlinkRouteMessage msg = buildRtmRouteMessage(RTM_DELROUTE, route, TEST_IFINDEX); 312 mNetlinkMessageProcessor.processNetlinkMessage(msg, TEST_UNUSED_REAL_TIME /* whenMs */); 313 } 314 onInterfaceDnsServerInfo(long lifetime, final String[] dnsServers)315 private void onInterfaceDnsServerInfo(long lifetime, final String[] dnsServers) { 316 final NduseroptMessage msg = buildNduseroptMessage(TEST_IFINDEX, lifetime, dnsServers); 317 mNetlinkMessageProcessor.processNetlinkMessage(msg, TEST_UNUSED_REAL_TIME /* whenMs */); 318 } 319 320 @Test testNullInterfaceNameMostDefinitelyThrows()321 public void testNullInterfaceNameMostDefinitelyThrows() throws Exception { 322 setTestInterfaceParams(null); 323 try { 324 final IpClient ipc = new IpClient(mContext, null, mCb, mNetworkStackServiceManager, 325 mDependencies); 326 ipc.shutdown(); 327 fail(); 328 } catch (NullPointerException npe) { 329 // Phew; null interface names not allowed. 330 } 331 } 332 333 @Test testNullCallbackMostDefinitelyThrows()334 public void testNullCallbackMostDefinitelyThrows() throws Exception { 335 final String ifname = "lo"; 336 setTestInterfaceParams(ifname); 337 try { 338 final IpClient ipc = new IpClient(mContext, ifname, null, mNetworkStackServiceManager, 339 mDependencies); 340 ipc.shutdown(); 341 fail(); 342 } catch (NullPointerException npe) { 343 // Phew; null callbacks not allowed. 344 } 345 } 346 347 @Test testInvalidInterfaceDoesNotThrow()348 public void testInvalidInterfaceDoesNotThrow() throws Exception { 349 setTestInterfaceParams(TEST_IFNAME); 350 final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mNetworkStackServiceManager, 351 mDependencies); 352 verifyNoMoreInteractions(mIpMemoryStore); 353 ipc.shutdown(); 354 } 355 356 @Test testInterfaceNotFoundFailsImmediately()357 public void testInterfaceNotFoundFailsImmediately() throws Exception { 358 setTestInterfaceParams(null); 359 final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mNetworkStackServiceManager, 360 mDependencies); 361 ipc.startProvisioning(new ProvisioningConfiguration()); 362 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningFailure(any()); 363 verify(mIpMemoryStore, never()).storeNetworkAttributes(any(), any(), any()); 364 ipc.shutdown(); 365 } 366 makeIPv6ProvisionedLinkProperties()367 private LinkProperties makeIPv6ProvisionedLinkProperties() { 368 // Add local addresses, and a global address with global scope 369 final Set<LinkAddress> addresses = links(TEST_LOCAL_ADDRESSES); 370 addresses.add(new LinkAddress(TEST_GLOBAL_ADDRESS, 0, RT_SCOPE_UNIVERSE)); 371 372 // Add a route on the interface for each prefix, and a global route 373 final Set<RouteInfo> routes = routes(TEST_PREFIXES); 374 routes.add(defaultIPV6Route(TEST_IPV6_GATEWAY)); 375 376 return linkproperties(addresses, routes, ips(TEST_DNSES)); 377 } 378 doProvisioningWithDefaultConfiguration()379 private IpClient doProvisioningWithDefaultConfiguration() throws Exception { 380 final IpClient ipc = makeIpClient(TEST_IFNAME); 381 382 ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() 383 .withoutIPv4() 384 // TODO: mock IpReachabilityMonitor's dependencies (NetworkInterface, PowerManager) 385 // and enable it in this test 386 .withoutIpReachabilityMonitor() 387 .build(); 388 389 ipc.startProvisioning(config); 390 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setNeighborDiscoveryOffload(true); 391 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false); 392 393 final LinkProperties lp = makeIPv6ProvisionedLinkProperties(); 394 lp.getRoutes().forEach(route -> onRouteUpdated(route)); 395 lp.getLinkAddresses().forEach( 396 la -> onInterfaceAddressUpdated(la, la.getFlags())); 397 onInterfaceDnsServerInfo(TEST_DNS_LIFETIME, 398 lp.getDnsServers().stream().map(InetAddress::getHostAddress) 399 .toArray(String[]::new)); 400 401 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 402 verify(mCb, never()).onProvisioningFailure(any()); 403 verify(mIpMemoryStore, never()).storeNetworkAttributes(any(), any(), any()); 404 405 verify(mCb).onProvisioningSuccess(lp); 406 return ipc; 407 } 408 409 @SuppressLint("NewApi") addIPv4Provisioning(LinkProperties lp)410 private void addIPv4Provisioning(LinkProperties lp) { 411 final LinkAddress la = new LinkAddress(TEST_IPV4_LINKADDRESS); 412 final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), 413 InetAddresses.parseNumericAddress(TEST_IPV4_GATEWAY), TEST_IFNAME); 414 onInterfaceAddressUpdated(la, la.getFlags()); 415 onRouteUpdated(defaultRoute); 416 417 lp.addLinkAddress(la); 418 lp.addRoute(defaultRoute); 419 } 420 421 /** 422 * Simulate loss of IPv6 provisioning (default route lost). 423 * 424 * @return The expected new LinkProperties. 425 */ doIPv6ProvisioningLoss(LinkProperties lp)426 private void doIPv6ProvisioningLoss(LinkProperties lp) { 427 final RouteInfo defaultRoute = defaultIPV6Route(TEST_IPV6_GATEWAY); 428 onRouteRemoved(defaultRoute); 429 430 lp.removeRoute(defaultRoute); 431 } 432 doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(boolean avoidBadWifi)433 private void doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(boolean avoidBadWifi) 434 throws Exception { 435 when(mCm.shouldAvoidBadWifi()).thenReturn(avoidBadWifi); 436 final IpClient ipc = doProvisioningWithDefaultConfiguration(); 437 final LinkProperties lp = makeIPv6ProvisionedLinkProperties(); 438 439 reset(mCb); 440 doIPv6ProvisioningLoss(lp); 441 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 442 verify(mCb).onProvisioningFailure(lp); 443 verify(mCb).onLinkPropertiesChange(makeEmptyLinkProperties(TEST_IFNAME)); 444 445 verifyShutdown(ipc); 446 } 447 448 @Test testDefaultIPv6ProvisioningConfiguration_AvoidBadWifi()449 public void testDefaultIPv6ProvisioningConfiguration_AvoidBadWifi() throws Exception { 450 doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(true /* avoidBadWifi */); 451 } 452 453 @Test testDefaultIPv6ProvisioningConfiguration_StayOnBadWifi()454 public void testDefaultIPv6ProvisioningConfiguration_StayOnBadWifi() throws Exception { 455 // Even when avoidBadWifi=false, if IPv6 only, loss of all provisioning causes 456 // onProvisioningFailure to be called. 457 doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(false /* avoidBadWifi */); 458 } 459 doDefaultDualStackProvisioningConfigurationTest( boolean avoidBadWifi)460 private void doDefaultDualStackProvisioningConfigurationTest( 461 boolean avoidBadWifi) throws Exception { 462 when(mCm.shouldAvoidBadWifi()).thenReturn(avoidBadWifi); 463 final IpClient ipc = doProvisioningWithDefaultConfiguration(); 464 final LinkProperties lp = makeIPv6ProvisionedLinkProperties(); 465 addIPv4Provisioning(lp); 466 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 467 468 reset(mCb); 469 doIPv6ProvisioningLoss(lp); 470 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 471 if (avoidBadWifi) { // Provisioning failure is expected only when avoidBadWifi is true 472 verify(mCb).onProvisioningFailure(lp); 473 verify(mCb).onLinkPropertiesChange(makeEmptyLinkProperties(TEST_IFNAME)); 474 } else { 475 verify(mCb, never()).onProvisioningFailure(any()); 476 verify(mCb).onLinkPropertiesChange(lp); 477 } 478 479 verifyShutdown(ipc); 480 } 481 482 @Test testDefaultDualStackProvisioningConfiguration_AvoidBadWifi()483 public void testDefaultDualStackProvisioningConfiguration_AvoidBadWifi() throws Exception { 484 doDefaultDualStackProvisioningConfigurationTest(true /* avoidBadWifi */); 485 } 486 487 @Test testDefaultDualStackProvisioningConfiguration_StayOnBadWifi()488 public void testDefaultDualStackProvisioningConfiguration_StayOnBadWifi() throws Exception { 489 doDefaultDualStackProvisioningConfigurationTest(false /* avoidBadWifi */); 490 } 491 492 @Test testProvisioningWithInitialConfiguration()493 public void testProvisioningWithInitialConfiguration() throws Exception { 494 final String iface = TEST_IFNAME; 495 final IpClient ipc = makeIpClient(iface); 496 final String l2Key = TEST_L2KEY; 497 final String cluster = TEST_CLUSTER; 498 499 ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() 500 .withoutIPv4() 501 .withoutIpReachabilityMonitor() 502 .withInitialConfiguration( 503 conf(links(TEST_LOCAL_ADDRESSES), prefixes(TEST_PREFIXES), ips())) 504 .build(); 505 506 ipc.startProvisioning(config); 507 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setNeighborDiscoveryOffload(true); 508 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false); 509 verify(mCb, never()).onProvisioningFailure(any()); 510 ipc.setL2KeyAndCluster(l2Key, cluster); 511 512 for (String addr : TEST_LOCAL_ADDRESSES) { 513 String[] parts = addr.split("/"); 514 verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)) 515 .interfaceAddAddress(iface, parts[0], Integer.parseInt(parts[1])); 516 } 517 518 final int lastAddr = TEST_LOCAL_ADDRESSES.length - 1; 519 520 // Add N - 1 addresses 521 for (int i = 0; i < lastAddr; i++) { 522 onInterfaceAddressUpdated(new LinkAddress(TEST_LOCAL_ADDRESSES[i]), 0 /* flags */); 523 verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(any()); 524 reset(mCb); 525 } 526 527 // Add Nth address 528 onInterfaceAddressUpdated(new LinkAddress(TEST_LOCAL_ADDRESSES[lastAddr]), 0 /* flags */); 529 LinkProperties want = linkproperties(links(TEST_LOCAL_ADDRESSES), 530 routes(TEST_PREFIXES), emptySet() /* dnses */); 531 want.setInterfaceName(iface); 532 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningSuccess(want); 533 verifyNetworkAttributesStored(l2Key, new NetworkAttributes.Builder() 534 .setCluster(cluster) 535 .build()); 536 537 verifyShutdown(ipc); 538 } 539 verifyShutdown(IpClient ipc)540 private void verifyShutdown(IpClient ipc) throws Exception { 541 ipc.shutdown(); 542 verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(TEST_IFNAME, false); 543 verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(TEST_IFNAME); 544 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)) 545 .onLinkPropertiesChange(makeEmptyLinkProperties(TEST_IFNAME)); 546 verifyNoMoreInteractions(mIpMemoryStore); 547 } 548 549 @Test testIsProvisioned()550 public void testIsProvisioned() throws Exception { 551 final IpClient ipc = makeIpClient(TEST_IFNAME); 552 InitialConfiguration empty = conf(links(), prefixes()); 553 IsProvisionedTestCase[] testcases = { 554 // nothing 555 notProvisionedCase(links(), routes(), dns(), null), 556 notProvisionedCase(links(), routes(), dns(), empty), 557 558 // IPv4 559 provisionedCase(links("192.0.2.12/24"), routes(), dns(), empty), 560 561 // IPv6 562 notProvisionedCase( 563 links("fe80::a4be:f92:e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 564 routes(), dns(), empty), 565 notProvisionedCase( 566 links("fe80::a4be:f92:e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 567 routes("fe80::/64", "fd2c:4e57:8e3c::/64"), dns("fd00:1234:5678::1000"), empty), 568 provisionedCase( 569 links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"), 570 routes("::/0"), 571 dns("2001:db8:dead:beef:f00::02"), empty), 572 573 // Initial configuration 574 provisionedCase( 575 links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 576 routes("fe80::/64", "fd2c:4e57:8e3c::/64"), 577 dns(), 578 conf(links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 579 prefixes("fe80::/64", "fd2c:4e57:8e3c::/64"), ips())), 580 581 // Test case with excluded route 582 notProvisionedCase( 583 links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 584 routes( 585 routes("fe80::/64"), 586 excludedRoutes("fd2c:4e57:8e3c::/64")), 587 dns(), 588 conf(links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 589 prefixes("fe80::/64", "fd2c:4e57:8e3c::/64"), ips())) 590 }; 591 592 for (IsProvisionedTestCase testcase : testcases) { 593 if (ipc.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) { 594 fail(testcase.errorMessage()); 595 } 596 } 597 598 ipc.shutdown(); 599 } 600 601 static class IsProvisionedTestCase { 602 boolean isProvisioned; 603 LinkProperties lp; 604 InitialConfiguration config; 605 errorMessage()606 String errorMessage() { 607 return String.format("expected %s with config %s to be %s, but was %s", 608 lp, config, provisioned(isProvisioned), provisioned(!isProvisioned)); 609 } 610 provisioned(boolean isProvisioned)611 static String provisioned(boolean isProvisioned) { 612 return isProvisioned ? "provisioned" : "not provisioned"; 613 } 614 } 615 provisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config)616 static IsProvisionedTestCase provisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, 617 Set<InetAddress> lpDns, InitialConfiguration config) { 618 return provisioningTest(true, lpAddrs, lpRoutes, lpDns, config); 619 } 620 notProvisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config)621 static IsProvisionedTestCase notProvisionedCase(Set<LinkAddress> lpAddrs, 622 Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) { 623 return provisioningTest(false, lpAddrs, lpRoutes, lpDns, config); 624 } 625 provisioningTest(boolean isProvisioned, Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config)626 static IsProvisionedTestCase provisioningTest(boolean isProvisioned, Set<LinkAddress> lpAddrs, 627 Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) { 628 IsProvisionedTestCase testcase = new IsProvisionedTestCase(); 629 testcase.isProvisioned = isProvisioned; 630 testcase.lp = makeEmptyLinkProperties(TEST_IFNAME); 631 testcase.lp.setLinkAddresses(lpAddrs); 632 for (RouteInfo route : lpRoutes) { 633 testcase.lp.addRoute(route); 634 } 635 for (InetAddress dns : lpDns) { 636 testcase.lp.addDnsServer(dns); 637 } 638 testcase.config = config; 639 return testcase; 640 } 641 642 @Test testInitialConfigurations()643 public void testInitialConfigurations() throws Exception { 644 InitialConfigurationTestCase[] testcases = { 645 validConf("valid IPv4 configuration", 646 links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns("192.0.2.2")), 647 validConf("another valid IPv4 configuration", 648 links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns()), 649 validConf("valid IPv6 configurations", 650 links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"), 651 prefixes("2001:db8:dead:beef::/64", "fe80::/64"), 652 dns("2001:db8:dead:beef:f00::02")), 653 validConf("valid IPv6 configurations", 654 links("fe80::1/64"), prefixes("fe80::/64"), dns()), 655 validConf("valid IPv6/v4 configuration", 656 links("2001:db8:dead:beef:f00::a0/48", "192.0.2.12/24"), 657 prefixes("2001:db8:dead:beef::/64", "192.0.2.0/24"), 658 dns("192.0.2.2", "2001:db8:dead:beef:f00::02")), 659 validConf("valid IPv6 configuration without any GUA.", 660 links("fd00:1234:5678::1/48"), 661 prefixes("fd00:1234:5678::/48"), 662 dns("fd00:1234:5678::1000")), 663 664 invalidConf("empty configuration", links(), prefixes(), dns()), 665 invalidConf("v4 addr and dns not in any prefix", 666 links("192.0.2.12/24"), prefixes("198.51.100.0/24"), dns("192.0.2.2")), 667 invalidConf("v4 addr not in any prefix", 668 links("198.51.2.12/24"), prefixes("198.51.100.0/24"), dns("192.0.2.2")), 669 invalidConf("v4 dns addr not in any prefix", 670 links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns("198.51.100.2")), 671 invalidConf("v6 addr not in any prefix", 672 links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"), 673 prefixes("2001:db8:dead:beef::/64"), 674 dns("2001:db8:dead:beef:f00::02")), 675 invalidConf("v6 dns addr not in any prefix", 676 links("fe80::1/64"), prefixes("fe80::/64"), dns("2001:db8:dead:beef:f00::02")), 677 invalidConf("default ipv6 route and no GUA", 678 links("fd01:1111:2222:3333::a0/128"), prefixes("::/0"), dns()), 679 invalidConf("invalid v6 prefix length", 680 links("2001:db8:dead:beef:f00::a0/128"), prefixes("2001:db8:dead:beef::/32"), 681 dns()), 682 invalidConf("another invalid v6 prefix length", 683 links("2001:db8:dead:beef:f00::a0/128"), prefixes("2001:db8:dead:beef::/72"), 684 dns()) 685 }; 686 687 for (InitialConfigurationTestCase testcase : testcases) { 688 if (testcase.config.isValid() != testcase.isValid) { 689 fail(testcase.errorMessage()); 690 } 691 } 692 } 693 694 static class InitialConfigurationTestCase { 695 String descr; 696 boolean isValid; 697 InitialConfiguration config; errorMessage()698 public String errorMessage() { 699 return String.format("%s: expected configuration %s to be %s, but was %s", 700 descr, config, validString(isValid), validString(!isValid)); 701 } validString(boolean isValid)702 static String validString(boolean isValid) { 703 return isValid ? VALID : INVALID; 704 } 705 } 706 validConf(String descr, Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns)707 static InitialConfigurationTestCase validConf(String descr, Set<LinkAddress> links, 708 Set<IpPrefix> prefixes, Set<InetAddress> dns) { 709 return confTestCase(descr, true, conf(links, prefixes, dns)); 710 } 711 invalidConf(String descr, Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns)712 static InitialConfigurationTestCase invalidConf(String descr, Set<LinkAddress> links, 713 Set<IpPrefix> prefixes, Set<InetAddress> dns) { 714 return confTestCase(descr, false, conf(links, prefixes, dns)); 715 } 716 confTestCase( String descr, boolean isValid, InitialConfiguration config)717 static InitialConfigurationTestCase confTestCase( 718 String descr, boolean isValid, InitialConfiguration config) { 719 InitialConfigurationTestCase testcase = new InitialConfigurationTestCase(); 720 testcase.descr = descr; 721 testcase.isValid = isValid; 722 testcase.config = config; 723 return testcase; 724 } 725 linkproperties(Set<LinkAddress> addresses, Set<RouteInfo> routes, Set<InetAddress> dnses)726 static LinkProperties linkproperties(Set<LinkAddress> addresses, 727 Set<RouteInfo> routes, Set<InetAddress> dnses) { 728 LinkProperties lp = makeEmptyLinkProperties(TEST_IFNAME); 729 lp.setLinkAddresses(addresses); 730 routes.forEach(lp::addRoute); 731 dnses.forEach(lp::addDnsServer); 732 return lp; 733 } 734 conf(Set<LinkAddress> links, Set<IpPrefix> prefixes)735 static InitialConfiguration conf(Set<LinkAddress> links, Set<IpPrefix> prefixes) { 736 return conf(links, prefixes, new HashSet<>()); 737 } 738 conf( Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns)739 static InitialConfiguration conf( 740 Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns) { 741 InitialConfiguration conf = new InitialConfiguration(); 742 conf.ipAddresses.addAll(links); 743 conf.directlyConnectedRoutes.addAll(prefixes); 744 conf.dnsServers.addAll(dns); 745 return conf; 746 } 747 routes(String... routes)748 static Set<RouteInfo> routes(String... routes) { 749 return mapIntoSet(routes, (r) -> new RouteInfo(new IpPrefix(r), null /* gateway */, 750 TEST_IFNAME)); 751 } 752 excludedRoutes(String... excludedRoutes)753 static Set<RouteInfo> excludedRoutes(String... excludedRoutes) { 754 return mapIntoSet(excludedRoutes, (r) -> new RouteInfo(new IpPrefix(r), null /* gateway */, 755 TEST_IFNAME, RouteInfo.RTN_THROW)); 756 } 757 routes(Set<RouteInfo> includedRoutes, Set<RouteInfo> excludedRoutes)758 static Set<RouteInfo> routes(Set<RouteInfo> includedRoutes, Set<RouteInfo> excludedRoutes) { 759 Set<RouteInfo> result = new HashSet<>(includedRoutes.size() + excludedRoutes.size()); 760 761 result.addAll(includedRoutes); 762 result.addAll(excludedRoutes); 763 764 return result; 765 } 766 767 @SuppressLint("NewApi") defaultIPV6Route(String gateway)768 static RouteInfo defaultIPV6Route(String gateway) { 769 return new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), 770 InetAddresses.parseNumericAddress(gateway), TEST_IFNAME); 771 } 772 prefixes(String... prefixes)773 static Set<IpPrefix> prefixes(String... prefixes) { 774 return mapIntoSet(prefixes, IpPrefix::new); 775 } 776 links(String... addresses)777 static Set<LinkAddress> links(String... addresses) { 778 return mapIntoSet(addresses, LinkAddress::new); 779 } 780 ips(String... addresses)781 static Set<InetAddress> ips(String... addresses) { 782 return mapIntoSet(addresses, InetAddress::getByName); 783 } 784 dns(String... addresses)785 static Set<InetAddress> dns(String... addresses) { 786 return ips(addresses); 787 } 788 mapIntoSet(A[] in, Fn<A, B> fn)789 static <A, B> Set<B> mapIntoSet(A[] in, Fn<A, B> fn) { 790 Set<B> out = new HashSet<>(in.length); 791 for (A item : in) { 792 try { 793 out.add(fn.call(item)); 794 } catch (Exception e) { 795 throw new RuntimeException(e); 796 } 797 } 798 return out; 799 } 800 verifyApfFilterCreatedOnStart(IpClient ipc, boolean isApfSupported)801 private ApfConfiguration verifyApfFilterCreatedOnStart(IpClient ipc, boolean isApfSupported) { 802 ProvisioningConfiguration.Builder config = new ProvisioningConfiguration.Builder() 803 .withoutIPv4() 804 .withoutIpReachabilityMonitor() 805 .withInitialConfiguration( 806 conf(links(TEST_LOCAL_ADDRESSES), prefixes(TEST_PREFIXES), ips())); 807 if (isApfSupported) { 808 config.withApfCapabilities(new ApfCapabilities(4 /* version */, 809 4096 /* maxProgramSize */, 4 /* format */)); 810 } 811 812 ipc.startProvisioning(config.build()); 813 final ArgumentCaptor<ApfConfiguration> configCaptor = ArgumentCaptor.forClass( 814 ApfConfiguration.class); 815 verify(mDependencies, timeout(TEST_TIMEOUT_MS)).maybeCreateApfFilter( 816 any(), configCaptor.capture(), any(), any(), any(), anyBoolean()); 817 818 return configCaptor.getValue(); 819 } 820 821 @Test @IgnoreAfter(Build.VERSION_CODES.R) testApfConfiguration_R()822 public void testApfConfiguration_R() throws Exception { 823 final IpClient ipc = makeIpClient(TEST_IFNAME); 824 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 825 true /* isApfSupported */); 826 827 assertEquals(ApfCapabilities.getApfDrop8023Frames(), config.ieee802_3Filter); 828 assertArrayEquals(ApfCapabilities.getApfEtherTypeBlackList(), config.ethTypeBlackList); 829 830 verify(mResources, never()).getBoolean(R.bool.config_apfDrop802_3Frames); 831 verify(mResources, never()).getIntArray(R.array.config_apfEthTypeDenyList); 832 833 verifyShutdown(ipc); 834 } 835 836 @Test @IgnoreUpTo(Build.VERSION_CODES.R) testApfConfiguration()837 public void testApfConfiguration() throws Exception { 838 doReturn(true).when(mResources).getBoolean(R.bool.config_apfDrop802_3Frames); 839 final int[] ethTypeDenyList = new int[] { 0x88A2, 0x88A4 }; 840 doReturn(ethTypeDenyList).when(mResources).getIntArray( 841 R.array.config_apfEthTypeDenyList); 842 843 final IpClient ipc = makeIpClient(TEST_IFNAME); 844 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 845 true /* isApfSupported */); 846 847 assertTrue(config.ieee802_3Filter); 848 assertArrayEquals(ethTypeDenyList, config.ethTypeBlackList); 849 850 verifyShutdown(ipc); 851 } 852 853 @Test @IgnoreUpTo(Build.VERSION_CODES.R) testApfConfiguration_NoApfDrop8023Frames()854 public void testApfConfiguration_NoApfDrop8023Frames() throws Exception { 855 doReturn(false).when(mResources).getBoolean(R.bool.config_apfDrop802_3Frames); 856 final int[] ethTypeDenyList = new int[] { 0x88A3, 0x88A5 }; 857 doReturn(ethTypeDenyList).when(mResources).getIntArray( 858 R.array.config_apfEthTypeDenyList); 859 860 final IpClient ipc = makeIpClient(TEST_IFNAME); 861 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 862 true /* isApfSupported */); 863 864 assertFalse(config.ieee802_3Filter); 865 assertArrayEquals(ethTypeDenyList, config.ethTypeBlackList); 866 867 verifyShutdown(ipc); 868 } 869 870 @Test testApfUpdateCapabilities()871 public void testApfUpdateCapabilities() throws Exception { 872 final IpClient ipc = makeIpClient(TEST_IFNAME); 873 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 874 false /* isApfSupported */); 875 assertNull(config.apfCapabilities); 876 clearInvocations(mDependencies); 877 878 ipc.updateApfCapabilities(new ApfCapabilities(4 /* version */, 4096 /* maxProgramSize */, 879 4 /* format */)); 880 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 881 882 final ArgumentCaptor<ApfConfiguration> configCaptor = ArgumentCaptor.forClass( 883 ApfConfiguration.class); 884 verify(mDependencies, timeout(TEST_TIMEOUT_MS)).maybeCreateApfFilter( 885 any(), configCaptor.capture(), any(), any(), any(), anyBoolean()); 886 final ApfConfiguration actual = configCaptor.getValue(); 887 assertNotNull(actual); 888 int expectedApfVersion = SdkLevel.isAtLeastS() ? 4 : 3; 889 assertEquals(expectedApfVersion, actual.apfCapabilities.apfVersionSupported); 890 assertEquals(4096, actual.apfCapabilities.maximumApfProgramSize); 891 assertEquals(4, actual.apfCapabilities.apfPacketFormat); 892 893 verifyShutdown(ipc); 894 } 895 896 @Test testDumpApfFilter_withNoException()897 public void testDumpApfFilter_withNoException() throws Exception { 898 final IpClient ipc = makeIpClient(TEST_IFNAME); 899 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 900 false /* isApfSupported */); 901 assertNull(config.apfCapabilities); 902 clearInvocations(mDependencies); 903 ipc.dump(mFd, mWriter, null /* args */); 904 verifyShutdown(ipc); 905 } 906 907 @Test testApfUpdateCapabilities_nonNullInitialApfCapabilities()908 public void testApfUpdateCapabilities_nonNullInitialApfCapabilities() throws Exception { 909 final IpClient ipc = makeIpClient(TEST_IFNAME); 910 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 911 true /* isApfSupported */); 912 assertNotNull(config.apfCapabilities); 913 clearInvocations(mDependencies); 914 915 final ApfCapabilities newApfCapabilities = new ApfCapabilities(4 /* version */, 916 8192 /* maxProgramSize */, 4 /* format */); 917 ipc.updateApfCapabilities(newApfCapabilities); 918 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 919 verify(mDependencies, never()).maybeCreateApfFilter(any(), any(), any(), any(), any(), 920 anyBoolean()); 921 verifyShutdown(ipc); 922 } 923 924 @Test testApfUpdateCapabilities_nullNewApfCapabilities()925 public void testApfUpdateCapabilities_nullNewApfCapabilities() throws Exception { 926 final IpClient ipc = makeIpClient(TEST_IFNAME); 927 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 928 true /* isApfSupported */); 929 assertNotNull(config.apfCapabilities); 930 clearInvocations(mDependencies); 931 932 ipc.updateApfCapabilities(null /* apfCapabilities */); 933 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 934 verify(mDependencies, never()).maybeCreateApfFilter(any(), any(), any(), any(), any(), 935 anyBoolean()); 936 verifyShutdown(ipc); 937 } 938 makeScanResultInfo(final String ssid, final String bssid)939 private ScanResultInfo makeScanResultInfo(final String ssid, final String bssid) { 940 final ByteBuffer payload = ByteBuffer.allocate(14 /* oui + type + data */); 941 final byte[] data = new byte[10]; 942 new Random().nextBytes(data); 943 payload.put(new byte[] { 0x00, 0x1A, 0x11 }); 944 payload.put((byte) 0x06); 945 payload.put(data); 946 947 final ScanResultInfo.InformationElement ie = 948 new ScanResultInfo.InformationElement(0xdd /* IE id */, payload); 949 return new ScanResultInfo(ssid, bssid, Collections.singletonList(ie)); 950 } 951 952 @Test testGetInitialBssidOnSOrAbove()953 public void testGetInitialBssidOnSOrAbove() throws Exception { 954 final IpClient ipc = makeIpClient(TEST_IFNAME); 955 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 956 MacAddress.fromString(TEST_BSSID)); 957 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID2); 958 final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo, 959 true /* isAtLeastS */); 960 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 961 ipc.shutdown(); 962 } 963 964 @Test testGetInitialBssidOnSOrAbove_NullScanReqsultInfo()965 public void testGetInitialBssidOnSOrAbove_NullScanReqsultInfo() throws Exception { 966 final IpClient ipc = makeIpClient(TEST_IFNAME); 967 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 968 MacAddress.fromString(TEST_BSSID)); 969 final MacAddress bssid = ipc.getInitialBssid(layer2Info, null /* ScanResultInfo */, 970 true /* isAtLeastS */); 971 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 972 ipc.shutdown(); 973 } 974 975 @Test testGetInitialBssidOnSOrAbove_NullBssid()976 public void testGetInitialBssidOnSOrAbove_NullBssid() throws Exception { 977 final IpClient ipc = makeIpClient(TEST_IFNAME); 978 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 979 null /* bssid */); 980 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID); 981 final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo, 982 true /* isAtLeastS */); 983 assertNull(bssid); 984 ipc.shutdown(); 985 } 986 987 @Test testGetInitialBssidOnSOrAbove_NullLayer2Info()988 public void testGetInitialBssidOnSOrAbove_NullLayer2Info() throws Exception { 989 final IpClient ipc = makeIpClient(TEST_IFNAME); 990 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID); 991 final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo, 992 true /* isAtLeastS */); 993 assertNull(bssid); 994 ipc.shutdown(); 995 } 996 997 @Test testGetInitialBssidBeforeS()998 public void testGetInitialBssidBeforeS() throws Exception { 999 final IpClient ipc = makeIpClient(TEST_IFNAME); 1000 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 1001 MacAddress.fromString(TEST_BSSID2)); 1002 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID); 1003 final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo, 1004 false /* isAtLeastS */); 1005 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 1006 ipc.shutdown(); 1007 } 1008 1009 @Test testGetInitialBssidBeforeS_NullLayer2Info()1010 public void testGetInitialBssidBeforeS_NullLayer2Info() throws Exception { 1011 final IpClient ipc = makeIpClient(TEST_IFNAME); 1012 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID); 1013 final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo, 1014 false /* isAtLeastS */); 1015 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 1016 ipc.shutdown(); 1017 } 1018 1019 @Test testGetInitialBssidBeforeS_BrokenInitialBssid()1020 public void testGetInitialBssidBeforeS_BrokenInitialBssid() throws Exception { 1021 final IpClient ipc = makeIpClient(TEST_IFNAME); 1022 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, "00:11:22:33:44:"); 1023 final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo, 1024 false /* isAtLeastS */); 1025 assertNull(bssid); 1026 ipc.shutdown(); 1027 } 1028 1029 @Test testGetInitialBssidBeforeS_BrokenInitialBssidFallback()1030 public void testGetInitialBssidBeforeS_BrokenInitialBssidFallback() throws Exception { 1031 final IpClient ipc = makeIpClient(TEST_IFNAME); 1032 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 1033 MacAddress.fromString(TEST_BSSID)); 1034 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, "00:11:22:33:44:"); 1035 final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo, 1036 false /* isAtLeastS */); 1037 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 1038 ipc.shutdown(); 1039 } 1040 1041 @Test testGetInitialBssidBeforeS_NullScanResultInfoFallback()1042 public void testGetInitialBssidBeforeS_NullScanResultInfoFallback() throws Exception { 1043 final IpClient ipc = makeIpClient(TEST_IFNAME); 1044 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 1045 MacAddress.fromString(TEST_BSSID)); 1046 final MacAddress bssid = ipc.getInitialBssid(layer2Info, null /* scanResultInfo */, 1047 false /* isAtLeastS */); 1048 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 1049 ipc.shutdown(); 1050 } 1051 1052 @Test testGetInitialBssidBeforeS_NullScanResultInfoAndLayer2Info()1053 public void testGetInitialBssidBeforeS_NullScanResultInfoAndLayer2Info() throws Exception { 1054 final IpClient ipc = makeIpClient(TEST_IFNAME); 1055 final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, 1056 null /* scanResultInfo */, false /* isAtLeastS */); 1057 assertNull(bssid); 1058 ipc.shutdown(); 1059 } 1060 1061 interface Fn<A,B> { call(A a)1062 B call(A a) throws Exception; 1063 } 1064 1065 @Test testAll()1066 public void testAll() { 1067 List<String> list1 = Arrays.asList(); 1068 List<String> list2 = Arrays.asList("foo"); 1069 List<String> list3 = Arrays.asList("bar", "baz"); 1070 List<String> list4 = Arrays.asList("foo", "bar", "baz"); 1071 1072 assertTrue(InitialConfiguration.all(list1, (x) -> false)); 1073 assertFalse(InitialConfiguration.all(list2, (x) -> false)); 1074 assertTrue(InitialConfiguration.all(list3, (x) -> true)); 1075 assertTrue(InitialConfiguration.all(list2, (x) -> x.charAt(0) == 'f')); 1076 assertFalse(InitialConfiguration.all(list4, (x) -> x.charAt(0) == 'f')); 1077 } 1078 1079 @Test testAny()1080 public void testAny() { 1081 List<String> list1 = Arrays.asList(); 1082 List<String> list2 = Arrays.asList("foo"); 1083 List<String> list3 = Arrays.asList("bar", "baz"); 1084 List<String> list4 = Arrays.asList("foo", "bar", "baz"); 1085 1086 assertFalse(InitialConfiguration.any(list1, (x) -> true)); 1087 assertTrue(InitialConfiguration.any(list2, (x) -> true)); 1088 assertTrue(InitialConfiguration.any(list2, (x) -> x.charAt(0) == 'f')); 1089 assertFalse(InitialConfiguration.any(list3, (x) -> x.charAt(0) == 'f')); 1090 assertTrue(InitialConfiguration.any(list4, (x) -> x.charAt(0) == 'f')); 1091 } 1092 1093 @Test testFindAll()1094 public void testFindAll() { 1095 List<String> list1 = Arrays.asList(); 1096 List<String> list2 = Arrays.asList("foo"); 1097 List<String> list3 = Arrays.asList("foo", "bar", "baz"); 1098 1099 assertEquals(list1, IpClient.findAll(list1, (x) -> true)); 1100 assertEquals(list1, IpClient.findAll(list3, (x) -> false)); 1101 assertEquals(list3, IpClient.findAll(list3, (x) -> true)); 1102 assertEquals(list2, IpClient.findAll(list3, (x) -> x.charAt(0) == 'f')); 1103 } 1104 } 1105