diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2015-06-02 07:47:46 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-06-02 07:47:48 +0000 |
commit | 8f602cdd38f7345eb0a8ec34ae4e51a333edce6c (patch) | |
tree | 9ea2de320f8b3981c13e55f7349e6574d0f1207d | |
parent | 168bfef182b8e631c93404f4e9e9c0176aa66ece (diff) | |
parent | d973537ee1bd013b4233d3369d66821e124a2e65 (diff) | |
download | frameworks_base-8f602cdd38f7345eb0a8ec34ae4e51a333edce6c.zip frameworks_base-8f602cdd38f7345eb0a8ec34ae4e51a333edce6c.tar.gz frameworks_base-8f602cdd38f7345eb0a8ec34ae4e51a333edce6c.tar.bz2 |
Merge "Fix DHCP lease time parsing." into mnc-dev
3 files changed, 103 insertions, 16 deletions
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java index 2692d71..b8c60ec 100644 --- a/services/net/java/android/net/dhcp/DhcpClient.java +++ b/services/net/java/android/net/dhcp/DhcpClient.java @@ -391,11 +391,15 @@ public class DhcpClient extends BaseDhcpStateMachine { } private void scheduleRenew() { - long now = SystemClock.elapsedRealtime(); - long alarmTime = (now + mDhcpLeaseExpiry) / 2; mAlarmManager.cancel(mRenewIntent); - mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mRenewIntent); - Log.d(TAG, "Scheduling renewal in " + ((alarmTime - now) / 1000) + "s"); + if (mDhcpLeaseExpiry != 0) { + long now = SystemClock.elapsedRealtime(); + long alarmTime = (now + mDhcpLeaseExpiry) / 2; + mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mRenewIntent); + Log.d(TAG, "Scheduling renewal in " + ((alarmTime - now) / 1000) + "s"); + } else { + Log.d(TAG, "Infinite lease, no renewal needed"); + } } private void notifyLease() { @@ -587,6 +591,12 @@ public class DhcpClient extends BaseDhcpStateMachine { return true; } + public void setDhcpLeaseExpiry(DhcpPacket packet) { + long leaseTimeMillis = packet.getLeaseTimeMillis(); + mDhcpLeaseExpiry = + (leaseTimeMillis > 0) ? SystemClock.elapsedRealtime() + leaseTimeMillis : 0; + } + /** * Retransmits packets using jittered exponential backoff with an optional timeout. Packet * transmission is triggered by CMD_KICK, which is sent by an AlarmManager alarm. @@ -724,10 +734,9 @@ public class DhcpClient extends BaseDhcpStateMachine { DhcpResults results = packet.toDhcpResults(); if (results != null) { mDhcpLease = results; - Log.d(TAG, "Confirmed lease: " + mDhcpLease); - mDhcpLeaseExpiry = SystemClock.elapsedRealtime() + - mDhcpLease.leaseDuration * 1000; mOffer = null; + Log.d(TAG, "Confirmed lease: " + mDhcpLease); + setDhcpLeaseExpiry(packet); transitionTo(mDhcpBoundState); } } else if (packet instanceof DhcpNakPacket) { @@ -799,10 +808,7 @@ public class DhcpClient extends BaseDhcpStateMachine { protected void receivePacket(DhcpPacket packet) { if (!isValidPacket(packet)) return; if ((packet instanceof DhcpAckPacket)) { - DhcpResults results = packet.toDhcpResults(); - mDhcpLease.leaseDuration = results.leaseDuration; - mDhcpLeaseExpiry = SystemClock.elapsedRealtime() + - mDhcpLease.leaseDuration * 1000; + setDhcpLeaseExpiry(packet); transitionTo(mDhcpBoundState); } else if (packet instanceof DhcpNakPacket) { transitionTo(mDhcpInitState); diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index b923b1b..2a25d30 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -28,6 +28,12 @@ import java.util.List; abstract class DhcpPacket { protected static final String TAG = "DhcpPacket"; + // dhcpcd has a minimum lease of 20 seconds, but DhcpStateMachine would refuse to wake up the + // CPU for anything shorter than 5 minutes. For sanity's sake, this must be higher than the + // DHCP client timeout. + public static final int MINIMUM_LEASE = 60; + public static final int INFINITE_LEASE = (int) 0xffffffff; + public static final Inet4Address INADDR_ANY = (Inet4Address) Inet4Address.ANY; public static final Inet4Address INADDR_BROADCAST = (Inet4Address) Inet4Address.ALL; public static final byte[] ETHER_BROADCAST = new byte[] { @@ -1006,11 +1012,25 @@ abstract class DhcpPacket { results.domains = mDomainName; results.serverAddress = mServerIdentifier; results.vendorInfo = mVendorId; - results.leaseDuration = mLeaseTime; + results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE; return results; } /** + * Returns the parsed lease time, in milliseconds, or 0 for infinite. + */ + public long getLeaseTimeMillis() { + // dhcpcd treats the lack of a lease time option as an infinite lease. + if (mLeaseTime == null || mLeaseTime == INFINITE_LEASE) { + return 0; + } else if (0 <= mLeaseTime && mLeaseTime < MINIMUM_LEASE) { + return MINIMUM_LEASE * 1000; + } else { + return (mLeaseTime & 0xffffffffL) * 1000; + } + } + + /** * Builds a DHCP-DISCOVER packet from the required specified * parameters. */ diff --git a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java index 4f7c7ec..f116042 100644 --- a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java +++ b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java @@ -17,6 +17,7 @@ package android.net.dhcp; import android.net.NetworkUtils; +import android.net.DhcpResults; import android.system.OsConstants; import android.test.suitebuilder.annotation.SmallTest; import junit.framework.TestCase; @@ -38,14 +39,27 @@ public class DhcpPacketTest extends TestCase { class TestDhcpPacket extends DhcpPacket { private byte mType; // TODO: Make this a map of option numbers to bytes instead. - private byte[] mDomainBytes, mVendorInfoBytes; + private byte[] mDomainBytes, mVendorInfoBytes, mLeaseTimeBytes; - public TestDhcpPacket(byte type, byte[] domainBytes, byte[] vendorInfoBytes) { + public TestDhcpPacket(byte type) { super(0xdeadbeef, (short) 0, INADDR_ANY, CLIENT_ADDR, INADDR_ANY, INADDR_ANY, CLIENT_MAC, true); mType = type; + } + + public TestDhcpPacket setDomainBytes(byte[] domainBytes) { mDomainBytes = domainBytes; + return this; + } + + public TestDhcpPacket setVendorInfoBytes(byte[] vendorInfoBytes) { mVendorInfoBytes = vendorInfoBytes; + return this; + } + + public TestDhcpPacket setLeaseTimeBytes(byte[] leaseTimeBytes) { + mLeaseTimeBytes = leaseTimeBytes; + return this; } public ByteBuffer buildPacket(int encap, short unusedDestUdp, short unusedSrcUdp) { @@ -63,6 +77,9 @@ public class DhcpPacketTest extends TestCase { if (mVendorInfoBytes != null) { addTlv(buffer, DHCP_VENDOR_CLASS_ID, mVendorInfoBytes); } + if (mLeaseTimeBytes != null) { + addTlv(buffer, DHCP_LEASE_TIME, mLeaseTimeBytes); + } addTlvEnd(buffer); } @@ -78,8 +95,10 @@ public class DhcpPacketTest extends TestCase { private void assertDomainAndVendorInfoParses( String expectedDomain, byte[] domainBytes, String expectedVendorInfo, byte[] vendorInfoBytes) { - ByteBuffer packet = new TestDhcpPacket(DHCP_MESSAGE_TYPE_OFFER, - domainBytes, vendorInfoBytes).build(); + ByteBuffer packet = new TestDhcpPacket(DHCP_MESSAGE_TYPE_OFFER) + .setDomainBytes(domainBytes) + .setVendorInfoBytes(vendorInfoBytes) + .build(); DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_BOOTP); assertEquals(expectedDomain, offerPacket.mDomainName); assertEquals(expectedVendorInfo, offerPacket.mVendorId); @@ -114,4 +133,46 @@ public class DhcpPacketTest extends TestCase { assertDomainAndVendorInfoParses("goo.gl", trailingNullDomain, "ANDROID_METERE\u0000", meteredTrailingNull); } + + private void assertLeaseTimeParses(boolean expectValid, Integer rawLeaseTime, + long leaseTimeMillis, byte[] leaseTimeBytes) { + TestDhcpPacket testPacket = new TestDhcpPacket(DHCP_MESSAGE_TYPE_OFFER); + if (leaseTimeBytes != null) { + testPacket.setLeaseTimeBytes(leaseTimeBytes); + } + ByteBuffer packet = testPacket.build(); + DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_BOOTP); + if (!expectValid) { + assertNull(offerPacket); + return; + } + assertEquals(rawLeaseTime, offerPacket.mLeaseTime); + DhcpResults dhcpResults = offerPacket.toDhcpResults(); // Just check this doesn't crash. + assertEquals(leaseTimeMillis, offerPacket.getLeaseTimeMillis()); + } + + @SmallTest + public void testLeaseTime() throws Exception { + byte[] noLease = null; + byte[] tooShortLease = new byte[] { 0x00, 0x00 }; + byte[] tooLongLease = new byte[] { 0x00, 0x00, 0x00, 60, 0x01 }; + byte[] zeroLease = new byte[] { 0x00, 0x00, 0x00, 0x00 }; + byte[] tenSecondLease = new byte[] { 0x00, 0x00, 0x00, 10 }; + byte[] oneMinuteLease = new byte[] { 0x00, 0x00, 0x00, 60 }; + byte[] fiveMinuteLease = new byte[] { 0x00, 0x00, 0x01, 0x2c }; + byte[] oneDayLease = new byte[] { 0x00, 0x01, 0x51, (byte) 0x80 }; + byte[] maxIntPlusOneLease = new byte[] { (byte) 0x80, 0x00, 0x00, 0x01 }; + byte[] infiniteLease = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }; + + assertLeaseTimeParses(true, null, 0, noLease); + assertLeaseTimeParses(false, null, 0, tooShortLease); + assertLeaseTimeParses(false, null, 0, tooLongLease); + assertLeaseTimeParses(true, 0, 60 * 1000, zeroLease); + assertLeaseTimeParses(true, 10, 60 * 1000, tenSecondLease); + assertLeaseTimeParses(true, 60, 60 * 1000, oneMinuteLease); + assertLeaseTimeParses(true, 300, 300 * 1000, fiveMinuteLease); + assertLeaseTimeParses(true, 86400, 86400 * 1000, oneDayLease); + assertLeaseTimeParses(true, -2147483647, 2147483649L * 1000, maxIntPlusOneLease); + assertLeaseTimeParses(true, DhcpPacket.INFINITE_LEASE, 0, infiniteLease); + } } |