1 /* 2 * Copyright (C) 2018 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.dhcp; 18 19 import static android.net.InetAddresses.parseNumericAddress; 20 import static android.net.dhcp.DhcpPacket.DHCP_HOST_NAME; 21 import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP; 22 import static android.net.dhcp.DhcpPacket.INADDR_ANY; 23 import static android.net.dhcp.DhcpPacket.INADDR_BROADCAST; 24 import static android.net.dhcp.DhcpServer.CMD_RECEIVE_PACKET; 25 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; 26 27 import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH; 28 import static com.android.networkstack.util.NetworkStackUtils.DHCP_RAPID_COMMIT_VERSION; 29 30 import static junit.framework.Assert.assertEquals; 31 import static junit.framework.Assert.assertFalse; 32 import static junit.framework.Assert.assertNotNull; 33 import static junit.framework.Assert.assertTrue; 34 35 import static org.mockito.ArgumentMatchers.any; 36 import static org.mockito.ArgumentMatchers.eq; 37 import static org.mockito.ArgumentMatchers.isNull; 38 import static org.mockito.Mockito.doNothing; 39 import static org.mockito.Mockito.never; 40 import static org.mockito.Mockito.times; 41 import static org.mockito.Mockito.verify; 42 import static org.mockito.Mockito.when; 43 44 import android.annotation.NonNull; 45 import android.annotation.Nullable; 46 import android.content.Context; 47 import android.net.INetworkStackStatusCallback; 48 import android.net.IpPrefix; 49 import android.net.LinkAddress; 50 import android.net.MacAddress; 51 import android.net.dhcp.DhcpLeaseRepository.InvalidAddressException; 52 import android.net.dhcp.DhcpLeaseRepository.OutOfAddressesException; 53 import android.net.dhcp.DhcpServer.Clock; 54 import android.net.dhcp.DhcpServer.Dependencies; 55 import android.os.ConditionVariable; 56 import android.testing.AndroidTestingRunner; 57 58 import androidx.test.filters.SmallTest; 59 60 import com.android.net.module.util.Inet4AddressUtils; 61 import com.android.net.module.util.SharedLog; 62 import com.android.testutils.HandlerUtils; 63 64 import org.junit.After; 65 import org.junit.Before; 66 import org.junit.Test; 67 import org.junit.runner.RunWith; 68 import org.mockito.ArgumentCaptor; 69 import org.mockito.Captor; 70 import org.mockito.Mock; 71 import org.mockito.MockitoAnnotations; 72 73 import java.net.Inet4Address; 74 import java.nio.ByteBuffer; 75 import java.util.Arrays; 76 import java.util.Collection; 77 import java.util.Collections; 78 import java.util.HashSet; 79 import java.util.Set; 80 81 @RunWith(AndroidTestingRunner.class) 82 @SmallTest 83 public class DhcpServerTest { 84 private static final String TEST_IFACE = "testiface"; 85 86 private static final Inet4Address TEST_SERVER_ADDR = parseAddr("192.168.0.2"); 87 private static final int TEST_PREFIX_LENGTH = 20; 88 private static final LinkAddress TEST_SERVER_LINKADDR = new LinkAddress( 89 TEST_SERVER_ADDR, TEST_PREFIX_LENGTH); 90 private static final Set<Inet4Address> TEST_DEFAULT_ROUTERS = new HashSet<>( 91 Arrays.asList(parseAddr("192.168.0.123"), parseAddr("192.168.0.124"))); 92 private static final Set<Inet4Address> TEST_DNS_SERVERS = new HashSet<>( 93 Arrays.asList(parseAddr("192.168.0.126"), parseAddr("192.168.0.127"))); 94 private static final Set<Inet4Address> TEST_EXCLUDED_ADDRS = new HashSet<>( 95 Arrays.asList(parseAddr("192.168.0.200"), parseAddr("192.168.0.201"))); 96 private static final long TEST_LEASE_TIME_SECS = 3600L; 97 private static final int TEST_MTU = 1500; 98 private static final String TEST_HOSTNAME = "testhostname"; 99 100 private static final int TEST_TRANSACTION_ID = 123; 101 private static final byte[] TEST_CLIENT_MAC_BYTES = new byte [] { 1, 2, 3, 4, 5, 6 }; 102 private static final MacAddress TEST_CLIENT_MAC = MacAddress.fromBytes(TEST_CLIENT_MAC_BYTES); 103 private static final Inet4Address TEST_CLIENT_ADDR = parseAddr("192.168.0.42"); 104 105 private static final long TEST_CLOCK_TIME = 1234L; 106 private static final int TEST_LEASE_EXPTIME_SECS = 3600; 107 private static final DhcpLease TEST_LEASE = new DhcpLease(null, TEST_CLIENT_MAC, 108 TEST_CLIENT_ADDR, TEST_PREFIX_LENGTH, TEST_LEASE_EXPTIME_SECS * 1000L + TEST_CLOCK_TIME, 109 null /* hostname */); 110 private static final DhcpLease TEST_LEASE_WITH_HOSTNAME = new DhcpLease(null, TEST_CLIENT_MAC, 111 TEST_CLIENT_ADDR, TEST_PREFIX_LENGTH, TEST_LEASE_EXPTIME_SECS * 1000L + TEST_CLOCK_TIME, 112 TEST_HOSTNAME); 113 private static final int TEST_TIMEOUT_MS = 10000; 114 115 @NonNull @Mock 116 private Context mContext; 117 @NonNull @Mock 118 private Dependencies mDeps; 119 @NonNull @Mock 120 private DhcpLeaseRepository mRepository; 121 @NonNull @Mock 122 private Clock mClock; 123 @NonNull @Mock 124 private DhcpPacketListener mPacketListener; 125 @NonNull @Mock 126 private IDhcpEventCallbacks mEventCallbacks; 127 128 @NonNull @Captor 129 private ArgumentCaptor<ByteBuffer> mSentPacketCaptor; 130 @NonNull @Captor 131 private ArgumentCaptor<Inet4Address> mResponseDstAddrCaptor; 132 133 @NonNull 134 private MyDhcpServer mServer; 135 136 @Nullable 137 private String mPrevShareClassloaderProp; 138 139 private class MyDhcpServer extends DhcpServer { 140 private final ConditionVariable mCv = new ConditionVariable(false); 141 MyDhcpServer(Context context, String ifName, DhcpServingParams params, SharedLog log, Dependencies deps)142 MyDhcpServer(Context context, String ifName, DhcpServingParams params, SharedLog log, 143 Dependencies deps) { 144 super(context, ifName, params, log, deps); 145 } 146 147 @Override onQuitting()148 protected void onQuitting() { 149 super.onQuitting(); 150 mCv.open(); 151 } 152 waitForShutdown()153 public void waitForShutdown() { 154 assertTrue(mCv.block(TEST_TIMEOUT_MS)); 155 } 156 } 157 158 private final INetworkStackStatusCallback mAssertSuccessCallback = 159 new INetworkStackStatusCallback.Stub() { 160 @Override 161 public void onStatusAvailable(int statusCode) { 162 assertEquals(STATUS_SUCCESS, statusCode); 163 } 164 165 @Override 166 public int getInterfaceVersion() { 167 return this.VERSION; 168 } 169 170 @Override 171 public String getInterfaceHash() { 172 return this.HASH; 173 } 174 }; 175 makeServingParams()176 private DhcpServingParams makeServingParams() throws Exception { 177 return new DhcpServingParams.Builder() 178 .setDefaultRouters(TEST_DEFAULT_ROUTERS) 179 .setDhcpLeaseTimeSecs(TEST_LEASE_TIME_SECS) 180 .setDnsServers(TEST_DNS_SERVERS) 181 .setServerAddr(TEST_SERVER_LINKADDR) 182 .setLinkMtu(TEST_MTU) 183 .setExcludedAddrs(TEST_EXCLUDED_ADDRS) 184 .setChangePrefixOnDecline(false) 185 .build(); 186 } 187 startServer()188 private void startServer() throws Exception { 189 mServer.start(mAssertSuccessCallback); 190 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 191 } 192 193 @Before setUp()194 public void setUp() throws Exception { 195 MockitoAnnotations.initMocks(this); 196 197 when(mDeps.makeLeaseRepository(any(), any(), any())).thenReturn(mRepository); 198 when(mDeps.makeClock()).thenReturn(mClock); 199 when(mDeps.makePacketListener(any())).thenReturn(mPacketListener); 200 when(mDeps.isFeatureNotChickenedOut(eq(mContext), eq(DHCP_RAPID_COMMIT_VERSION))) 201 .thenReturn(true); 202 doNothing().when(mDeps) 203 .sendPacket(any(), mSentPacketCaptor.capture(), mResponseDstAddrCaptor.capture()); 204 when(mClock.elapsedRealtime()).thenReturn(TEST_CLOCK_TIME); 205 when(mPacketListener.start()).thenReturn(true); 206 207 mServer = new MyDhcpServer(mContext, TEST_IFACE, makeServingParams(), 208 new SharedLog(DhcpServerTest.class.getSimpleName()), mDeps); 209 } 210 211 @After tearDown()212 public void tearDown() throws Exception { 213 verify(mRepository, never()).addLeaseCallbacks(eq(null)); 214 mServer.stop(mAssertSuccessCallback); 215 mServer.waitForShutdown(); 216 verify(mPacketListener, times(1)).stop(); 217 } 218 219 @Test testStart()220 public void testStart() throws Exception { 221 startServer(); 222 223 verify(mPacketListener, times(1)).start(); 224 } 225 226 @Test testStartWithCallbacks()227 public void testStartWithCallbacks() throws Exception { 228 mServer.start(mAssertSuccessCallback, mEventCallbacks); 229 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 230 verify(mRepository).addLeaseCallbacks(eq(mEventCallbacks)); 231 } 232 233 @Test testDiscover()234 public void testDiscover() throws Exception { 235 startServer(); 236 237 // TODO: refactor packet construction to eliminate unnecessary/confusing/duplicate fields 238 when(mRepository.getOffer(isNull() /* clientId */, eq(TEST_CLIENT_MAC), 239 eq(INADDR_ANY) /* relayAddr */, isNull() /* reqAddr */, isNull() /* hostname */)) 240 .thenReturn(TEST_LEASE); 241 242 final DhcpDiscoverPacket discover = new DhcpDiscoverPacket(TEST_TRANSACTION_ID, 243 (short) 0 /* secs */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES, 244 false /* broadcast */, INADDR_ANY /* srcIp */, false /* rapidCommit */); 245 mServer.sendMessage(CMD_RECEIVE_PACKET, discover); 246 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 247 248 assertResponseSentTo(TEST_CLIENT_ADDR); 249 final DhcpOfferPacket packet = assertOffer(getPacket()); 250 assertMatchesTestLease(packet); 251 } 252 253 @Test testDiscover_RapidCommit()254 public void testDiscover_RapidCommit() throws Exception { 255 startServer(); 256 257 when(mDeps.isFeatureNotChickenedOut(eq(mContext), eq(DHCP_RAPID_COMMIT_VERSION))) 258 .thenReturn(true); 259 when(mRepository.getCommittedLease(isNull() /* clientId */, eq(TEST_CLIENT_MAC), 260 eq(INADDR_ANY) /* relayAddr */, isNull() /* hostname */)).thenReturn(TEST_LEASE); 261 262 final DhcpDiscoverPacket discover = new DhcpDiscoverPacket(TEST_TRANSACTION_ID, 263 (short) 0 /* secs */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES, 264 false /* broadcast */, INADDR_ANY /* srcIp */, true /* rapidCommit */); 265 mServer.sendMessage(CMD_RECEIVE_PACKET, discover); 266 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 267 268 assertResponseSentTo(TEST_CLIENT_ADDR); 269 final DhcpAckPacket packet = assertAck(getPacket()); 270 assertMatchesTestLease(packet); 271 } 272 273 @Test testDiscover_OutOfAddresses()274 public void testDiscover_OutOfAddresses() throws Exception { 275 startServer(); 276 277 when(mRepository.getOffer(isNull() /* clientId */, eq(TEST_CLIENT_MAC), 278 eq(INADDR_ANY) /* relayAddr */, isNull() /* reqAddr */, isNull() /* hostname */)) 279 .thenThrow(new OutOfAddressesException("Test exception")); 280 281 final DhcpDiscoverPacket discover = new DhcpDiscoverPacket(TEST_TRANSACTION_ID, 282 (short) 0 /* secs */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES, 283 false /* broadcast */, INADDR_ANY /* srcIp */, false /* rapidCommit */); 284 mServer.sendMessage(CMD_RECEIVE_PACKET, discover); 285 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 286 287 assertResponseSentTo(INADDR_BROADCAST); 288 final DhcpNakPacket packet = assertNak(getPacket()); 289 assertMatchesClient(packet); 290 } 291 makeRequestSelectingPacket()292 private DhcpRequestPacket makeRequestSelectingPacket() { 293 final DhcpRequestPacket request = new DhcpRequestPacket(TEST_TRANSACTION_ID, 294 (short) 0 /* secs */, INADDR_ANY /* clientIp */, INADDR_ANY /* relayIp */, 295 TEST_CLIENT_MAC_BYTES, false /* broadcast */); 296 request.mServerIdentifier = TEST_SERVER_ADDR; 297 request.mRequestedIp = TEST_CLIENT_ADDR; 298 return request; 299 } 300 301 @Test testRequest_Selecting_Ack()302 public void testRequest_Selecting_Ack() throws Exception { 303 startServer(); 304 305 when(mRepository.requestLease(isNull() /* clientId */, eq(TEST_CLIENT_MAC), 306 eq(INADDR_ANY) /* clientAddr */, eq(INADDR_ANY) /* relayAddr */, 307 eq(TEST_CLIENT_ADDR) /* reqAddr */, eq(true) /* sidSet */, eq(TEST_HOSTNAME))) 308 .thenReturn(TEST_LEASE_WITH_HOSTNAME); 309 310 final DhcpRequestPacket request = makeRequestSelectingPacket(); 311 request.mHostName = TEST_HOSTNAME; 312 request.mRequestedParams = new byte[] { DHCP_HOST_NAME }; 313 mServer.sendMessage(CMD_RECEIVE_PACKET, request); 314 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 315 316 assertResponseSentTo(TEST_CLIENT_ADDR); 317 final DhcpAckPacket packet = assertAck(getPacket()); 318 assertMatchesTestLease(packet, TEST_HOSTNAME); 319 } 320 321 @Test testRequest_Selecting_Nak()322 public void testRequest_Selecting_Nak() throws Exception { 323 startServer(); 324 325 when(mRepository.requestLease(isNull(), eq(TEST_CLIENT_MAC), 326 eq(INADDR_ANY) /* clientAddr */, eq(INADDR_ANY) /* relayAddr */, 327 eq(TEST_CLIENT_ADDR) /* reqAddr */, eq(true) /* sidSet */, isNull() /* hostname */)) 328 .thenThrow(new InvalidAddressException("Test error")); 329 330 final DhcpRequestPacket request = makeRequestSelectingPacket(); 331 mServer.sendMessage(CMD_RECEIVE_PACKET, request); 332 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 333 334 assertResponseSentTo(INADDR_BROADCAST); 335 final DhcpNakPacket packet = assertNak(getPacket()); 336 assertMatchesClient(packet); 337 } 338 339 @Test testRelease()340 public void testRelease() throws Exception { 341 startServer(); 342 343 final DhcpReleasePacket release = new DhcpReleasePacket(TEST_TRANSACTION_ID, 344 TEST_SERVER_ADDR, TEST_CLIENT_ADDR, 345 INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES); 346 mServer.sendMessage(CMD_RECEIVE_PACKET, release); 347 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 348 349 verify(mRepository, times(1)) 350 .releaseLease(isNull(), eq(TEST_CLIENT_MAC), eq(TEST_CLIENT_ADDR)); 351 } 352 353 @Test testDecline_LeaseDoesNotExist()354 public void testDecline_LeaseDoesNotExist() throws Exception { 355 when(mRepository.markAndReleaseDeclinedLease(isNull(), eq(TEST_CLIENT_MAC), 356 eq(TEST_CLIENT_ADDR))).thenReturn(false); 357 358 startServer(); 359 runOnReceivedDeclinePacket(); 360 verify(mEventCallbacks, never()).onNewPrefixRequest(any()); 361 } 362 runOnReceivedDeclinePacket()363 private void runOnReceivedDeclinePacket() throws Exception { 364 when(mRepository.getCommittedLeases()).thenReturn( 365 Arrays.asList(new DhcpLease(null, TEST_CLIENT_MAC, TEST_CLIENT_ADDR, 366 TEST_PREFIX_LENGTH, TEST_LEASE_EXPTIME_SECS * 1000L + TEST_CLOCK_TIME, 367 TEST_HOSTNAME))); 368 final DhcpDeclinePacket decline = new DhcpDeclinePacket(TEST_TRANSACTION_ID, 369 (short) 0 /* secs */, INADDR_ANY /* clientIp */, INADDR_ANY /* yourIp */, 370 INADDR_ANY /* nextIp */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES, 371 TEST_CLIENT_ADDR /* requestedIp */, TEST_SERVER_ADDR /* serverIdentifier */); 372 mServer.sendMessage(CMD_RECEIVE_PACKET, decline); 373 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 374 375 verify(mRepository).markAndReleaseDeclinedLease(isNull(), eq(TEST_CLIENT_MAC), 376 eq(TEST_CLIENT_ADDR)); 377 } 378 toIntArray(@onNull Collection<Inet4Address> addrs)379 private int[] toIntArray(@NonNull Collection<Inet4Address> addrs) { 380 return addrs.stream().mapToInt(Inet4AddressUtils::inet4AddressToIntHTH).toArray(); 381 } 382 updateServingParams(Set<Inet4Address> defaultRouters, Set<Inet4Address> dnsServers, Set<Inet4Address> excludedAddrs, LinkAddress serverAddr, boolean changePrefixOnDecline)383 private void updateServingParams(Set<Inet4Address> defaultRouters, 384 Set<Inet4Address> dnsServers, Set<Inet4Address> excludedAddrs, LinkAddress serverAddr, 385 boolean changePrefixOnDecline) throws Exception { 386 final DhcpServingParamsParcel params = new DhcpServingParamsParcel(); 387 params.serverAddr = inet4AddressToIntHTH((Inet4Address) serverAddr.getAddress()); 388 params.serverAddrPrefixLength = serverAddr.getPrefixLength(); 389 params.defaultRouters = toIntArray(defaultRouters); 390 params.dnsServers = toIntArray(dnsServers); 391 params.excludedAddrs = toIntArray(excludedAddrs); 392 params.dhcpLeaseTimeSecs = TEST_LEASE_EXPTIME_SECS; 393 params.linkMtu = TEST_MTU; 394 params.metered = true; 395 params.changePrefixOnDecline = changePrefixOnDecline; 396 397 mServer.updateParams(params, mAssertSuccessCallback); 398 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 399 } 400 401 @Test testChangePrefixOnDecline()402 public void testChangePrefixOnDecline() throws Exception { 403 when(mRepository.markAndReleaseDeclinedLease(isNull(), eq(TEST_CLIENT_MAC), 404 eq(TEST_CLIENT_ADDR))).thenReturn(true); 405 406 mServer.start(mAssertSuccessCallback, mEventCallbacks); 407 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 408 verify(mRepository).addLeaseCallbacks(eq(mEventCallbacks)); 409 410 // Enable changePrefixOnDecline 411 updateServingParams(TEST_DEFAULT_ROUTERS, TEST_DNS_SERVERS, TEST_EXCLUDED_ADDRS, 412 TEST_SERVER_LINKADDR, true /* changePrefixOnDecline */); 413 414 runOnReceivedDeclinePacket(); 415 final IpPrefix servingPrefix = DhcpServingParams.makeIpPrefix(TEST_SERVER_LINKADDR); 416 verify(mEventCallbacks).onNewPrefixRequest(eq(servingPrefix)); 417 418 final Inet4Address serverAddr = parseAddr("192.168.51.129"); 419 final LinkAddress srvLinkAddr = new LinkAddress(serverAddr, 24); 420 final Set<Inet4Address> srvAddr = new HashSet<>(Collections.singletonList(serverAddr)); 421 final Set<Inet4Address> excludedAddrs = new HashSet<>( 422 Arrays.asList(parseAddr("192.168.51.200"), parseAddr("192.168.51.201"))); 423 424 // Simulate IpServer updates the serving params with a new prefix. 425 updateServingParams(srvAddr, srvAddr, excludedAddrs, srvLinkAddr, 426 true /* changePrefixOnDecline */); 427 428 final Inet4Address clientAddr = parseAddr("192.168.51.42"); 429 final DhcpLease lease = new DhcpLease(null, TEST_CLIENT_MAC, 430 clientAddr, 24 /*prefixLen*/, TEST_LEASE_EXPTIME_SECS * 1000L + TEST_CLOCK_TIME, 431 null /* hostname */); 432 when(mRepository.getOffer(isNull() /* clientId */, eq(TEST_CLIENT_MAC), 433 eq(INADDR_ANY) /* relayAddr */, isNull() /* reqAddr */, isNull() /* hostname */)) 434 .thenReturn(lease); 435 436 // Test discover packet 437 final DhcpDiscoverPacket discover = new DhcpDiscoverPacket(TEST_TRANSACTION_ID, 438 (short) 0 /* secs */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES, 439 false /* broadcast */, INADDR_ANY /* srcIp */, false /* rapidCommit */); 440 mServer.sendMessage(CMD_RECEIVE_PACKET, discover); 441 HandlerUtils.waitForIdle(mServer.getHandler(), TEST_TIMEOUT_MS); 442 assertResponseSentTo(clientAddr); 443 final DhcpOfferPacket packet = assertOffer(getPacket()); 444 assertMatchesLease(packet, serverAddr, clientAddr, null); 445 } 446 447 /* TODO: add more tests once packet construction is refactored, including: 448 * - usage of giaddr 449 * - usage of broadcast bit 450 * - other request states (init-reboot/renewing/rebinding) 451 */ 452 assertMatchesLease(@onNull DhcpPacket packet, @NonNull Inet4Address srvAddr, @NonNull Inet4Address clientAddr, @Nullable String hostname)453 private void assertMatchesLease(@NonNull DhcpPacket packet, @NonNull Inet4Address srvAddr, 454 @NonNull Inet4Address clientAddr, @Nullable String hostname) { 455 assertMatchesClient(packet); 456 assertFalse(packet.hasExplicitClientId()); 457 assertEquals(srvAddr, packet.mServerIdentifier); 458 assertEquals(clientAddr, packet.mYourIp); 459 assertNotNull(packet.mLeaseTime); 460 assertEquals(TEST_LEASE_EXPTIME_SECS, (int) packet.mLeaseTime); 461 assertEquals(hostname, packet.mHostName); 462 } 463 assertMatchesTestLease(@onNull DhcpPacket packet, @Nullable String hostname)464 private void assertMatchesTestLease(@NonNull DhcpPacket packet, @Nullable String hostname) { 465 assertMatchesLease(packet, TEST_SERVER_ADDR, TEST_CLIENT_ADDR, hostname); 466 } 467 assertMatchesTestLease(@onNull DhcpPacket packet)468 private void assertMatchesTestLease(@NonNull DhcpPacket packet) { 469 assertMatchesTestLease(packet, null); 470 } 471 assertMatchesClient(@onNull DhcpPacket packet)472 private void assertMatchesClient(@NonNull DhcpPacket packet) { 473 assertEquals(TEST_TRANSACTION_ID, packet.mTransId); 474 assertEquals(TEST_CLIENT_MAC, MacAddress.fromBytes(packet.mClientMac)); 475 } 476 assertResponseSentTo(@onNull Inet4Address addr)477 private void assertResponseSentTo(@NonNull Inet4Address addr) { 478 assertEquals(addr, mResponseDstAddrCaptor.getValue()); 479 } 480 assertNak(@ullable DhcpPacket packet)481 private static DhcpNakPacket assertNak(@Nullable DhcpPacket packet) { 482 assertTrue(packet instanceof DhcpNakPacket); 483 return (DhcpNakPacket) packet; 484 } 485 assertAck(@ullable DhcpPacket packet)486 private static DhcpAckPacket assertAck(@Nullable DhcpPacket packet) { 487 assertTrue(packet instanceof DhcpAckPacket); 488 return (DhcpAckPacket) packet; 489 } 490 assertOffer(@ullable DhcpPacket packet)491 private static DhcpOfferPacket assertOffer(@Nullable DhcpPacket packet) { 492 assertTrue(packet instanceof DhcpOfferPacket); 493 return (DhcpOfferPacket) packet; 494 } 495 getPacket()496 private DhcpPacket getPacket() throws Exception { 497 verify(mDeps, times(1)).sendPacket(any(), any(), any()); 498 return DhcpPacket.decodeFullPacket(mSentPacketCaptor.getValue(), ENCAP_BOOTP, 499 new byte[0] /* optionsToSkip */); 500 } 501 parseAddr(@ullable String inet4Addr)502 private static Inet4Address parseAddr(@Nullable String inet4Addr) { 503 return (Inet4Address) parseNumericAddress(inet4Addr); 504 } 505 } 506